diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.pbxproj b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.pbxproj new file mode 100644 index 00000000..28c16230 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.pbxproj @@ -0,0 +1,753 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 39A2F20E28D9B2C400DDCAF2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F20D28D9B2C400DDCAF2 /* AppDelegate.m */; }; + 39A2F21428D9B2C400DDCAF2 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F21328D9B2C400DDCAF2 /* ViewController.m */; }; + 39A2F21728D9B2C400DDCAF2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 39A2F21528D9B2C400DDCAF2 /* Main.storyboard */; }; + 39A2F21928D9B2C500DDCAF2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 39A2F21828D9B2C500DDCAF2 /* Assets.xcassets */; }; + 39A2F21C28D9B2C500DDCAF2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 39A2F21A28D9B2C500DDCAF2 /* LaunchScreen.storyboard */; }; + 39A2F21F28D9B2C500DDCAF2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F21E28D9B2C500DDCAF2 /* main.m */; }; + 39A2F22928D9B2C600DDCAF2 /* IMUIKitOCExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F22828D9B2C600DDCAF2 /* IMUIKitOCExampleTests.m */; }; + 39A2F23328D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F23228D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.m */; }; + 39A2F23528D9B2C600DDCAF2 /* IMUIKitOCExampleUITestsLaunchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F23428D9B2C600DDCAF2 /* IMUIKitOCExampleUITestsLaunchTests.m */; }; + 39A2F24728DABC1700DDCAF2 /* NETabbarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F24628DABC1700DDCAF2 /* NETabbarController.m */; }; + 39A2F24B28DABC6700DDCAF2 /* NENavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 39A2F24A28DABC6700DDCAF2 /* NENavigationController.m */; }; + 39EBBACA1D04C27BC1E3AEC9 /* Pods_IMUIKitOCExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F8E39DDEB8C36F0E96A1333 /* Pods_IMUIKitOCExample.framework */; }; + 39ED7B1E290FA9C700CAE608 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 39ED7B20290FA9C700CAE608 /* Localizable.strings */; }; + DD774A7729485F6600347A9E /* CustomRouterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD774A7629485F6600347A9E /* CustomRouterViewController.m */; }; + DDC1AC8929651B6C008C085A /* ConversationController+Test.m in Sources */ = {isa = PBXBuildFile; fileRef = DDC1AC8829651B6C008C085A /* ConversationController+Test.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 39A2F22528D9B2C600DDCAF2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 39A2F20128D9B2C400DDCAF2 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 39A2F20828D9B2C400DDCAF2; + remoteInfo = IMUIKitOCExample; + }; + 39A2F22F28D9B2C600DDCAF2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 39A2F20128D9B2C400DDCAF2 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 39A2F20828D9B2C400DDCAF2; + remoteInfo = IMUIKitOCExample; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 147F8282453DD1C889BE79CA /* Pods-IMUIKitOCExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IMUIKitOCExample.release.xcconfig"; path = "Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample.release.xcconfig"; sourceTree = ""; }; + 39A2F20928D9B2C400DDCAF2 /* IMUIKitOCExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IMUIKitOCExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 39A2F20C28D9B2C400DDCAF2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 39A2F20D28D9B2C400DDCAF2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 39A2F21228D9B2C400DDCAF2 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 39A2F21328D9B2C400DDCAF2 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 39A2F21628D9B2C400DDCAF2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 39A2F21828D9B2C500DDCAF2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 39A2F21B28D9B2C500DDCAF2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 39A2F21D28D9B2C500DDCAF2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 39A2F21E28D9B2C500DDCAF2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 39A2F22428D9B2C600DDCAF2 /* IMUIKitOCExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IMUIKitOCExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 39A2F22828D9B2C600DDCAF2 /* IMUIKitOCExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IMUIKitOCExampleTests.m; sourceTree = ""; }; + 39A2F22E28D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IMUIKitOCExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 39A2F23228D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IMUIKitOCExampleUITests.m; sourceTree = ""; }; + 39A2F23428D9B2C600DDCAF2 /* IMUIKitOCExampleUITestsLaunchTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IMUIKitOCExampleUITestsLaunchTests.m; sourceTree = ""; }; + 39A2F24428DAAC1500DDCAF2 /* AppKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppKey.h; sourceTree = ""; }; + 39A2F24528DABC1700DDCAF2 /* NETabbarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NETabbarController.h; sourceTree = ""; }; + 39A2F24628DABC1700DDCAF2 /* NETabbarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NETabbarController.m; sourceTree = ""; }; + 39A2F24928DABC6700DDCAF2 /* NENavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NENavigationController.h; sourceTree = ""; }; + 39A2F24A28DABC6700DDCAF2 /* NENavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NENavigationController.m; sourceTree = ""; }; + 39ED7B1F290FA9C700CAE608 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 39ED7B24290FAA6E00CAE608 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + 39ED7B25290FAA6E00CAE608 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; + 39ED7B26290FAA6E00CAE608 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 9F8E39DDEB8C36F0E96A1333 /* Pods_IMUIKitOCExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IMUIKitOCExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DD774A7529485F6600347A9E /* CustomRouterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomRouterViewController.h; sourceTree = ""; }; + DD774A7629485F6600347A9E /* CustomRouterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomRouterViewController.m; sourceTree = ""; }; + DDC1AC8729651B6C008C085A /* ConversationController+Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ConversationController+Test.h"; sourceTree = ""; }; + DDC1AC8829651B6C008C085A /* ConversationController+Test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ConversationController+Test.m"; sourceTree = ""; }; + DDF443AC294851D90077184F /* IMUIKitOCExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IMUIKitOCExample-Bridging-Header.h"; sourceTree = ""; }; + F984299B79B347145EA4AF84 /* Pods-IMUIKitOCExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IMUIKitOCExample.debug.xcconfig"; path = "Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 39A2F20628D9B2C400DDCAF2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 39EBBACA1D04C27BC1E3AEC9 /* Pods_IMUIKitOCExample.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39A2F22128D9B2C600DDCAF2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39A2F22B28D9B2C600DDCAF2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0BEF3C37E3BB9E3AE318BAB8 /* Pods */ = { + isa = PBXGroup; + children = ( + F984299B79B347145EA4AF84 /* Pods-IMUIKitOCExample.debug.xcconfig */, + 147F8282453DD1C889BE79CA /* Pods-IMUIKitOCExample.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 39A2F20028D9B2C400DDCAF2 = { + isa = PBXGroup; + children = ( + 39A2F20B28D9B2C400DDCAF2 /* IMUIKitOCExample */, + 39A2F22728D9B2C600DDCAF2 /* IMUIKitOCExampleTests */, + 39A2F23128D9B2C600DDCAF2 /* IMUIKitOCExampleUITests */, + 39A2F20A28D9B2C400DDCAF2 /* Products */, + 0BEF3C37E3BB9E3AE318BAB8 /* Pods */, + 6B7A97EA6BE0B274CD63D9AC /* Frameworks */, + ); + sourceTree = ""; + }; + 39A2F20A28D9B2C400DDCAF2 /* Products */ = { + isa = PBXGroup; + children = ( + 39A2F20928D9B2C400DDCAF2 /* IMUIKitOCExample.app */, + 39A2F22428D9B2C600DDCAF2 /* IMUIKitOCExampleTests.xctest */, + 39A2F22E28D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 39A2F20B28D9B2C400DDCAF2 /* IMUIKitOCExample */ = { + isa = PBXGroup; + children = ( + 39A2F24828DABC2B00DDCAF2 /* Main */, + 39A2F24428DAAC1500DDCAF2 /* AppKey.h */, + 39A2F21528D9B2C400DDCAF2 /* Main.storyboard */, + 39A2F21828D9B2C500DDCAF2 /* Assets.xcassets */, + 39A2F21A28D9B2C500DDCAF2 /* LaunchScreen.storyboard */, + 39A2F21D28D9B2C500DDCAF2 /* Info.plist */, + 39A2F21E28D9B2C500DDCAF2 /* main.m */, + ); + path = IMUIKitOCExample; + sourceTree = ""; + }; + 39A2F22728D9B2C600DDCAF2 /* IMUIKitOCExampleTests */ = { + isa = PBXGroup; + children = ( + 39A2F22828D9B2C600DDCAF2 /* IMUIKitOCExampleTests.m */, + ); + path = IMUIKitOCExampleTests; + sourceTree = ""; + }; + 39A2F23128D9B2C600DDCAF2 /* IMUIKitOCExampleUITests */ = { + isa = PBXGroup; + children = ( + 39A2F23228D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.m */, + 39A2F23428D9B2C600DDCAF2 /* IMUIKitOCExampleUITestsLaunchTests.m */, + ); + path = IMUIKitOCExampleUITests; + sourceTree = ""; + }; + 39A2F24828DABC2B00DDCAF2 /* Main */ = { + isa = PBXGroup; + children = ( + 39A2F20C28D9B2C400DDCAF2 /* AppDelegate.h */, + 39A2F20D28D9B2C400DDCAF2 /* AppDelegate.m */, + 39A2F24528DABC1700DDCAF2 /* NETabbarController.h */, + 39A2F24628DABC1700DDCAF2 /* NETabbarController.m */, + 39A2F24928DABC6700DDCAF2 /* NENavigationController.h */, + 39A2F24A28DABC6700DDCAF2 /* NENavigationController.m */, + 39A2F21228D9B2C400DDCAF2 /* ViewController.h */, + 39A2F21328D9B2C400DDCAF2 /* ViewController.m */, + DD774A7529485F6600347A9E /* CustomRouterViewController.h */, + DD774A7629485F6600347A9E /* CustomRouterViewController.m */, + DDC1AC8729651B6C008C085A /* ConversationController+Test.h */, + DDC1AC8829651B6C008C085A /* ConversationController+Test.m */, + 39ED7B20290FA9C700CAE608 /* Localizable.strings */, + DDF443AC294851D90077184F /* IMUIKitOCExample-Bridging-Header.h */, + ); + path = Main; + sourceTree = ""; + }; + 6B7A97EA6BE0B274CD63D9AC /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9F8E39DDEB8C36F0E96A1333 /* Pods_IMUIKitOCExample.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 39A2F20828D9B2C400DDCAF2 /* IMUIKitOCExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 39A2F23828D9B2C600DDCAF2 /* Build configuration list for PBXNativeTarget "IMUIKitOCExample" */; + buildPhases = ( + CDCC4CE4D4082A1DA0D5A888 /* [CP] Check Pods Manifest.lock */, + 39A2F20528D9B2C400DDCAF2 /* Sources */, + 39A2F20628D9B2C400DDCAF2 /* Frameworks */, + 39A2F20728D9B2C400DDCAF2 /* Resources */, + DB787379DE2DF44860C11CF1 /* [CP] Embed Pods Frameworks */, + 8F14E37FD20AEF03EA4142FE /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = IMUIKitOCExample; + productName = IMUIKitOCExample; + productReference = 39A2F20928D9B2C400DDCAF2 /* IMUIKitOCExample.app */; + productType = "com.apple.product-type.application"; + }; + 39A2F22328D9B2C600DDCAF2 /* IMUIKitOCExampleTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 39A2F23B28D9B2C600DDCAF2 /* Build configuration list for PBXNativeTarget "IMUIKitOCExampleTests" */; + buildPhases = ( + 39A2F22028D9B2C600DDCAF2 /* Sources */, + 39A2F22128D9B2C600DDCAF2 /* Frameworks */, + 39A2F22228D9B2C600DDCAF2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 39A2F22628D9B2C600DDCAF2 /* PBXTargetDependency */, + ); + name = IMUIKitOCExampleTests; + productName = IMUIKitOCExampleTests; + productReference = 39A2F22428D9B2C600DDCAF2 /* IMUIKitOCExampleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 39A2F22D28D9B2C600DDCAF2 /* IMUIKitOCExampleUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 39A2F23E28D9B2C600DDCAF2 /* Build configuration list for PBXNativeTarget "IMUIKitOCExampleUITests" */; + buildPhases = ( + 39A2F22A28D9B2C600DDCAF2 /* Sources */, + 39A2F22B28D9B2C600DDCAF2 /* Frameworks */, + 39A2F22C28D9B2C600DDCAF2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 39A2F23028D9B2C600DDCAF2 /* PBXTargetDependency */, + ); + name = IMUIKitOCExampleUITests; + productName = IMUIKitOCExampleUITests; + productReference = 39A2F22E28D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 39A2F20128D9B2C400DDCAF2 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1330; + TargetAttributes = { + 39A2F20828D9B2C400DDCAF2 = { + CreatedOnToolsVersion = 13.3.1; + LastSwiftMigration = 1410; + }; + 39A2F22328D9B2C600DDCAF2 = { + CreatedOnToolsVersion = 13.3.1; + TestTargetID = 39A2F20828D9B2C400DDCAF2; + }; + 39A2F22D28D9B2C600DDCAF2 = { + CreatedOnToolsVersion = 13.3.1; + TestTargetID = 39A2F20828D9B2C400DDCAF2; + }; + }; + }; + buildConfigurationList = 39A2F20428D9B2C400DDCAF2 /* Build configuration list for PBXProject "IMUIKitOCExample" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + "zh-Hans", + ); + mainGroup = 39A2F20028D9B2C400DDCAF2; + productRefGroup = 39A2F20A28D9B2C400DDCAF2 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 39A2F20828D9B2C400DDCAF2 /* IMUIKitOCExample */, + 39A2F22328D9B2C600DDCAF2 /* IMUIKitOCExampleTests */, + 39A2F22D28D9B2C600DDCAF2 /* IMUIKitOCExampleUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 39A2F20728D9B2C400DDCAF2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 39A2F21C28D9B2C500DDCAF2 /* LaunchScreen.storyboard in Resources */, + 39ED7B1E290FA9C700CAE608 /* Localizable.strings in Resources */, + 39A2F21928D9B2C500DDCAF2 /* Assets.xcassets in Resources */, + 39A2F21728D9B2C400DDCAF2 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39A2F22228D9B2C600DDCAF2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39A2F22C28D9B2C600DDCAF2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8F14E37FD20AEF03EA4142FE /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + CDCC4CE4D4082A1DA0D5A888 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-IMUIKitOCExample-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + DB787379DE2DF44860C11CF1 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-IMUIKitOCExample/Pods-IMUIKitOCExample-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 39A2F20528D9B2C400DDCAF2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 39A2F21428D9B2C400DDCAF2 /* ViewController.m in Sources */, + 39A2F20E28D9B2C400DDCAF2 /* AppDelegate.m in Sources */, + DDC1AC8929651B6C008C085A /* ConversationController+Test.m in Sources */, + 39A2F24B28DABC6700DDCAF2 /* NENavigationController.m in Sources */, + 39A2F24728DABC1700DDCAF2 /* NETabbarController.m in Sources */, + 39A2F21F28D9B2C500DDCAF2 /* main.m in Sources */, + DD774A7729485F6600347A9E /* CustomRouterViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39A2F22028D9B2C600DDCAF2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 39A2F22928D9B2C600DDCAF2 /* IMUIKitOCExampleTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39A2F22A28D9B2C600DDCAF2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 39A2F23528D9B2C600DDCAF2 /* IMUIKitOCExampleUITestsLaunchTests.m in Sources */, + 39A2F23328D9B2C600DDCAF2 /* IMUIKitOCExampleUITests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 39A2F22628D9B2C600DDCAF2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 39A2F20828D9B2C400DDCAF2 /* IMUIKitOCExample */; + targetProxy = 39A2F22528D9B2C600DDCAF2 /* PBXContainerItemProxy */; + }; + 39A2F23028D9B2C600DDCAF2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 39A2F20828D9B2C400DDCAF2 /* IMUIKitOCExample */; + targetProxy = 39A2F22F28D9B2C600DDCAF2 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 39A2F21528D9B2C400DDCAF2 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 39A2F21628D9B2C400DDCAF2 /* Base */, + 39ED7B24290FAA6E00CAE608 /* zh-Hans */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 39A2F21A28D9B2C500DDCAF2 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 39A2F21B28D9B2C500DDCAF2 /* Base */, + 39ED7B25290FAA6E00CAE608 /* zh-Hans */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + 39ED7B20290FA9C700CAE608 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 39ED7B1F290FA9C700CAE608 /* en */, + 39ED7B26290FAA6E00CAE608 /* zh-Hans */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 39A2F23628D9B2C600DDCAF2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 39A2F23728D9B2C600DDCAF2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 39A2F23928D9B2C600DDCAF2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F984299B79B347145EA4AF84 /* Pods-IMUIKitOCExample.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 569GNZ5392; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = IMUIKitOCExample/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "云信IM OC"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 9.2.9; + PRODUCT_BUNDLE_IDENTIFIER = com.netease.yunxin.app.im; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "IMUIKitOCExample/Main/IMUIKitOCExample-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 39A2F23A28D9B2C600DDCAF2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 147F8282453DD1C889BE79CA /* Pods-IMUIKitOCExample.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 569GNZ5392; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = IMUIKitOCExample/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "云信IM OC"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 9.2.9; + PRODUCT_BUNDLE_IDENTIFIER = com.netease.yunxin.app.im; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "IMUIKitOCExample/Main/IMUIKitOCExample-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; + 39A2F23C28D9B2C600DDCAF2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.yunbite.cn.IMUIKitOCExampleTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IMUIKitOCExample.app/IMUIKitOCExample"; + }; + name = Debug; + }; + 39A2F23D28D9B2C600DDCAF2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.yunbite.cn.IMUIKitOCExampleTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/IMUIKitOCExample.app/IMUIKitOCExample"; + }; + name = Release; + }; + 39A2F23F28D9B2C600DDCAF2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.yunbite.cn.IMUIKitOCExampleUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = IMUIKitOCExample; + }; + name = Debug; + }; + 39A2F24028D9B2C600DDCAF2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.yunbite.cn.IMUIKitOCExampleUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = IMUIKitOCExample; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 39A2F20428D9B2C400DDCAF2 /* Build configuration list for PBXProject "IMUIKitOCExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 39A2F23628D9B2C600DDCAF2 /* Debug */, + 39A2F23728D9B2C600DDCAF2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 39A2F23828D9B2C600DDCAF2 /* Build configuration list for PBXNativeTarget "IMUIKitOCExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 39A2F23928D9B2C600DDCAF2 /* Debug */, + 39A2F23A28D9B2C600DDCAF2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 39A2F23B28D9B2C600DDCAF2 /* Build configuration list for PBXNativeTarget "IMUIKitOCExampleTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 39A2F23C28D9B2C600DDCAF2 /* Debug */, + 39A2F23D28D9B2C600DDCAF2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 39A2F23E28D9B2C600DDCAF2 /* Build configuration list for PBXNativeTarget "IMUIKitOCExampleUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 39A2F23F28D9B2C600DDCAF2 /* Debug */, + 39A2F24028D9B2C600DDCAF2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 39A2F20128D9B2C400DDCAF2 /* Project object */; +} diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcworkspace/contents.xcworkspacedata b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..8be4f694 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatCornerCell.swift b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/AppKey.h similarity index 58% rename from NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatCornerCell.swift rename to IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/AppKey.h index a83319a7..5e105323 100644 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatCornerCell.swift +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/AppKey.h @@ -3,8 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -// this cell has rounding corner style -import UIKit -import NECommonUIKit +#ifndef AppKey_h +#define AppKey_h -class QChatCornerCell: CornerCell {} +/// IM key +static NSString *const AppKey = @""; + +#endif /* AppKey_h */ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 51% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Contents.json rename to IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AccentColor.colorset/Contents.json index 73c00596..eb878970 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Contents.json +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AccentColor.colorset/Contents.json @@ -1,4 +1,9 @@ { + "colors" : [ + { + "idiom" : "universal" + } + ], "info" : { "author" : "xcode", "version" : 1 diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/1024x1024.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/1024x1024.png new file mode 100644 index 00000000..dbc0b4f6 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/1024x1024.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/120x120-1.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/120x120-1.png new file mode 100644 index 00000000..8b59b70e Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/120x120-1.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/120x120.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/120x120.png new file mode 100644 index 00000000..8b59b70e Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/120x120.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/152x152.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/152x152.png new file mode 100644 index 00000000..b2e438b3 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/152x152.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/167x167.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/167x167.png new file mode 100644 index 00000000..32480439 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/167x167.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/180x180.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/180x180.png new file mode 100644 index 00000000..ac60d3d9 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/180x180.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/20x20.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/20x20.png new file mode 100644 index 00000000..5280c6b3 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/20x20.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/29x29.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/29x29.png new file mode 100644 index 00000000..66c90c25 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/29x29.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40-1.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40-1.png new file mode 100644 index 00000000..b3cff5b7 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40-1.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40-2.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40-2.png new file mode 100644 index 00000000..b3cff5b7 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40-2.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40.png new file mode 100644 index 00000000..b3cff5b7 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/40x40.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/58x58-1.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/58x58-1.png new file mode 100644 index 00000000..ff5a7ba2 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/58x58-1.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/58x58.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/58x58.png new file mode 100644 index 00000000..ff5a7ba2 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/58x58.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/60x60.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/60x60.png new file mode 100644 index 00000000..64b84619 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/60x60.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/76x76.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/76x76.png new file mode 100644 index 00000000..f9b9b798 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/76x76.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/80x80-1.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/80x80-1.png new file mode 100644 index 00000000..ec7963dd Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/80x80-1.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/80x80.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/80x80.png new file mode 100644 index 00000000..ec7963dd Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/80x80.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/87x87.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/87x87.png new file mode 100644 index 00000000..faaf1df4 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/87x87.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..b51241aa --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "filename" : "40x40.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "60x60.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "58x58.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "87x87.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "80x80.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "120x120.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "120x120-1.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "180x180.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "20x20.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "40x40-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "29x29.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "58x58-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "40x40-2.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "80x80-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "76x76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "152x152.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "167x167.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "1024x1024.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/Contents.json similarity index 100% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/Contents.json rename to IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/Contents.json diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/Contents.json similarity index 79% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/Contents.json rename to IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/Contents.json index 79099b29..65f4223d 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/Contents.json +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "back@2x.png", + "filename" : "chat@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "back@3x.png", + "filename" : "chat@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/chat@2x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/chat@2x.png new file mode 100644 index 00000000..93d859e8 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/chat@2x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/chat@3x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/chat@3x.png new file mode 100644 index 00000000..ec90f787 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chat.imageset/chat@3x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/Contents.json new file mode 100644 index 00000000..48d1c275 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatSelect@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "chatSelect@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/chatSelect@2x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/chatSelect@2x.png new file mode 100644 index 00000000..3b8343cb Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/chatSelect@2x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/chatSelect@3x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/chatSelect@3x.png new file mode 100644 index 00000000..24e35746 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/chatSelect.imageset/chatSelect@3x.png differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/Contents.json similarity index 78% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Contents.json rename to IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/Contents.json index 4bdf5bae..38184864 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Contents.json +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x-1.png", + "filename" : "contact@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x-1.png", + "filename" : "contact@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/contact@2x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/contact@2x.png new file mode 100644 index 00000000..36db1478 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/contact@2x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/contact@3x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/contact@3x.png new file mode 100644 index 00000000..60d7a0b2 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contact.imageset/contact@3x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/Contents.json new file mode 100644 index 00000000..e3ce2a6c --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "contactSelect@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "contactSelect@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/contactSelect@2x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/contactSelect@2x.png new file mode 100644 index 00000000..d173a1e5 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/contactSelect@2x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/contactSelect@3x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/contactSelect@3x.png new file mode 100644 index 00000000..c9ab56e2 Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/contactSelect.imageset/contactSelect@3x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/Contents.json b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/Contents.json new file mode 100644 index 00000000..1b35333a --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "qchat_tabbar_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "qchat_tabbar_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/qchat_tabbar_icon@2x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/qchat_tabbar_icon@2x.png new file mode 100644 index 00000000..0f38526a Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/qchat_tabbar_icon@2x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/qchat_tabbar_icon@3x.png b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/qchat_tabbar_icon@3x.png new file mode 100644 index 00000000..5838a2ec Binary files /dev/null and b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Assets.xcassets/qchat_tabbar_icon.imageset/qchat_tabbar_icon@3x.png differ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Base.lproj/LaunchScreen.storyboard b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Base.lproj/Main.storyboard b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Base.lproj/Main.storyboard new file mode 100644 index 00000000..808a21ce --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Info.plist b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Info.plist new file mode 100644 index 00000000..81ed29b7 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Info.plist @@ -0,0 +1,25 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + SceneDelegate + UISceneStoryboardFile + Main + + + + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/AppDelegate.h b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/AppDelegate.h new file mode 100644 index 00000000..fa0a737e --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/AppDelegate.h @@ -0,0 +1,11 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +@interface AppDelegate : UIResponder + +@property(nonatomic, strong) UIWindow *window; +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/AppDelegate.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/AppDelegate.m new file mode 100644 index 00000000..5b3feeaa --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/AppDelegate.m @@ -0,0 +1,132 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "AppDelegate.h" +#import +#import "AppKey.h" +#import "NETabbarController.h" + +#import +#import +#import +#import +#import +#import +#import "CustomRouterViewController.h" + +@import NIMSDK; + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [self setupInit]; + return YES; +} + +- (void)setupInit { + // 初始化NIMSDK + NIMSDKOption *option = [NIMSDKOption optionWithAppKey:AppKey]; + [[IMKitClient instance] setupCoreKitIM:option]; + + // 统一登录组件 + YXConfig *config = [[YXConfig alloc] init]; + config.appKey = AppKey; + config.parentScope = @2; + config.scope = @7; + config.supportInternationalize = false; + config.type = YXLoginPhone; + +#ifdef DEBUG + config.isOnline = NO; +#else + config.isOnline = YES; +#endif + [[AuthorManager shareInstance] initAuthorWithConfig:config]; + if ([AuthorManager shareInstance].canAutologin) { + [[AuthorManager shareInstance] + autoLoginWithCompletion:^(YXUserInfo *_Nullable userinfo, NSError *_Nullable error) { + if (error) { + NSLog(@"auto login failed,error = %@", error); + } else { + [self setupXKit:userinfo]; + } + }]; + } else { + [self loginWithUI]; + } +} + +- (void)loginWithUI { + [[AuthorManager shareInstance] + startLoginWithCompletion:^(YXUserInfo *_Nullable userinfo, NSError *_Nullable error) { + if (!error) { + [self setupXKit:userinfo]; + } else { + NSLog(@"login failed,error = %@", error); + } + }]; +} + +- (void)setupXKit:(YXUserInfo *)user { + // 登录云信IM + if (user.imToken && user.imAccid) { + [[IMKitClient instance] loginIM:user.imAccid :user.imToken :^(NSError * _Nullable error) { + if (!error) { + [ChatRouter setupInit]; + //登录圈组模块,如不需要圈组功能则不用登录 + QChatLoginParam *parama = [[QChatLoginParam alloc]init:user.imAccid :user.imToken]; + [[IMKitClient instance] loginQchat:parama completion:^(NSError * _Nullable error, QChatLoginResult * _Nullable result) { + if (!error) { + [self setupTabbar]; + }else { + NSLog(@"qchat login failed,error = %@",error); + } + }]; + + }else { + NSLog(@"loginIM failed,error = %@",error); + } + }]; + } else { + NSLog(@"parameter is nil"); + } +} + +- (void)setupTabbar { + self.window.backgroundColor = [UIColor whiteColor]; + self.window.rootViewController = [[NETabbarController alloc] init]; + [self registerRouter]; +} + +// 注册路由 +- (void)registerRouter { + [ChatRouter register]; + [ConversationRouter register]; + [ContactRouter register]; + + [[Router shared] register:@"imkit://chat/p2pChat.page" + closure:^(NSDictionary *_Nonnull param) { + NSObject *param1 = [param objectForKey:@"nav"]; + if ([param1 isKindOfClass:[UINavigationController class]]) { + UINavigationController *nav = (UINavigationController *)param1; + CustomRouterViewController *controller = + [[CustomRouterViewController alloc] init]; + + [nav pushViewController:controller animated:YES]; + } + }]; +} + +- (UIInterfaceOrientationMask)application:(UIApplication *)application + supportedInterfaceOrientationsForWindow:(UIWindow *)window { + return UIInterfaceOrientationMaskPortrait; +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ConversationController+Test.h b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ConversationController+Test.h new file mode 100644 index 00000000..e08e9af8 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ConversationController+Test.h @@ -0,0 +1,14 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. +#import +#import +#import "IMUIKitOCExample-Bridging-Header.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ConversationController (Test) + +@end + +NS_ASSUME_NONNULL_END diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ConversationController+Test.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ConversationController+Test.m new file mode 100644 index 00000000..ccd0b372 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ConversationController+Test.m @@ -0,0 +1,20 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import "ConversationController+Test.h" + +@implementation ConversationController (Test) + ++ (void)initialize { + Method originalMethod = class_getInstanceMethod(self, @selector(viewDidLoad)); + Method swizzledMethod = class_getInstanceMethod(self, @selector(test_viewDidLoad)); + method_exchangeImplementations(originalMethod, swizzledMethod); +} + +- (void)test_viewDidLoad { + [self test_viewDidLoad]; +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/CustomRouterViewController.h b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/CustomRouterViewController.h new file mode 100644 index 00000000..a2ad9efe --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/CustomRouterViewController.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface CustomRouterViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/CustomRouterViewController.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/CustomRouterViewController.m new file mode 100644 index 00000000..e8c880df --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/CustomRouterViewController.m @@ -0,0 +1,40 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "CustomRouterViewController.h" + +@interface CustomRouterViewController () + +@end + +@implementation CustomRouterViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + UILabel *tipLabel = [[UILabel alloc] init]; + tipLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:tipLabel]; + tipLabel.text = @"自定义路由测试页面"; + tipLabel.textAlignment = NSTextAlignmentCenter; + tipLabel.textColor = [UIColor blackColor]; + [NSLayoutConstraint activateConstraints:@[ + [tipLabel.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor], + [tipLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + ]]; + self.navigationController.navigationBarHidden = NO; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before +navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/IMUIKitOCExample-Bridging-Header.h b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/IMUIKitOCExample-Bridging-Header.h new file mode 100644 index 00000000..61396132 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/IMUIKitOCExample-Bridging-Header.h @@ -0,0 +1,3 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NENavigationController.h b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NENavigationController.h new file mode 100644 index 00000000..76d8f3c8 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NENavigationController.h @@ -0,0 +1,14 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NENavigationController : UINavigationController + +@end + +NS_ASSUME_NONNULL_END diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NENavigationController.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NENavigationController.m new file mode 100644 index 00000000..1872d2c5 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NENavigationController.m @@ -0,0 +1,40 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NENavigationController.h" + +@interface NENavigationController () + +@end + +@implementation NENavigationController + +- (void)viewDidLoad { + [super viewDidLoad]; + [self setUpNavigation]; +} + +- (void)setUpNavigation { + if (@available(iOS 13.0, *)) { + UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init]; + appearance.backgroundImage = [UIImage new]; + appearance.backgroundColor = [UIColor whiteColor]; + appearance.shadowColor = [UIColor whiteColor]; + self.navigationBar.standardAppearance = appearance; + self.navigationBar.scrollEdgeAppearance = appearance; + } +} + +- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { + if (self.childViewControllers.count > 0) { + viewController.hidesBottomBarWhenPushed = YES; + if (self.childViewControllers.count > 1) { + viewController.hidesBottomBarWhenPushed = NO; + } + } + [super pushViewController:viewController animated:animated]; +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NETabbarController.h b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NETabbarController.h new file mode 100644 index 00000000..ab07800c --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NETabbarController.h @@ -0,0 +1,15 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import "IMUIKitOCExample-Bridging-Header.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NETabbarController : UITabBarController + +@end + +NS_ASSUME_NONNULL_END diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NETabbarController.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NETabbarController.m new file mode 100644 index 00000000..c4647db3 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/NETabbarController.m @@ -0,0 +1,62 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NETabbarController.h" +#import "NENavigationController.h" + +#import +#import +#import +#import +#import +#import + +@interface NETabbarController () + +@end + +@implementation NETabbarController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + [self setUpControllers]; +} + +- (void)setUpControllers { + // 会话列表页 + ConversationController *sessionCtrl = [[ConversationController alloc] init]; + sessionCtrl.view.backgroundColor = [UIColor whiteColor]; + sessionCtrl.tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"message", @"") + image:[UIImage imageNamed:@"chat"] + selectedImage:[UIImage imageNamed:@"chatSelect"]]; + NENavigationController *sessionNav = + [[NENavigationController alloc] initWithRootViewController:sessionCtrl]; + + // 通讯录 + ContactsViewController *contactCtrl = [[ContactsViewController alloc] init]; + contactCtrl.tabBarItem = + [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"contact", @"") + image:[UIImage imageNamed:@"contact"] + selectedImage:[UIImage imageNamed:@"contactSelect"]]; + NENavigationController *contactNav = + [[NENavigationController alloc] initWithRootViewController:contactCtrl]; + + // 圈组 + + QChatHomeViewController *qchatCtrl = [[QChatHomeViewController alloc] init]; + qchatCtrl.tabBarItem = + [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"qchat", @"") + image:[UIImage imageNamed:@"qchat_tabbar_icon"] + selectedImage:[UIImage imageNamed:@"qchat_tabbar_icon"]]; + NENavigationController *qchatNav = + [[NENavigationController alloc] initWithRootViewController:qchatCtrl]; + + self.tabBar.backgroundColor = [UIColor whiteColor]; + self.viewControllers = @[ sessionNav, contactNav, qchatNav ]; + self.selectedIndex = 0; +} + +@end diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatRouter/QChatRouter.swift b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ViewController.h similarity index 66% rename from NEQChatUIKit/NEQChatUIKit/Classes/QChatRouter/QChatRouter.swift rename to IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ViewController.h index bc9d74c5..53076181 100644 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatRouter/QChatRouter.swift +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ViewController.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import Foundation +#import -public enum QChatRouter { - public static func register() {} -} +@interface ViewController : UIViewController + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ViewController.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ViewController.m new file mode 100644 index 00000000..015dc5c1 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/ViewController.m @@ -0,0 +1,19 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/en-IN.lproj/Localizable.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/en-IN.lproj/Localizable.strings new file mode 100644 index 00000000..686cbdf1 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/en-IN.lproj/Localizable.strings @@ -0,0 +1,7 @@ +/* + Localizable.strings + IMUIKitOCExample + + Created by vvj on 2022/10/31. + +*/ diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/en.lproj/Localizable.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/en.lproj/Localizable.strings new file mode 100644 index 00000000..07add498 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/en.lproj/Localizable.strings @@ -0,0 +1,11 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +"message"="Message"; +"qchat"="Qchat"; +"contact"="Contact"; +"mine"="Me"; + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/zh-Hans.lproj/Localizable.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000..c8d3a1a7 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/Main/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,13 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + + +"message"="消息"; +"qchat"="圈组"; +"contact"="通讯录"; +"mine"="我"; + + + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/en-IN.lproj/LaunchScreen.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/en-IN.lproj/LaunchScreen.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/en-IN.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/en-IN.lproj/Main.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/en-IN.lproj/Main.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/en-IN.lproj/Main.strings @@ -0,0 +1 @@ + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/main.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/main.m new file mode 100644 index 00000000..49b07ea9 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/main.m @@ -0,0 +1,16 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import "AppDelegate.h" + +int main(int argc, char *argv[]) { + NSString *appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/zh-Hans.lproj/LaunchScreen.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/zh-Hans.lproj/LaunchScreen.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/zh-Hans.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/zh-Hans.lproj/Main.strings b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/zh-Hans.lproj/Main.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExample/zh-Hans.lproj/Main.strings @@ -0,0 +1 @@ + diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleTests/IMUIKitOCExampleTests.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleTests/IMUIKitOCExampleTests.m new file mode 100644 index 00000000..79076fc1 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleTests/IMUIKitOCExampleTests.m @@ -0,0 +1,36 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +@interface IMUIKitOCExampleTests : XCTestCase + +@end + +@implementation IMUIKitOCExampleTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the + // class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the + // class. +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleUITests/IMUIKitOCExampleUITests.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleUITests/IMUIKitOCExampleUITests.m new file mode 100644 index 00000000..d0b0e770 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleUITests/IMUIKitOCExampleUITests.m @@ -0,0 +1,48 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +@interface IMUIKitOCExampleUITests : XCTestCase + +@end + +@implementation IMUIKitOCExampleUITests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the + // class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + self.continueAfterFailure = NO; + + // In UI tests it’s important to set the initial state - such as interface orientation - required + // for your tests before they run. The setUp method is a good place to do this. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the + // class. +} + +- (void)testExample { + // UI tests must launch the application that they test. + XCUIApplication *app = [[XCUIApplication alloc] init]; + [app launch]; + + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testLaunchPerformance { + if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *)) { + // This measures how long it takes to launch your application. + [self measureWithMetrics:@[ [[XCTApplicationLaunchMetric alloc] init] ] + block:^{ + [[[XCUIApplication alloc] init] launch]; + }]; + } +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleUITests/IMUIKitOCExampleUITestsLaunchTests.m b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleUITests/IMUIKitOCExampleUITestsLaunchTests.m new file mode 100644 index 00000000..6faa84f1 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/IMUIKitOCExampleUITests/IMUIKitOCExampleUITestsLaunchTests.m @@ -0,0 +1,36 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +@interface IMUIKitOCExampleUITestsLaunchTests : XCTestCase + +@end + +@implementation IMUIKitOCExampleUITestsLaunchTests + ++ (BOOL)runsForEachTargetApplicationUIConfiguration { + return YES; +} + +- (void)setUp { + self.continueAfterFailure = NO; +} + +- (void)testLaunch { + XCUIApplication *app = [[XCUIApplication alloc] init]; + [app launch]; + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + XCTAttachment *attachment = + [XCTAttachment attachmentWithScreenshot:XCUIScreen.mainScreen.screenshot]; + attachment.name = @"Launch Screen"; + attachment.lifetime = XCTAttachmentLifetimeKeepAlways; + [self addAttachment:attachment]; +} + +@end diff --git a/IMUIKitOC/IMUIKitOCExample/Podfile b/IMUIKitOC/IMUIKitOCExample/Podfile new file mode 100644 index 00000000..467e3636 --- /dev/null +++ b/IMUIKitOC/IMUIKitOCExample/Podfile @@ -0,0 +1,56 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +platform :ios, '9.0' +source 'https://github.com/CocoaPods/Specs.git' + +target 'IMUIKitOCExample' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + #登录组件 + pod 'YXLogin', '1.0.0' + + #可选UI库 + pod 'NEContactUIKit', '9.4.0' + pod 'NEQChatUIKit', '9.4.0' + pod 'NEConversationUIKit', '9.4.0' + pod 'NEChatUIKit', '9.4.0' + pod 'NETeamUIKit', '9.4.0' + + + #可选Kit库(和UIKit对应) + pod 'NEContactKit', '9.4.0' + pod 'NEQChatKit', '9.4.0' + pod 'NEConversationKit', '9.4.0' + pod 'NEChatKit', '9.4.0' + pod 'NETeamKit', '9.4.0' + + #基础kit库 + pod 'NECommonUIKit', '9.4.0' + pod 'NECommonKit', '9.4.0' + pod 'NECoreIMKit', '9.4.0' + pod 'NECoreKit', '9.4.0' + pod 'NEMapKit', '9.4.0' + + + + + #fix bug in Xcode 14 + post_install do |installer| + installer.pods_project.targets.each do |target| + if target.name == 'RSKPlaceholderTextView' + target.build_configurations.each do |config| + config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' + end + end + end + end + + # 如果需要查看UI部分源码请注释掉以上在线依赖,打开下面的本地依赖 +# pod 'NEQChatUIKit', :path => '../NEQChatUIKit/NEQChatUIKit.podspec' +# pod 'NEContactUIKit', :path => '../NEContactUIKit/NEContactUIKit.podspec' +# pod 'NEConversationUIKit', :path => '../NEConversationUIKit/NEConversationUIKit.podspec' +# pod 'NETeamUIKit', :path => '../NETeamUIKit/NETeamUIKit.podspec' +# pod 'NEChatUIKit', :path => '../NEChatUIKit/NEChatUIKit.podspec' + +end diff --git a/NEChatUIKit/NEChatUIKit.podspec b/NEChatUIKit/NEChatUIKit.podspec index f199a175..6dbe13c0 100644 --- a/NEChatUIKit/NEChatUIKit.podspec +++ b/NEChatUIKit/NEChatUIKit.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| # spec.name = 'NEChatUIKit' - spec.version = '9.3.0' + spec.version = '9.2.10' spec.summary = 'Chat Module of IM.' # This description is used to generate tags and improve search results. @@ -37,9 +37,9 @@ TODO: Add long description of the pod here. spec.source_files = 'NEChatUIKit/Classes/**/*' spec.pod_target_xcconfig = { + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64', 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } - spec.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } # spec.resource_bundles = { # 'NEChatUIKit' => ['NEChatUIKit/Assets/*.png'] # } @@ -52,7 +52,6 @@ TODO: Add long description of the pod here. spec.dependency 'RSKPlaceholderTextView' spec.dependency 'MJRefresh' spec.dependency 'NIMSDK_LITE' - spec.dependency 'YXAlog_iOS' # spec.dependency 'AMap2DMap' # spec.dependency 'AMapSearch' diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Contents.json b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Contents.json similarity index 100% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Contents.json rename to NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Contents.json diff --git a/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Frame@2x.png b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Frame@2x.png new file mode 100644 index 00000000..af69153c Binary files /dev/null and b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Frame@2x.png differ diff --git a/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Frame@3x.png b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Frame@3x.png new file mode 100644 index 00000000..d6d8af55 Binary files /dev/null and b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/audio_record.imageset/Frame@3x.png differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Contents.json b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Contents.json similarity index 100% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Contents.json rename to NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Contents.json diff --git a/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Vector@2x.png b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Vector@2x.png new file mode 100644 index 00000000..869763af Binary files /dev/null and b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Vector@2x.png differ diff --git a/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Vector@3x.png b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Vector@3x.png new file mode 100644 index 00000000..d21bee94 Binary files /dev/null and b/NEChatUIKit/NEChatUIKit/Assets/NEChatUIKit.xcassets/Commom/video_record.imageset/Vector@3x.png differ diff --git a/NEChatUIKit/NEChatUIKit/Assets/en.lproj/Localizable.strings b/NEChatUIKit/NEChatUIKit/Assets/en.lproj/Localizable.strings index a3f2a5a8..1311f81b 100644 --- a/NEChatUIKit/NEChatUIKit/Assets/en.lproj/Localizable.strings +++ b/NEChatUIKit/NEChatUIKit/Assets/en.lproj/Localizable.strings @@ -55,6 +55,7 @@ "not_mute" = "unmute"; "mute" = "mute"; "team_has_been_removed" = "This group was removed"; +"team_has_quit" = "Group chat has exited"; "join"="joined"; "pass"="Passed"; "leave"="leave"; @@ -66,7 +67,8 @@ "team_all_mute"="Mute all"; "team_all_no_mute"="Unmute"; -"pin_text"="pinned this message for both"; +"pin_text_P2P"="pinned this message for both"; +"pin_text_team"="pinned this message for both all"; "session_set_top"="sticky to top"; "message_remind"="open notification"; @@ -106,8 +108,8 @@ "user_select"="notification"; "user_select_all"="all"; -"contact_user"="contacts"; -"team"="group"; +"contact_user"="Forward to contacts"; +"team"="Forward to group"; "cancel"="cancel"; "send_to"="send to"; "send"="send"; @@ -117,18 +119,30 @@ "mdhm"="MM.dd HH:mm"; "ymdhm"="yyyy.MM.dd HH:mm"; -"chat_takePicture"="拍摄"; -"chat_rtc"="音视频"; -"chat_location"="位置"; -"chat_file"="文件"; -"gaode_map"="高德地图"; -"tencent_map"="腾讯地图"; +"chat_takePicture"="Capture video"; +"chat_rtc"="Audio and video call"; +"chat_location"="Location"; +"chat_file"="File"; +"gaode_map"="高德 Map"; +"tencent_map"="腾讯 Map"; "search_place"="Search Location"; -"search_cancel"="取消"; +"search_cancel"="cancel"; "distance_inner"="内"; "search_result_empty"="Not found"; -"no_map_plugin"="未集成地图模块"; -"location_not_auth"="地理位置未授权,请去设置中开启"; +"no_map_plugin"="Map module not integrated"; +"location_not_auth"="The geographic location is not authorized. Please open it in the settings"; "fileSize_over_limit"="Oops!File size limit."; "message_recalled"="message recalled"; + +"video_call"="Video call"; +"audio_call"="Audio call"; + +"call_complete"="Talk time"; +"call_canceled"="Call cancellation"; +"call_rejected"="Rejected"; +"call_timeout"="No answer after timeout"; +"call_busy"="The busy line is not answered"; + +"editable_time_expired"="Editable time has expired"; +"message_not_found"="This message is gone"; diff --git a/NEChatUIKit/NEChatUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NEChatUIKit/NEChatUIKit/Assets/zh-Hans.lproj/Localizable.strings index be1a8703..a9292507 100644 --- a/NEChatUIKit/NEChatUIKit/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEChatUIKit/NEChatUIKit/Assets/zh-Hans.lproj/Localizable.strings @@ -6,6 +6,7 @@ //MAKR:common "ok"="确认"; "send_to"="发送给 "; + //MAKR:message "send_picture"="发来了一张图片"; "send_voice"="发来了一段语音"; @@ -61,6 +62,7 @@ "not_mute" = "解除禁言"; "mute" = "禁言"; "team_has_been_removed" = "当前群聊已解散"; +"team_has_quit" = "已退出群聊"; "join"="进入了"; "pass"="通过了"; "leave"="离开了"; @@ -71,7 +73,8 @@ "team_mute"="当前群主设置为禁言"; "team_all_mute"="群全体禁言"; "team_all_no_mute"="取消群全体禁言"; -"pin_text"="标记了这条信息,对话内容双方均可见"; +"pin_text_P2P"="标记了这条信息,对话内容双方均可见"; +"pin_text_team"="标记了这条信息,所有群成员均可见"; "session_set_top"="聊天置顶"; "message_remind"="开启消息提醒"; "open_soon"="暂未开放"; @@ -109,8 +112,8 @@ "user_select"="选择提醒"; "user_select_all"="所有人"; -"contact_user"="好友"; -"team"="群聊"; +"contact_user"="转发到个人"; +"team"="转发到群组"; "cancel"="取消"; "send_to"="发送给"; "send"="发送"; @@ -121,7 +124,7 @@ "ymdhm"="yyyy年MM月dd日 HH:mm"; "chat_takePicture"="拍摄"; -"chat_rtc"="音视频"; +"chat_rtc"="音视频通话"; "chat_location"="位置"; "chat_file"="文件"; "gaode_map"="高德地图"; @@ -135,3 +138,15 @@ "fileSize_over_limit"="当前文件大小超出发送限制,请重新选择"; "message_recalled"="消息已撤回"; + +"video_call"="视频通话"; +"audio_call"="音频通话"; + +"call_complete"="通话时长"; +"call_canceled"="已取消"; +"call_rejected"="已拒绝"; +"call_timeout"="超时未接听"; +"call_busy"="忙线未接听"; + +"editable_time_expired"="已超过可编辑时间"; +"message_not_found"="该消息已移除"; diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift index eef1d8e9..ebfc2e86 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift @@ -22,8 +22,8 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel UITableViewDelegate, UIDocumentPickerDelegate, UIDocumentInteractionControllerDelegate, CLLocationManagerDelegate { private let tag = "ChatViewController" public var viewmodel: ChatViewModel - private var inputViewTopConstraint: NSLayoutConstraint? - private var tableViewBottomConstraint: NSLayoutConstraint? + public var inputViewTopConstraint: NSLayoutConstraint? + public var tableViewBottomConstraint: NSLayoutConstraint? public var menuView: ChatInputView = .init() public var operationView: MessageOperationView? private var playingCell: ChatAudioCell? @@ -32,7 +32,8 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel var replyView = ReplyView() private var isFile = false let interactionController = UIDocumentInteractionController() - + private var needMarkReadMsgs = [NIMMessage]() + private var isCurrentPage = true var titleContent = "" private lazy var manager = CLLocationManager() @@ -40,19 +41,23 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel public init(session: NIMSession) { viewmodel = ChatViewModel(session: session, anchor: nil) super.init(nibName: nil, bundle: nil) - viewmodel.delegate = self NEKeyboardManager.shared.enable = false NEKeyboardManager.shared.enableAutoToolbar = false NIMSDK.shared().mediaManager.add(self) NIMSDK.shared().mediaManager.setNeedProximityMonitor(viewmodel.getHandSetEnable()) // 注册自定义消息的解析器 - NIMCustomObject.registerCustomDecoder(CustomAttachmentDecoder()) + // NIMCustomObject.registerCustomDecoder(CustomAttachmentDecoder()) } public required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + override func backEvent() { + super.backEvent() + cleanDelegate() + } + override open func viewDidLoad() { super.viewDidLoad() commonUI() @@ -62,15 +67,29 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel override open func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + NEKeyboardManager.shared.enable = false + NEKeyboardManager.shared.shouldResignOnTouchOutside = false + isCurrentPage = true navigationController?.isNavigationBarHidden = false + markNeedReadMsg() } override open func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + NEKeyboardManager.shared.enable = true + NEKeyboardManager.shared.shouldResignOnTouchOutside = true + isCurrentPage = false + operationView?.removeFromSuperview() if NIMSDK.shared().mediaManager.isPlaying() { NIMSDK.shared().mediaManager.stopPlay() } } + override open func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + stopPlay() + } + // MARK: 子类可重写方法 // load data的时候会调用 @@ -133,7 +152,12 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } else { operationY = rectInView.origin.y - h } - let frame = CGRect(x: 0, y: operationY, width: w, height: h) + var frameX = 0.0 + if let msg = model?.message, + msg.isOutgoingMsg { + frameX = kScreenWidth - w + } + let frame = CGRect(x: frameX, y: operationY, width: w, height: h) operationView = MessageOperationView(frame: frame) operationView!.delegate = self operationView!.items = items @@ -215,17 +239,14 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel ) } -// public override func touchesBegan(_ touches: Set, with event: UIEvent?) { -// self.operationView?.removeFromSuperview() -// if self.menuView.textField.isFirstResponder { -// self.menuView.textField.resignFirstResponder() -// }else { -// self.layoutInputView(offset: 0) -// } -// } - deinit { print("will deinit") + cleanDelegate() + } + + func cleanDelegate() { + NIMSDK.shared().mediaManager.remove(self) + viewmodel.delegate = nil } // MARK: objc 方法 @@ -252,7 +273,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel view.addSubview(tableView) tableViewBottomConstraint = tableView.bottomAnchor.constraint( equalTo: view.bottomAnchor, - constant: -86 - KStatusBarHeight + constant: -100 ) tableViewBottomConstraint?.isActive = true if #available(iOS 10, *) { @@ -275,6 +296,10 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel ]) } + tableView.register(ChatCallRecordLeftCell.self, forCellReuseIdentifier: "\(ChatCallRecordLeftCell.self)") + + tableView.register(ChatCallRecordRightCell.self, forCellReuseIdentifier: "\(ChatCallRecordRightCell.self)") + tableView.register( ChatTimeTableViewCell.self, forCellReuseIdentifier: "\(ChatTimeTableViewCell.self)" @@ -350,15 +375,17 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel tableView.register(ChatLocationLeftCell.self, forCellReuseIdentifier: "\(ChatLocationLeftCell.self)") tableView.register(ChatLocationRightCell.self, forCellReuseIdentifier: "\(ChatLocationRightCell.self)") + viewmodel.delegate = self menuView.backgroundColor = UIColor(hexString: "#EFF1F3") menuView.translatesAutoresizingMaskIntoConstraints = false menuView.delegate = self + menuView.chatAddMoreView.configData(data: NEChatUIKitClient.instance.getMoreActionData(sessionType: viewmodel.session.sessionType)) view.addSubview(menuView) inputViewTopConstraint = menuView.topAnchor.constraint( equalTo: view.bottomAnchor, - constant: -(86 + NEConstant.statusBarHeight) + constant: -100 ) NSLayoutConstraint.activate([ menuView.leftAnchor.constraint(equalTo: view.leftAnchor), @@ -373,6 +400,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel weakSelf?.view.addSubview(networkView) } else { weakSelf?.brokenNetworkView.removeFromSuperview() + weakSelf?.viewmodel.refreshReceipts() } } addRightAction(UIImage.ne_imageNamed(name: "three_point"), #selector(toSetting), self) @@ -388,27 +416,18 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel ModuleName + " " + self.tag, desc: "CALLBACK queryRoamMsgHasMoreTime_v2 " + (error?.localizedDescription ?? "no error") ) + weakSelf?.viewmodel.refreshReceipts() if let ms = models, ms.count > 0 { - if let messages = weakSelf?.viewmodel.messages { - for index in 0 ..< messages.count { - let message = messages[index] - print("messages id : ", message.message?.messageId as Any) - if message.message?.messageId == weakSelf?.viewmodel.anchor?.messageId { - print("messages real index : ", index) - } - } - } weakSelf?.tableView.reloadData() if weakSelf?.viewmodel.isHistoryChat == true { let indexPath = IndexPath(row: index, section: 0) print("queryRoamMsgHasMoreTime_v2 index : ", index) weakSelf?.tableView.scrollToRow(at: indexPath, at: .none, animated: false) - if newEnd <= 0 { + if newEnd > 0 { weakSelf?.addBottomLoadMore() } } else { if let tempArray = weakSelf?.viewmodel.messages, tempArray.count > 0 { - weakSelf?.tableView.reloadData() weakSelf?.tableView.scrollToRow( at: IndexPath(row: tempArray.count - 1, section: 0), at: .bottom, @@ -421,44 +440,6 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel weakSelf?.showToast(err.localizedDescription) } } - - // if viewmodel.isHistoryChat == false { - // viewmodel.getMessageHistory({[weak self] error,isEmpty,messages in - // if let err = error { - // NELog.errorLog(ModuleName + " " + (self?.tag ?? "ChatViewController"), desc: "❌getMessageHistory error, error:\(err)") - // }else { - // if let tempArray = weakSelf?.viewmodel.messages,tempArray.count > 0 { - // weakSelf?.tableView.reloadData() - // weakSelf?.tableView.scrollToRow(at: IndexPath(row: tempArray.count - 1, section: 0), at: .bottom, animated: false) - // } - // } - // }) - // }else { - // print("queryRoamMsgHasMoreTime") - // viewmodel.queryRoamMsgHasMoreTime_v2 { error, historyEnd, newEnd, models, index in - // if let ms = models, ms.count > 0 { - // if let messages = weakSelf?.viewmodel.messages { - // for index in 0.. 0 { weakSelf?.tableView.scrollToRow( - at: IndexPath(row: count, section: 0), + at: IndexPath(row: count - 1, section: 0), at: .top, animated: false ) } weakSelf?.tableView.mj_header?.endRefreshing() } - - // viewmodel.getMoreMessageHistory { error, isEmpty, messageFrames in - // weakSelf?.tableView.reloadData() - // weakSelf?.tableView.mj_header?.endRefreshing() - // } } func loadFartherToNowData() {} func loadCloserToNowData() { weak var weakSelf = self - viewmodel.pullRemoteRefresh { error, end, datas in + viewmodel.pullRemoteRefresh { error, count, datas in NELog.infoLog( ModuleName + " " + self.tag, desc: "CALLBACK pullRemoteRefresh " + (error?.localizedDescription ?? "no error") ) - if end > 0 { + if count <= 0 { weakSelf?.removeBottomLoadMore() } else { weakSelf?.tableView.mj_footer?.endRefreshing() @@ -506,6 +482,10 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } func addObseve() { + NotificationCenter.default.addObserver(self, + selector: #selector(markNeedReadMsg), + name: UIApplication.willEnterForegroundNotification, + object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, @@ -515,9 +495,9 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel selector: #selector(keyBoardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) - // let tap = UITapGestureRecognizer(target: self, action: #selector(viewTap)) - // tap.delegate = self - // self.view.addGestureRecognizer(tap) + let tap = UITapGestureRecognizer(target: self, action: #selector(viewTap)) + tap.delegate = self + view.addGestureRecognizer(tap) } func addBottomLoadMore() { @@ -533,14 +513,34 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel viewmodel.isHistoryChat = false // 转为普通聊天页面 } + func markNeedReadMsg() { + if isCurrentPage { + viewmodel.markRead(messages: needMarkReadMsgs) { error in + NELog.infoLog( + ModuleName + " " + self.tag, + desc: "CALLBACK markRead " + (error?.localizedDescription ?? "no error") + ) + } + needMarkReadMsgs = [NIMMessage]() + } + } + // MARK: 键盘通知相关操作 func keyBoardWillShow(_ notification: Notification) { if menuView.currentType != .text { return } + let oldKeyboardRect = (notification + .userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue let keyboardRect = (notification .userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue + + // 键盘已经弹出 + if oldKeyboardRect == keyboardRect { + return + } + print("chat view key board size : ", keyboardRect) layoutInputView(offset: keyboardRect.size.height) @@ -559,7 +559,6 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel // operationView?.removeFromSuperview() // } layoutInputView(offset: 0) - scrollTableViewToBottom() } private func scrollTableViewToBottom() { @@ -567,16 +566,21 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel print("self.tableView.numberOfRows(inSection: 0)\(tableView.numberOfRows(inSection: 0))") if viewmodel.messages.count > 0 { let indexPath = IndexPath(row: viewmodel.messages.count - 1, section: 0) - tableView.scrollToRow(at: indexPath, at: .bottom, animated: true) + weak var weakSelf = self + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: DispatchWorkItem(block: { + weakSelf?.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true) + })) } } // offset:value which from self.view.bottom to inputView.bottom - private func layoutInputView(offset: CGFloat) { - inputViewTopConstraint?.constant = -100 - offset - tableViewBottomConstraint?.constant = -100 - offset - UIView.animate(withDuration: 0.25, animations: { - self.view.layoutIfNeeded() + var count = 0 + func layoutInputView(offset: CGFloat) { + print("layoutInputView offset : ", offset) + weak var weakSelf = self + UIView.animate(withDuration: 0.1, animations: { + weakSelf?.inputViewTopConstraint?.constant = -100 - offset + weakSelf?.tableViewBottomConstraint?.constant = -100 - offset }) } @@ -615,10 +619,16 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } public func didSelectMoreCell(cell: NEInputMoreCell) { + if let delegate = cell.cellData?.customDelegate as? AnyObject, let action = cell.cellData?.action { + // 用户自定义更多面板按钮 + _ = delegate.perform(action) + return + } + if let type = cell.cellData?.type, type == .location { if #available(iOS 14.0, *) { if manager.authorizationStatus == .denied { - showToast(chatLocalizable("location_not_auth")) + showSingleAlert(message: commonLocalizable("jump_location_setting")) {} return } else if manager.authorizationStatus == .notDetermined { manager.delegate = self @@ -628,7 +638,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } } else { if CLLocationManager.authorizationStatus() == .denied { - showToast(chatLocalizable("location_not_auth")) + showSingleAlert(message: commonLocalizable("jump_location_setting")) {} return } else if CLLocationManager.authorizationStatus() == .notDetermined { manager.delegate = self @@ -645,9 +655,34 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } else if let type = cell.cellData?.type, type == .file { isFile = true showBottomFileAction(self) + } else if let type = cell.cellData?.type, type == .rtc { + showRtcCallAction() } else {} } + func showRtcCallAction() { + var param = [String: AnyObject]() + param["remoteUserAccid"] = viewmodel.session.sessionId as AnyObject + param["currentUserAccid"] = NIMSDK.shared().loginManager.currentAccount() as AnyObject + param["remoteShowName"] = titleContent as AnyObject + if let user = viewmodel.repo.getUserInfo(userId: viewmodel.session.sessionId), let avatar = user.userInfo?.avatarUrl { + param["remoteAvatar"] = avatar as AnyObject + } + + let videoCallAction = UIAlertAction(title: chatLocalizable("video_call"), style: .default) { _ in + param["type"] = NSNumber(integerLiteral: 2) as AnyObject + Router.shared.use(CallViewRouter, parameters: param) + } + let audioCallAction = UIAlertAction(title: chatLocalizable("audio_call"), style: .default) { _ in + param["type"] = NSNumber(integerLiteral: 1) as AnyObject + Router.shared.use(CallViewRouter, parameters: param) + } + let cancelAction = UIAlertAction(title: chatLocalizable("cancel"), + style: .cancel) { action in + } + showActionSheet([videoCallAction, audioCallAction, cancelAction]) + } + func didToSearchLocationView() { let ctrl = NEDetailMapController(type: .search) navigationController?.pushViewController(ctrl, animated: true) @@ -668,8 +703,10 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel if viewmodel.session.sessionType == .P2P { return true } else { - showUserSelectVC(text: text) - return false + DispatchQueue.main.async { + self.showUserSelectVC(text: text) + } + return true } } else { @@ -688,11 +725,37 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel break } } + if index >= 0 { atUsers.remove(at: index) - if let text = menuView.textField.text { - menuView.textField.text = text - .substring(to: text.index(text.startIndex, offsetBy: removeRange!.location)) + if let rmRange = removeRange { + // 删除rmRange后,rmRange.location后面所有的atUser的location都发生了变化 + var atUsersTmp = [NSRange]() + for atUser in atUsers { + if rmRange.location < atUser.location { + atUsersTmp.append(NSRange(location: atUser.location - rmRange.length, length: atUser.length)) + } else { + atUsersTmp.append(atUser) + } + } + if atUsersTmp.count > 0 { + atUsers = atUsersTmp + } + + // 记录当前光标位置(removeSubrange后光标会直接跳到末尾) + var selRange = menuView.textField.selectedTextRange + if let oldCursor = menuView.textField.selectedTextRange { + if let newCursor = menuView.textField.position(from: oldCursor.start, offset: -rmRange.length) { + selRange = menuView.textField.textRange(from: newCursor, to: newCursor) + } + } + + // 删除rmRange范围内的字符串("@xxx ") + let subRange = menuView.textField.text.utf16.index(menuView.textField.text.startIndex, offsetBy: rmRange.location) ... menuView.textField.text.utf16.index(menuView.textField.text.startIndex, offsetBy: rmRange.location + rmRange.length - 1) + menuView.textField.text.removeSubrange(subRange) + + // 重新设置光标到删除前的位置 + menuView.textField.selectedTextRange = selRange } return false } @@ -720,6 +783,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } public func willSelectItem(button: UIButton, index: Int) { + operationView?.removeFromSuperview() if index == 0 { layoutInputView(offset: 204) scrollTableViewToBottom() @@ -727,8 +791,6 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel layoutInputView(offset: 204) scrollTableViewToBottom() } else if index == 2 { - // showMenue(sourceView: view) - // showBottomAlert(self, false) goPhotoAlbumWithVideo(self) } else { // 更多 @@ -782,14 +844,8 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel present(imagePickerVC, animated: true) {} } - // MARK: UIImagePickerControllerDelegate - - public func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [UIImagePickerController - .InfoKey: Any]) { - // send message - - picker.dismiss(animated: true, completion: nil) + func sendMediaMessage(didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { var imageName = "IMG_0001" if isFile, let imgUrl = info[.referenceURL] as? URL { @@ -830,8 +886,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel let imgData = image.pngData() { let imgSize_MB = Double(imgData.count) / 1e6 print("@@# imgSize_MB: \(imgSize_MB) MB") - if let fileSizeLimit = NEKitChatConfig.shared.ui.fileSizeLimit, - imgSize_MB > fileSizeLimit { + if imgSize_MB > NEKitChatConfig.shared.ui.fileSizeLimit { showToast(chatLocalizable("fileSize_over_limit")) } else { viewmodel.sendFileMessage(data: imgData, displayName: imageName) { [weak self] error in @@ -858,6 +913,19 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } } + // MARK: UIImagePickerControllerDelegate + + public func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { +// picker.dismiss(animated: true, completion: nil) +// sendMediaMessage(didFinishPickingMediaWithInfo: info) + weak var weakSelf = self + picker.dismiss(animated: true, completion: { + weakSelf?.sendMediaMessage(didFinishPickingMediaWithInfo: info) + }) + } + public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) isFile = false @@ -884,8 +952,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel print("@@# size:\(size_B)B") let size_MB = size_B / 1e6 print("@@# size:\(size_MB)MB") - if let fileSizeLimit = NEKitChatConfig.shared.ui.fileSizeLimit, - size_MB > fileSizeLimit { + if size_MB > NEKitChatConfig.shared.ui.fileSizeLimit { showToast(chatLocalizable("fileSize_over_limit")) try? FileManager.default.removeItem(atPath: desPath) } else { @@ -939,14 +1006,32 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel // MARK: ChatViewModelDelegate + public func didLeaveTeam() { + weak var weakSelf = self + showSingleAlert(message: chatLocalizable("team_has_quit")) { + weakSelf?.navigationController?.popViewController(animated: true) + } + } + + public func didDismissTeam() { + weak var weakSelf = self + showSingleAlert(message: chatLocalizable("team_has_been_removed")) { + weakSelf?.navigationController?.popViewController(animated: true) + } + } + public func onRecvMessages(_ messages: [NIMMessage]) { insertRows() - viewmodel.markRead(messages: messages) { error in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK markRead " + (error?.localizedDescription ?? "no error") - ) -// print("mark read \(error?.localizedDescription)") + if isCurrentPage, + UIApplication.shared.applicationState == .active { + viewmodel.markRead(messages: messages) { error in + NELog.infoLog( + ModuleName + " " + self.tag, + desc: "CALLBACK markRead " + (error?.localizedDescription ?? "no error") + ) + } + } else { + needMarkReadMsgs += messages } } @@ -1030,12 +1115,12 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } public func didReadedMessageIndexs() { - if let indexPaths = tableView.indexPathsForVisibleRows, indexPaths.count > 0 { - tableView.beginUpdates() - // self.tableView.reloadRows(at: indexs, with: .none) - tableView.reloadRows(at: indexPaths, with: .none) - tableView.endUpdates() - } + tableView.reloadData() +// if let indexPaths = tableView.indexPathsForVisibleRows, indexPaths.count > 0 { +// tableView.beginUpdates() +// tableView.reloadRows(at: indexPaths, with: .none) +// tableView.endUpdates() +// } } public func tableViewUpdateDownload(_ index: IndexPath) { @@ -1050,11 +1135,11 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel if NEAuthManager.hasAudioAuthoriztion() { NIMSDK.shared().mediaManager.record(forDuration: dur) } else { - NEAuthManager.requestAudioAuthorization { granted in + NEAuthManager.requestAudioAuthorization { [weak self] granted in if granted { } else { DispatchQueue.main.async { - self.showToast(chatLocalizable("no_microphone_permission")) + self?.showSingleAlert(message: commonLocalizable("jump_microphone_setting")) {} } } } @@ -1077,11 +1162,16 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } func viewTap(tap: UITapGestureRecognizer) { - operationView?.removeFromSuperview() - if menuView.textField.isFirstResponder { - menuView.textField.resignFirstResponder() + if let opeView = operationView, + view.subviews.contains(opeView) { + opeView.removeFromSuperview() + } else { - layoutInputView(offset: 0) + if menuView.textField.isFirstResponder { + menuView.textField.resignFirstResponder() + } else { + layoutInputView(offset: 0) + } } } @@ -1234,33 +1324,58 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel } } + func addToAtUsers(addText: String, isReply: Bool = false) { + // @列表中添加一项 + let anIndex = menuView.textField.selectedRange.location + var range = NSRange(location: anIndex - 1, length: addText.utf16.count + 1) + if isReply { + range = NSRange(location: anIndex, length: addText.utf16.count) + } + atUsers.append(range) + + // 添加range后,range.location后面所有的atUser的location都发生了变化 + var atUsersTmp = [NSRange]() + for atUser in atUsers { + if range.location < atUser.location { + atUsersTmp.append(NSRange(location: atUser.location + range.length, length: atUser.length)) + } else { + atUsersTmp.append(atUser) + } + } + if atUsersTmp.count > 0 { + atUsers = atUsersTmp + } + + // range范围内添加字符串("@xxx ") + if let pos = menuView.textField.selectedTextRange { + // 用replace代替insert(start==end) + menuView.textField.replace(pos, withText: addText) + } else { + menuView.textField.text += addText + } + } + private func showUserSelectVC(text: String) { - let selectVC = SelectUserViewController(sessionId: viewmodel.session.sessionId) + let selectVC = SelectUserViewController(sessionId: viewmodel.session.sessionId, showSelf: false) selectVC.modalPresentationStyle = .formSheet selectVC.selectedBlock = { [weak self] index, model in - var resultText = "" - var location = 0 - var length = 0 - if let t = self?.menuView.textField.text, t.count > 0 { - resultText = t - location = t.count - } + var addText = "" + if index == 0 { - let addText = text + chatLocalizable("user_select_all") + " " - resultText += addText - length = addText.count - let range = NSRange(location: location, length: length) - self?.atUsers.append(range) + addText += chatLocalizable("user_select_all") + " " } else { if let m = model { - let addText = text + m.atNameInTeam() + " " - resultText += addText - length = addText.count - let range = NSRange(location: location, length: length) - self?.atUsers.append(range) + var name = "" + if let nick = m.nimUser?.userInfo?.nickName { + name = nick + } else if let uid = m.nimUser?.userId { + name = uid + } + addText += name + " " } } - self?.menuView.textField.text = resultText + + self?.addToAtUsers(addText: addText) } present(selectVC, animated: true, completion: nil) } @@ -1294,10 +1409,10 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel private func copyMessage() { if let model = viewmodel.operationModel as? MessageTextModel, - let text = model.attributeStr { + let text = model.message?.text { let pasteboard = UIPasteboard.general - pasteboard.string = text.string - showToast(chatLocalizable("copy_success")) + pasteboard.string = text + view.makeToast(chatLocalizable("copy_success"), duration: 2, position: .center) } } @@ -1322,10 +1437,16 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel ]) if let message = viewmodel.operationModel?.message { var text = chatLocalizable("msg_reply") - if let name = viewmodel.operationModel?.shortName { - text += name + if let uid = message.from { + let user = viewmodel.getUserInfo(userId: uid) + let name = user?.userInfo?.nickName + if viewmodel.session.sessionType != .P2P, + !IMKitClient.instance.isMySelf(uid) { + addToAtUsers(addText: "@" + (name ?? uid) + " ", isReply: true) + } + text += " " + (name ?? uid) } - text += ":" + text += ": " switch message.messageType { case .text: if let t = message.text { @@ -1347,6 +1468,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel text += "" } replyView.textLabel.text = text + menuView.textField.becomeFirstResponder() } } @@ -1362,6 +1484,9 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel if let messageType = weakSelf?.viewmodel.operationModel?.message?.messageType, messageType == .text { weakSelf?.viewmodel.operationModel?.isRevokedText = true } +// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(120)) { +// weakSelf?.tableView.reloadData() +// } weakSelf?.viewmodel.revokeMessage(message: message) { error in NELog.infoLog( ModuleName + " " + (weakSelf?.tag ?? ""), @@ -1427,6 +1552,10 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel weakSelf?.addChild(forwardAlert) weakSelf?.view.addSubview(forwardAlert.view) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: DispatchWorkItem(block: { + UIApplication.shared.keyWindow?.endEditing(true) + })) + forwardAlert.sureBlock = { print("sure click ") weakSelf?.viewmodel.forwardUserMessage(message, users) @@ -1458,9 +1587,14 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel if let senderName = message.senderName { forwardAlert.context = senderName } + forwardAlert.sureBlock = { + weakSelf?.viewmodel.forwardTeamMessage(message, team) + } weakSelf?.addChild(forwardAlert) weakSelf?.view.addSubview(forwardAlert.view) - weakSelf?.viewmodel.forwardTeamMessage(message, team) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: DispatchWorkItem(block: { + UIApplication.shared.keyWindow?.endEditing(true) + })) } } @@ -1475,7 +1609,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel style: .cancel) { action in } - showActionSheet([userAction, teamAction, cancelAction]) + showActionSheet([teamAction, userAction, cancelAction]) } } @@ -1520,7 +1654,9 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel // MARK: UITableViewDataSource, UITableViewDelegate public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - viewmodel.messages.count ?? 0 + let count = viewmodel.messages.count + print("numberOfRowsInSection count : ", count) + return count } public func tableView(_ tableView: UITableView, @@ -1528,7 +1664,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel let model = viewmodel.messages[indexPath.row] var reuseId = "" if let isSend = model.message?.isOutgoingMsg, isSend { - if model.replyedModel != nil { + if model.replyedModel?.isReplay == true { reuseId = "\(ChatReplyRightCell.self)" } else { switch model.type { @@ -1548,6 +1684,8 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel reuseId = "\(ChatLocationRightCell.self)" case .file: reuseId = "\(ChatFileRightCell.self)" + case .rtcCallRecord: + reuseId = "\(ChatCallRecordRightCell.self)" default: reuseId = "\(ChatBaseRightCell.self)" } @@ -1569,7 +1707,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel return ChatBaseRightCell() } } else { - if model.replyedModel != nil { + if model.replyedModel?.isReplay == true { reuseId = "\(ChatReplyLeftCell.self)" } else { switch model.type { @@ -1589,6 +1727,8 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel reuseId = "\(ChatRevokeLeftCell.self)" case .location: reuseId = "\(ChatLocationLeftCell.self)" + case .rtcCallRecord: + reuseId = "\(ChatCallRecordLeftCell.self)" default: reuseId = "\(ChatBaseLeftCell.self)" } @@ -1627,6 +1767,22 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel return CGFloat(m.height) } + public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + 0 + } + + public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { + 0 + } + + // MARK: UIScrollViewDelegate + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + operationView?.removeFromSuperview() + } + + // MARK: CLLocationManagerDelegate + // public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { // if #available(iOS 14.0, *) { // if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse { @@ -1702,6 +1858,7 @@ extension ChatViewController: ChatBaseCellDelegate { } else if model?.type == .video, let object = model?.message?.messageObject as? NIMVideoObject { print("video click") + stopPlay() weak var weakSelf = self let videoPlayer = VideoPlayerViewController() videoPlayer.modalPresentationStyle = .overFullScreen @@ -1810,8 +1967,22 @@ extension ChatViewController: ChatBaseCellDelegate { } } } + } else if model?.type == .rtcCallRecord, let object = model?.message?.messageObject as? NIMRtcCallRecordObject { + var param = [String: AnyObject]() + param["remoteUserAccid"] = viewmodel.session.sessionId as AnyObject + param["currentUserAccid"] = NIMSDK.shared().loginManager.currentAccount() as AnyObject + param["remoteShowName"] = titleContent as AnyObject + if let user = viewmodel.repo.getUserInfo(userId: viewmodel.session.sessionId), let avatar = user.userInfo?.avatarUrl { + param["remoteAvatar"] = avatar as AnyObject + } + if object.callType == .audio { + param["type"] = NSNumber(integerLiteral: 1) as AnyObject + } else { + param["type"] = NSNumber(integerLiteral: 2) as AnyObject + } + Router.shared.use(CallViewRouter, parameters: param) } else { - print(#function + "message did tap but type else") + print(#function + "message did tap but type unknow") } } @@ -1820,16 +1991,42 @@ extension ChatViewController: ChatBaseCellDelegate { } public func didTapResendView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - if let msg = model?.message { + if playingCell?.messageId == model?.message?.messageId { + if playingCell?.isPlaying == true { + stopPlay() + } + } + if let m = model, let msg = m.message { + let messages = viewmodel.messages + var index = -1 + for i in 0 ..< messages.count { + if let message = messages[i].message { + if message.messageId == msg.messageId { + index = i + break + } + } + } + if index >= 0 { + viewmodel.messages.remove(at: index) + viewmodel.messages.append(m) + } viewmodel.resendMessage(message: msg) } } public func didTapReeditButton(_ cell: UITableViewCell, _ model: MessageContentModel?) { - if model?.type == .revoke, model?.message?.messageType == .text { + if model?.type == .revoke, model?.message?.messageType == .text, let message = model?.message { + let time = message.timestamp + let date = Date() + let currentTime = date.timeIntervalSince1970 + if currentTime - time >= 60 * 2 { + showToast(chatLocalizable("editable_time_expired")) + tableView.reloadData() + return + } menuView.textField.text = model?.message?.text menuView.textField.becomeFirstResponder() - let date = Date() } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/GroupChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/GroupChatViewController.swift index 22bd1eeb..f965207a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/GroupChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/GroupChatViewController.swift @@ -46,9 +46,20 @@ open class GroupChatViewController: ChatViewController, TeamChatViewModelDelegat if team.inAllMuteMode(), team.owner != NIMSDK.shared().loginManager.currentAccount() { menuView.textField.isEditable = false menuView.textField.placeholder = chatLocalizable("team_mute") as NSString? + layoutInputView(offset: 0) + menuView.stackView.isUserInteractionEnabled = false } else { menuView.textField.isEditable = true - menuView.textField.placeholder = (chatLocalizable("send_to") + team.getShowName()) as NSString? + let text = "\(chatLocalizable("send_to"))\(team.getShowName())" as NSString? +// let attribute = NSMutableAttributedString(string: text) +// let style = NSMutableParagraphStyle() +// style.lineBreakMode = .byTruncatingTail +// style.alignment = .left +// attribute.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, text.count)) +// attribute.addAttribute(.font, value: UIFont.systemFont(ofSize: 16), range: NSMakeRange(0, text.count)) +// attribute.addAttribute(.foregroundColor, value: UIColor.gray, range: NSMakeRange(0, text.count)) + menuView.textField.placeholder = text + menuView.stackView.isUserInteractionEnabled = true } } @@ -56,9 +67,24 @@ open class GroupChatViewController: ChatViewController, TeamChatViewModelDelegat public func onTeamRemoved(team: NIMTeam) { navigationController?.popViewController(animated: true) + + /* 后续优化逻辑,暂时不做修改 + if team.clientCustomInfo?.contains(discussTeamKey) == true { + navigationController?.popViewController(animated: true) + return + } + if team.teamId == viewmodel.session.sessionId { + weak var weakSelf = self + showSingleAlert(message: chatLocalizable("team_has_been_removed")) { + weakSelf?.navigationController?.popViewController(animated: true) + } + } */ } public func onTeamUpdate(team: NIMTeam) { + if team.teamId != viewmodel.session.sessionId { + return + } updateTeamInfo(team: team) } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/P2PChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/P2PChatViewController.swift index 8a7dbcb9..aa13d6a4 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/P2PChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/P2PChatViewController.swift @@ -20,6 +20,16 @@ open class P2PChatViewController: ChatViewController { title = showName titleContent = showName menuView.textField.placeholder = (chatLocalizable("send_to") + showName) as NSString? +// let text = "\(chatLocalizable("send_to"))\(showName))" +// menuView.textField.placeholder = text +// let attribute = NSMutableAttributedString(string: text) +// let style = NSMutableParagraphStyle() +// style.lineBreakMode = .byTruncatingTail +// style.alignment = .left +// attribute.addAttribute(.font, value: UIFont.systemFont(ofSize: 16), range: NSMakeRange(0, text.count)) +// attribute.addAttribute(.foregroundColor, value: UIColor.gray, range: NSMakeRange(0, text.count)) +// attribute.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, text.count)) +// menuView.textField.attributedPlaceholder = attribute } /// 创建个人聊天页构造方法 diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/SelectUserViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/SelectUserViewController.swift index 34141f4a..8cfc992b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/SelectUserViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/SelectUserViewController.swift @@ -5,7 +5,7 @@ import UIKit import NEChatKit - +import NECoreIMKit public typealias DidSelectedAtRow = (_ index: Int, _ model: ChatTeamMemberInfoModel?) -> Void @objcMembers @@ -16,10 +16,12 @@ public class SelectUserViewController: ChatBaseViewController, UITableViewDelega public var viewModel = TeamMemberSelectVM() public var selectedBlock: DidSelectedAtRow? var teamInfo: ChatTeamInfoModel? + private var showSelf = true // 是否展示自己 private let className = "SelectUserViewController" - init(sessionId: String) { + init(sessionId: String, showSelf: Bool = true) { self.sessionId = sessionId + self.showSelf = showSelf super.init(nibName: nil, bundle: nil) } @@ -114,6 +116,16 @@ public class SelectUserViewController: ChatBaseViewController, UITableViewDelega self?.view.makeToast(error?.localizedDescription) return } + + // 人员选择页面移除自己 + if !(self?.showSelf ?? true), + let users = team?.users { + for (index, user) in users.enumerated() { + if user.nimUser?.userId == IMKitLoginManager.instance.currentAccount() { + team?.users.remove(at: index) + } + } + } self?.teamInfo = team self?.tableView.reloadData() } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift index 126403f4..10c98694 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift @@ -4,7 +4,7 @@ // found in the LICENSE file. import UIKit - +import NECoreIMKit @objc public protocol InputEmoticonContainerViewDelegate: NSObjectProtocol { func selectedEmoticon(emoticonID: String, emotCatalogID: String, description: String) func didPressSend(sender: UIButton) diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift index 99938280..eaa66675 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift @@ -4,7 +4,7 @@ // found in the LICENSE file. import UIKit - +import NECoreIMKit @objc public protocol InputEmoticonTabViewDelegate: NSObjectProtocol { @objc optional func tabView(_ tabView: InputEmoticonTabView?, didSelectTabIndex index: Int) } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift index e8baa96c..524b4d04 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift @@ -4,7 +4,7 @@ // found in the LICENSE file. import UIKit - +import NECoreIMKit public protocol NIMInputEmoticonButtonDelegate: NSObjectProtocol { func selectedEmoticon(emotion: NIMInputEmoticon, catalogID: String) } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift index 08ea7fd6..132c9ca9 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift @@ -4,7 +4,7 @@ // found in the LICENSE file. import UIKit - +import NECoreIMKit public enum NIMEmoticonType: NSInteger { case file = 0 case unicode diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift index 29bfc3c4..d8f171dd 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift @@ -29,6 +29,53 @@ public class NotificationMessageUtils: NSObject { return "" } + public class func isDiscussSeniorTeamUpdateCustomNoti(message: NIMMessage) -> Bool { + if let object = message.messageObject as? NIMNotificationObject { + guard let content = object.content as? NIMTeamNotificationContent else { + return false + } + + // 转移讨论组的通知 + if content.operationType == .transferOwner, + teamName(message: message) == chatLocalizable("discussion_group") { + return true + } + + if content.operationType != .update { + return false + } + guard let attach = content.attachment as? NIMUpdateTeamInfoAttachment, + let tag = attach.values?.keys.first?.intValue else { + return false + } + + if tag == 18 || tag == 19 { + return true + } + } + return false + } + + public class func isTeamLeaveOrDismiss(message: NIMMessage) -> (isLeave: Bool, isDismiss: Bool) { + var leave = false + var dismiss = false + if let object = message.messageObject as? NIMNotificationObject, object.notificationType == .team { + if let content = object.content as? NIMTeamNotificationContent { + switch content.operationType { + case .leave: + leave = true + + case .dismiss: + dismiss = true + + @unknown default: + break + } + } + } + return (leave, dismiss) + } + public class func textForTeamNotificationMessage(message: NIMMessage) -> String { var text = chatLocalizable("unknown_system_message") if let object = message.messageObject as? NIMNotificationObject { @@ -96,7 +143,8 @@ public class NotificationMessageUtils: NSObject { if let atta = content.attachment as? NIMMuteSuperTeamMemberAttachment { mute = atta.flag } - text = mute ? chatLocalizable("team_all_mute") : chatLocalizable("team_all_no_mute") + // text = mute ? chatLocalizable("team_all_mute") : chatLocalizable("team_all_no_mute") + text = "\(toNamestext) \(mute ? chatLocalizable("mute") : chatLocalizable("not_mute"))" default: text = chatLocalizable("unknown_system_message") @@ -142,7 +190,7 @@ public class NotificationMessageUtils: NSObject { public class func teamName(message: NIMMessage) -> String { let team = TeamProvider.shared.teamInfo(teamId: message.session?.sessionId) - if team?.type == .normalTeam { + if team?.type == .normalTeam || (team?.type == .advancedTeam && team?.nimTeam?.clientCustomInfo?.contains(discussTeamKey) == true) { return chatLocalizable("discussion_group") } else { return chatLocalizable("group") @@ -152,55 +200,68 @@ public class NotificationMessageUtils: NSObject { private class func textOfUpdateTeam(fromName: String, teamName: String, content: NIMTeamNotificationContent) -> String { var text = fromName + chatLocalizable("has_updated") + teamName - guard let attach = content.attachment as? NIMUpdateTeamInfoAttachment else { - return text - } - if attach.values?.count == 1 { - let tag = attach.values?.keys.first?.intValue - switch tag { - case 3: - text = fromName + chatLocalizable("has_updated") + teamName + " " + - chatLocalizable("team_name") - case 14: - text = fromName + chatLocalizable("has_updated") + teamName + " " + - chatLocalizable("team_intro") - case 15: - text = fromName + chatLocalizable("has_updated") + teamName + " " + - chatLocalizable("team_anouncement") - case 16: - text = fromName + chatLocalizable("has_updated") + teamName + " " + - chatLocalizable("team_join_mode") - case 18: - text = fromName + chatLocalizable("has_updated") + " " + chatLocalizable("team_custom_info") - case 19: - text = fromName + chatLocalizable("has_updated") + " " + chatLocalizable("team_custom_info") - case 20: - text = fromName + chatLocalizable("has_updated") + teamName + " " + - chatLocalizable("team_avatar") - case 21: - text = fromName + chatLocalizable("has_updated") + " " + - chatLocalizable("team_be_invited_author") - case 22: - text = fromName + chatLocalizable("has_updated") + " " + - chatLocalizable("team_be_invited_permission") - case 23: - text = fromName + chatLocalizable("has_updated") + " " + - chatLocalizable("team_update_info_permission") - case 24: - text = fromName + chatLocalizable("has_updated") + " " + - chatLocalizable("team_update_client_custom") - case 100: - let muteState = attach.values?.values.first - - if muteState == "0" { - text = teamName + chatLocalizable("not_mute") - } else { - text = teamName + chatLocalizable("mute") + if let attach = content.attachment as? NIMUpdateTeamInfoAttachment { + if let tag = attach.values?.keys.first?.intValue { + let string = getShowString(fromName, teamName, tag, attach.values?.values.first) + if string.count > 0 { + text = string } - default: - text = fromName + chatLocalizable("has_updated") + teamName } } + if let attach = content.attachment as? NIMMuteTeamMemberAttachment { + if attach.flag == false { + text = teamName + chatLocalizable("team_all_mute") + } else { + text = teamName + chatLocalizable("team_all_no_mute") + } + } + return text + } + + private class func getShowString(_ fromName: String, _ teamName: String, _ tag: Int, _ muteState: String?) -> String { + var text = "" + switch tag { + case 3: + text = fromName + chatLocalizable("has_updated") + teamName + " " + + chatLocalizable("team_name") + case 14: + text = fromName + chatLocalizable("has_updated") + teamName + " " + + chatLocalizable("team_intro") + case 15: + text = fromName + chatLocalizable("has_updated") + teamName + " " + + chatLocalizable("team_anouncement") + case 16: + text = fromName + chatLocalizable("has_updated") + teamName + " " + + chatLocalizable("team_join_mode") + case 18: + text = fromName + chatLocalizable("has_updated") + " " + chatLocalizable("team_custom_info") + case 19: + text = fromName + chatLocalizable("has_updated") + " " + chatLocalizable("team_custom_info") + case 20: + text = fromName + chatLocalizable("has_updated") + teamName + " " + + chatLocalizable("team_avatar") + case 21: + text = fromName + chatLocalizable("has_updated") + " " + + chatLocalizable("team_be_invited_author") + case 22: + text = fromName + chatLocalizable("has_updated") + " " + + chatLocalizable("team_be_invited_permission") + case 23: + text = fromName + chatLocalizable("has_updated") + " " + + chatLocalizable("team_update_info_permission") + case 24: + text = fromName + chatLocalizable("has_updated") + " " + + chatLocalizable("team_update_client_custom") + case 100: + + if muteState == "1" || muteState == "3" { + text = chatLocalizable("team_all_mute") + } else if muteState == "0" { + text = chatLocalizable("team_all_no_mute") + } + default: + text = fromName + chatLocalizable("has_updated") + teamName + } return text } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/ReplyMessageUtil.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/ReplyMessageUtil.swift index 2ce4891e..bc62c91f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/ReplyMessageUtil.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/ReplyMessageUtil.swift @@ -16,6 +16,8 @@ public class ReplyMessageUtil: NSObject { case .text: if let t = model.message?.text { text += t + } else { + text = chatLocalizable("message_not_found") } case .image: text += "[\(chatLocalizable("msg_image"))]" diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift new file mode 100644 index 00000000..e5f11880 --- /dev/null +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift @@ -0,0 +1,76 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +import UIKit +import NIMSDK + +@objcMembers +class MessageCallRecordModel: MessageContentModel { + public var attributeStr: NSMutableAttributedString? + + required init(message: NIMMessage?) { + super.init(message: message) + type = .rtcCallRecord + var isAuiodRecord = false + if let object = message?.messageObject as? NIMRtcCallRecordObject, let isSend = message?.isOutgoingMsg { + attributeStr = NSMutableAttributedString() + var image: UIImage? + var bound = CGRect.zero + let offset: CGFloat = -1 + if object.callType == .audio { + isAuiodRecord = true + image = coreLoader.loadImage("audio_record") + bound = CGRect(x: 0, y: offset - 5, width: 24, height: 24) + } else { + image = coreLoader.loadImage("video_record") + bound = CGRect(x: 0, y: offset, width: 24, height: 14) + } + switch object.callStatus { + case .complete: + var timeString = "00:00" + if let duration = object.durations[NIMSDK.shared().loginManager.currentAccount()] { + timeString = Date.getFormatPlayTime(duration.doubleValue) + } + attributeStr?.append(NSAttributedString(string: chatLocalizable("call_complete") + " \(timeString)")) + case .canceled: + attributeStr?.append(NSAttributedString(string: chatLocalizable("call_canceled"))) + case .rejected: + attributeStr?.append(NSAttributedString(string: chatLocalizable("call_rejected"))) + case .timeout: + attributeStr?.append(NSAttributedString(string: chatLocalizable("call_timeout"))) + case .busy: + attributeStr?.append(NSAttributedString(string: chatLocalizable("call_busy"))) + default: + break + } + let attachment = NSTextAttachment() + attachment.image = image + attachment.bounds = bound + if isSend { + attributeStr?.append(NSAttributedString(string: " ")) + attributeStr?.append(NSAttributedString(attachment: attachment)) + } else { + attributeStr?.insert(NSAttributedString(string: " "), at: 0) + attributeStr?.insert(NSAttributedString(attachment: attachment), at: 0) + } + + attributeStr?.addAttribute(NSAttributedString.Key.font, value: NEKitChatConfig.shared.ui.messageFont, range: NSMakeRange(0, attributeStr?.length ?? 0)) + + attributeStr?.addAttribute(NSAttributedString.Key.foregroundColor, value: NEKitChatConfig.shared.ui.messageColor, range: NSMakeRange(0, attributeStr?.length ?? 0)) + } + + let textSize = NEChatUITool.getSizeWithAtt( + att: attributeStr ?? NSAttributedString(string: ""), + font: DefaultTextFont(16), + maxSize: CGSize(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude) + ) + + var h = qChat_min_h + h = textSize.height + (isAuiodRecord ? 20 : 24) + contentSize = CGSize(width: textSize.width + qChat_cell_margin * 2, height: h) + + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } +} diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift index 9fe2c65b..feb91336 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift @@ -11,6 +11,8 @@ import NECoreIMKit @objcMembers public class MessageContentModel: NSObject, MessageModel { + public var isReplay: Bool = false + public var pinAccount: String? public var pinShowName: String? public var type: MessageType = .custom @@ -27,7 +29,7 @@ public class MessageContentModel: NSObject, MessageModel { public var replyedModel: MessageModel? { didSet { - if let reply = replyedModel as? MessageContentModel { + if let reply = replyedModel as? MessageContentModel, reply.isReplay == true { replyText = ReplyMessageUtil.textForReplyModel(model: reply) if let t = replyText { let size = String.getTextRectSize( @@ -62,12 +64,12 @@ public class MessageContentModel: NSObject, MessageModel { if let time = message?.timestamp { let date = Date() let currentTime = date.timeIntervalSince1970 - if currentTime - time > 60 * 5 { + if currentTime - time > 60 * 2 { timeOut = true } } // 只有文本消息,才计算可编辑按钮的宽度 - if let isSend = message?.isOutgoingMsg, isSend, message?.messageType == .text, isRevokedText == true, timeOut == false { + if let isSend = message?.isOutgoingMsg, isSend, message?.messageType == .text, timeOut == false { contentSize = CGSize(width: 218, height: qChat_min_h) } else { contentSize = CGSize(width: 130, height: qChat_min_h) diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageModel.swift index f47d6fe8..45c68297 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageModel.swift @@ -45,6 +45,7 @@ public protocol MessageModel: NSObjectProtocol { var replyedModel: MessageModel? { get set } var replyText: String? { get set } var isRevokedText: Bool { get set } + var isReplay: Bool { get set } init(message: NIMMessage?) } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTextModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTextModel.swift index 2db36b99..d8222142 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTextModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTextModel.swift @@ -8,13 +8,12 @@ import NIMSDK @objcMembers class MessageTextModel: MessageContentModel { -// public var text: String? public var attributeStr: NSAttributedString? required init(message: NIMMessage?) { super.init(message: message) type = .text -// text = message?.text + attributeStr = NEEmotionTool.getAttWithStr( str: message?.text ?? "", font: NEKitChatConfig.shared.ui.messageFont @@ -35,6 +34,6 @@ class MessageTextModel: MessageContentModel { height = Float(contentSize.height + qChat_margin) + fullNameHeight - print(">>text:\(message?.text) height:\(height)") +// print(">>text:\(message?.text) height:\(height)") } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTipsModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTipsModel.swift index 4e43e367..5b24c458 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTipsModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageTipsModel.swift @@ -8,6 +8,12 @@ import NIMSDK @objcMembers class MessageTipsModel: NSObject, MessageModel { + var tipTimeStamp: TimeInterval? + + var isReplay: Bool = false + + var pinToAccount: String? + var pinFromAccount: String? var isPined: Bool = false var pinAccount: String? var pinShowName: String? @@ -23,6 +29,7 @@ class MessageTipsModel: NSObject, MessageModel { var isRevoked: Bool = false var replyedModel: MessageModel? var isRevokedText: Bool = false + weak var tipMessage: NIMMessage? required init(message: NIMMessage?) { if let msg = message { if msg.messageType == .notification { @@ -33,6 +40,8 @@ class MessageTipsModel: NSObject, MessageModel { type = .tip } } + tipMessage = message + tipTimeStamp = message?.timestamp contentSize = CGSize(width: kScreenWidth, height: 35) height = 35 } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift index 449493ed..0b1518c3 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift @@ -1,6 +1,3 @@ -// -// NEMoreItemModel.swift -// NEChatUIKit // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be @@ -20,11 +17,20 @@ public enum NEMoreActionType: Int { public class NEMoreItemModel: NSObject { // 单元图标 - var image: UIImage? + public var image: UIImage? // 单元名称 - var title: String? + public var title: String? // 对应的单元类型 - var type: NEMoreActionType? + public var type: NEMoreActionType? + + // 代理类 + public var customDelegate: AnyObject? + + // 动态事件 + public var action: Selector? + + // 自定义图标 + public var customImage: UIImage? } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioLeftCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioLeftCell.swift index cec68640..03acf188 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioLeftCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioLeftCell.swift @@ -10,7 +10,7 @@ public class ChatAudioLeftCell: ChatBaseLeftCell, ChatAudioCell { var isPlaying: Bool = false var audioImageView = UIImageView(image: UIImage.ne_imageNamed(name: "left_play_3")) var timeLabel = UILabel() - + var messageId: String? override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) commonUI() @@ -69,6 +69,7 @@ public class ChatAudioLeftCell: ChatBaseLeftCell, ChatAudioCell { if let m = model as? MessageAudioModel { timeLabel.text = "\(m.duration)" + "s" m.isPlaying ? startAnimation() : stopAnimation() + messageId = m.message?.messageId } } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioRightCell.swift index 3c32eb97..d0c1dfff 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioRightCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatAudioRightCell.swift @@ -7,12 +7,14 @@ import UIKit protocol ChatAudioCell { var isPlaying: Bool { get set } + var messageId: String? { get set } func startAnimation() func stopAnimation() } @objcMembers public class ChatAudioRightCell: ChatBaseRightCell, ChatAudioCell { + var messageId: String? var isPlaying: Bool = false var audioImageView = UIImageView(image: UIImage.ne_imageNamed(name: "audio_play")) var timeLabel = UILabel() @@ -81,6 +83,7 @@ public class ChatAudioRightCell: ChatBaseRightCell, ChatAudioCell { if let m = model as? MessageAudioModel { timeLabel.text = "\(m.duration)" + "s" m.isPlaying ? startAnimation() : stopAnimation() + messageId = m.message?.messageId } } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseLeftCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseLeftCell.swift index 5fba75b9..9a70b02f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseLeftCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseLeftCell.swift @@ -4,7 +4,7 @@ // found in the LICENSE file. import UIKit - +import NIMSDK @objcMembers public class ChatBaseLeftCell: ChatBaseCell { public var avatarImage = UIImageView() @@ -127,7 +127,6 @@ public class ChatBaseLeftCell: ChatBaseCell { contentView.addSubview(pinLabel) pinLabel.translatesAutoresizingMaskIntoConstraints = false pinLabel.textAlignment = .left -// pinLabel.text = localizable("pin_text") pinLabel.font = UIFont.systemFont(ofSize: 12) pinLabel.textColor = UIColor.ne_greenText pinLabel.isHidden = true @@ -213,7 +212,7 @@ public class ChatBaseLeftCell: ChatBaseCell { } fullNameH?.constant = CGFloat(model.fullNameHeight) avatarImage.backgroundColor = UIColor - .colorWithNumber(number: UInt64(model.message?.from ?? "0")) + .colorWithString(string: model.message?.from) if let avatarURL = model.avatar { avatarImage .sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in @@ -246,9 +245,15 @@ public class ChatBaseLeftCell: ChatBaseCell { contentView.backgroundColor = model.isPined ? NEKitChatConfig.shared.ui .chatPinColor : .white if model.isPined { - if let text = model.pinShowName { - pinLabel.text = text + chatLocalizable("pin_text") + let pinText = model.message?.session?.sessionType == .P2P ? chatLocalizable("pin_text_P2P") : chatLocalizable("pin_text_team") + if model.pinAccount == nil { + pinLabel.text = chatLocalizable("You") + pinText + } else if let account = model.pinAccount, account == NIMSDK.shared().loginManager.currentAccount() { + pinLabel.text = chatLocalizable("You") + pinText + } else if let text = model.pinShowName { + pinLabel.text = text + pinText } + pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") pinLabelH?.constant = chat_pin_height diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseRightCell.swift index bfb55187..42d3c03c 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseRightCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatBaseRightCell.swift @@ -6,7 +6,7 @@ import UIKit import NECoreIMKit import NECoreKit - +import NIMSDK public protocol ChatBaseCellDelegate: NSObjectProtocol { func didTapAvatarView(_ cell: UITableViewCell, _ model: MessageContentModel?) func didTapMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) @@ -252,7 +252,7 @@ public class ChatBaseRightCell: ChatBaseCell { // avatar nameLabel.text = model.shortName avatarImage.backgroundColor = UIColor - .colorWithNumber(number: UInt64(model.message?.from ?? "0")) + .colorWithString(string: model.message?.from) if let avatarURL = model.avatar { avatarImage .sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in @@ -284,7 +284,8 @@ public class ChatBaseRightCell: ChatBaseCell { if model.message?.deliveryState == .deliveried { if model.message?.session?.sessionType == .P2P { let receiptEnable = model.message?.setting?.teamReceiptEnabled ?? false - if receiptEnable { + if receiptEnable, + IMKitClient.instance.repo.getShowReadStatus() == true { readView.isHidden = false if let read = model.message?.isRemoteRead, read { readView.progress = 1 @@ -304,7 +305,8 @@ public class ChatBaseRightCell: ChatBaseCell { } else if model.message?.session?.sessionType == .team { let receiptEnable = model.message?.setting?.teamReceiptEnabled ?? false - if receiptEnable { + if receiptEnable, + IMKitClient.instance.repo.getShowReadStatus() == true { readView.isHidden = false let readCount = model.message?.teamReceiptInfo?.readCount ?? 0 let unreadCount = model.message?.teamReceiptInfo?.unreadCount ?? 0 @@ -333,16 +335,22 @@ public class ChatBaseRightCell: ChatBaseCell { contentView.backgroundColor = model.isPined ? NEKitChatConfig.shared.ui .chatPinColor : .white if model.isPined { - if let text = model.pinShowName { - pinLabel.text = text + chatLocalizable("pin_text") + let pinText = model.message?.session?.sessionType == .P2P ? chatLocalizable("pin_text_P2P") : chatLocalizable("pin_text_team") + if model.pinAccount == nil { + pinLabel.text = chatLocalizable("You") + pinText + } else if let account = model.pinAccount, account == NIMSDK.shared().loginManager.currentAccount() { + pinLabel.text = chatLocalizable("You") + pinText + } else if let text = model.pinShowName { + pinLabel.text = text + pinText } + pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") let size = String.getTextRectSize( - pinLabel.text ?? chatLocalizable("pin_text"), - font: UIFont.systemFont(ofSize: 11.0), + pinLabel.text ?? pinText, + font: UIFont.systemFont(ofSize: 12.0), size: CGSize(width: kScreenWidth - 56 - 22, height: CGFloat.greatestFiniteMagnitude) ) - pinLabelW?.constant = size.width + pinLabelW?.constant = size.width + 1 pinLabelH?.constant = chat_pin_height } else { pinImage.image = nil diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatCallRecordLeftCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatCallRecordLeftCell.swift new file mode 100644 index 00000000..9171d6e2 --- /dev/null +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatCallRecordLeftCell.swift @@ -0,0 +1,41 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +import UIKit + +@objcMembers +class ChatCallRecordLeftCell: ChatBaseLeftCell { + public let contentLabel = UILabel() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func commonUI() { + contentLabel.translatesAutoresizingMaskIntoConstraints = false + contentLabel.isEnabled = false + contentLabel.numberOfLines = 0 + contentLabel.isUserInteractionEnabled = false + contentLabel.font = DefaultTextFont(16) + contentLabel.backgroundColor = .clear + bubbleImage.addSubview(contentLabel) + NSLayoutConstraint.activate([ + contentLabel.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + contentLabel.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), + contentLabel.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + contentLabel.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageCallRecordModel { + contentLabel.attributedText = m.attributeStr + } + } +} diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatCallRecordRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatCallRecordRightCell.swift new file mode 100644 index 00000000..0d710927 --- /dev/null +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatCallRecordRightCell.swift @@ -0,0 +1,43 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +import UIKit + +@objcMembers +class ChatCallRecordRightCell: ChatBaseRightCell { + public let contentLabel = UILabel() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func commonUI() { + contentLabel.translatesAutoresizingMaskIntoConstraints = false + contentLabel.isEnabled = false + contentLabel.numberOfLines = 0 + contentLabel.isUserInteractionEnabled = false + contentLabel.font = DefaultTextFont(16) + contentLabel.backgroundColor = .clear + bubbleImage.addSubview(contentLabel) + NSLayoutConstraint.activate([ + contentLabel.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + contentLabel.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), + contentLabel.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + contentLabel.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + + activityView.removeFromSuperview() + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageCallRecordModel { + contentLabel.attributedText = m.attributeStr + } + } +} diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationLeftCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationLeftCell.swift index 1f9d0496..43038c2f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationLeftCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationLeftCell.swift @@ -5,6 +5,7 @@ import UIKit import NEChatKit +@objcMembers class ChatLocationLeftCell: ChatBaseLeftCell { private lazy var titleLabel: UILabel = { let label = UILabel() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationRightCell.swift index 6c036746..31f39d9a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationRightCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatLocationRightCell.swift @@ -5,6 +5,7 @@ import UIKit import NEChatKit +@objcMembers class ChatLocationRightCell: ChatBaseRightCell { private lazy var titleLabel: UILabel = { let label = UILabel() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatRevokeRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatRevokeRightCell.swift index 2c3223bd..61e2010a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatRevokeRightCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatRevokeRightCell.swift @@ -57,10 +57,22 @@ public class ChatRevokeRightCell: ChatBaseRightCell { } override func setModel(_ model: MessageContentModel) { + if let time = model.message?.timestamp { + let date = Date() + let currentTime = date.timeIntervalSince1970 + if currentTime - time >= 60 * 2 { + model.timeOut = true + } + } + if let isSend = model.message?.isOutgoingMsg, isSend, model.isRevokedText == true, model.timeOut == false { + model.contentSize = CGSize(width: 218, height: qChat_min_h) + } else { + model.contentSize = CGSize(width: 130, height: qChat_min_h) + } super.setModel(model) label.text = chatLocalizable("message_has_be_withdrawn") reeditButton.setTitle(chatLocalizable("message_reedit"), for: .normal) - // 判断可编辑按钮的隐藏,只有文本才可以重新编辑 + if model.isRevokedText == true { if model.timeOut == true { reeditButton.isHidden = true diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTeamMemberCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTeamMemberCell.swift index 65f727fa..a9315cc1 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTeamMemberCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTeamMemberCell.swift @@ -69,6 +69,6 @@ public class ChatTeamMemberCell: UITableViewCell { headerView.setTitle(model.showNameInTeam()) headerView.backgroundColor = UIColor.colorWithString(string: model.nimUser?.userId) } - nameLabel.text = model.showNameInTeam() + nameLabel.text = model.atNameInTeam() } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextLeftCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextLeftCell.swift index 97314f0b..cf17888d 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextLeftCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextLeftCell.swift @@ -20,14 +20,9 @@ public class ChatTextLeftCell: ChatBaseLeftCell { func commonUI() { contentLabel.translatesAutoresizingMaskIntoConstraints = false contentLabel.isEnabled = false -// textView.isScrollEnabled = false -// textView.showsVerticalScrollIndicator = false contentLabel.numberOfLines = 0 contentLabel.isUserInteractionEnabled = false -// textView.textContainer.lineFragmentPadding = 0; -// textView.textContainerInset = .zero; contentLabel.font = DefaultTextFont(16) -// textView.autoresizingMask = [.flexibleWidth, .flexibleHeight] contentLabel.backgroundColor = .clear bubbleImage.addSubview(contentLabel) NSLayoutConstraint.activate([ @@ -41,7 +36,6 @@ public class ChatTextLeftCell: ChatBaseLeftCell { override func setModel(_ model: MessageContentModel) { super.setModel(model) if let m = model as? MessageTextModel { -// textView.text = m.text contentLabel.attributedText = m.attributeStr } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextRightCell.swift index c9e21f05..66e3e35d 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextRightCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatTextRightCell.swift @@ -35,7 +35,6 @@ public class ChatTextRightCell: ChatBaseRightCell { override func setModel(_ model: MessageContentModel) { super.setModel(model) if let m = model as? MessageTextModel { -// textView.text = m.text contentLabel.attributedText = m.attributeStr } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatVideoRightCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatVideoRightCell.swift index 06a8039a..67f1c102 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatVideoRightCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/ChatVideoRightCell.swift @@ -89,7 +89,7 @@ public class ChatVideoRightCell: ChatImageRightCell { override func setModel(_ model: MessageContentModel) { super.setModel(model) if let videoObject = model.message?.messageObject as? NIMVideoObject { - if let path = videoObject.coverPath { + if let path = videoObject.coverPath, FileManager.default.fileExists(atPath: path) { contentImageView.sd_setImage( with: URL(fileURLWithPath: path), placeholderImage: nil, diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatInputView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatInputView.swift index 9f84b028..2139f66a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatInputView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatInputView.swift @@ -34,7 +34,7 @@ public protocol ChatInputViewDelegate: NSObjectProtocol { } @objcMembers -public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, +public class ChatInputView: UIView, ChatRecordViewDelegate, InputEmoticonContainerViewDelegate, UITextViewDelegate, NEMoreViewDelagate { public weak var delegate: ChatInputViewDelegate? public var currentType: ChatMenuType = .text @@ -43,10 +43,12 @@ public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, public var atCache: NIMInputAtCache? var textField = RSKPlaceholderTextView() + var stackView = UIStackView() var contentView = UIView() public var contentSubView: UIView? private var greyView = UIView() private var recordView = ChatRecordView(frame: .zero) + override init(frame: CGRect) { super.init(frame: frame) commonUI() @@ -67,9 +69,7 @@ public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, textField.clipsToBounds = true textField.translatesAutoresizingMaskIntoConstraints = false textField.backgroundColor = .white - // textField.leftViewMode = .always textField.returnKeyType = .send - // textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 40)) textField.delegate = self textField.allowsEditingTextAttributes = true addSubview(textField) @@ -98,7 +98,8 @@ public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, button.tag = i + 5 items.append(button) } - let stackView = UIStackView(arrangedSubviews: items) + + stackView = UIStackView(arrangedSubviews: items) stackView.translatesAutoresizingMaskIntoConstraints = false stackView.distribution = .fillEqually addSubview(stackView) @@ -244,7 +245,6 @@ public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, public lazy var chatAddMoreView: NEChatMoreActionView = { let view = NEChatMoreActionView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 200)) view.translatesAutoresizingMaskIntoConstraints = false - view.configData(data: NEChatUIKitClient.instance.getMoreActionData()) view.isHidden = true view.delegate = self return view @@ -297,28 +297,6 @@ public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, return true } - public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - guard let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) else { - return true - } - textField.text = "" - delegate?.sendText(text: text) - return true - } - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - print("range:\(range) string:\(string)") - if string.count == 0 { - if let delegate = delegate { - return delegate.textDelete(range: range, text: string) - } - } else { - delegate?.textChanged(text: string) - } - return true - } - func buttonEvent(button: UIButton) { switch button.tag - 5 { case 0: diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatRecordView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatRecordView.swift index 7881dd02..d6345e72 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatRecordView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatRecordView.swift @@ -78,7 +78,7 @@ public class ChatRecordView: UIView, UIGestureRecognizerDelegate { } func clickLabel(recognizer: UILongPressGestureRecognizer) { - print("location:\(recognizer.location(in: recognizer.view))") +// print("location:\(recognizer.location(in: recognizer.view))") switch recognizer.state { case .began: print("state:begin") @@ -88,8 +88,10 @@ public class ChatRecordView: UIView, UIGestureRecognizerDelegate { case .ended: endRecord(recognizer: recognizer) case .cancelled: + endRecord(recognizer: recognizer) print("state:cancelled") case .failed: + endRecord(recognizer: recognizer) print("state:failed") default: print("state:default") diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift index b87f6014..bfaef7ac 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift @@ -46,16 +46,16 @@ public class NEInputMoreCell: UICollectionViewCell { lazy var titleLabel: UILabel = { let title = UILabel() title.textColor = UIColor.ne_greyText - title.font = UIFont.systemFont(ofSize: 12) + title.font = UIFont.systemFont(ofSize: 10) title.textAlignment = .center title.translatesAutoresizingMaskIntoConstraints = false return title }() - func config(_ itmeModel: NEMoreItemModel) { - cellData = itmeModel - avatarImage.image = itmeModel.image - titleLabel.text = itmeModel.title + func config(_ itemModel: NEMoreItemModel) { + cellData = itemModel + avatarImage.image = itemModel.customImage == nil ? itemModel.image : itemModel.customImage + titleLabel.text = itemModel.title } /// 获取大小 diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift index 3a29ddfe..fd31137b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift @@ -30,6 +30,8 @@ public protocol ChatViewModelDelegate: NSObjectProtocol { func updateDownloadProgress(_ message: NIMMessage, atIndex: IndexPath, progress: Float) func remoteUserEditing() func remoteUserEndEditing() + func didLeaveTeam() + func didDismissTeam() } let revokeLocalMessage = "revoke_message_local" @@ -38,9 +40,11 @@ let revokeLocalMessageContent = "revoke_message_local_content" @objcMembers public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDelegate, NIMConversationManagerDelegate, NIMSystemNotificationManagerDelegate, ChatExtendProviderDelegate { + public var team: NIMTeam? public var session: NIMSession - public var messages: [MessageModel] = .init() + public var messages = [MessageModel]() public weak var delegate: ChatViewModelDelegate? + public var messageDic = [String: MessageModel]() // 上拉时间戳 private var newMsg: NIMMessage? // 下拉时间戳 @@ -58,6 +62,8 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel public var isHistoryChat = false + public var filterInviteSet = Set() + init(session: NIMSession) { NELog.infoLog(ModuleName + " " + className, desc: #function + ", sessionId:" + session.sessionId) self.session = session @@ -154,26 +160,85 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel ) } - public func queryRoamMsgHasMoreTime(_ completion: @escaping (Error?, NSInteger, - [MessageModel]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) -// NIMIncompleteSessionInfo + // 动态查询历史消息解决方案 + public func getMessagesModelDynamically(_ order: NIMMessageSearchOrder, message: NIMMessage?, + _ completion: @escaping (Error?, NSInteger, [MessageModel]?) + -> Void) { + let param = NIMGetMessagesDynamicallyParam() + param.limit = messagPageNum + param.session = session + param.order = order + if let msg = message { + if order == .desc { + param.endTime = msg.timestamp + } else { + param.startTime = msg.timestamp + } + param.anchorClientId = msg.messageId + param.anchorServerId = msg.serverID + } weak var weakSelf = self - repo.getIncompleteSessionInfo(session: session) { error, sessionInfos in - if error == nil { - let sessionInfo = sessionInfos?.first - // 记录可信时间戳 - weakSelf?.credibleTimestamp = sessionInfo?.timestamp ?? 0 - if weakSelf?.anchor == nil { - weakSelf?.getMessageHistory(self.oldMsg, completion) - + repo.getMessagesDynamically(param) { error, isReliable, messages in + if let messageArray = messages, messageArray.count > 0 { + var count = 0 + var datas = messageArray + var readMsg: NIMMessage? + if order == .desc { + weakSelf?.oldMsg = messageArray.last + readMsg = messageArray.first } else { - // 有锚点消息,从两个方向拉去消息 - weakSelf?.newMsg = weakSelf?.anchor - weakSelf?.oldMsg = weakSelf?.anchor - weakSelf?.dropDownRemoteRefresh(completion) - weakSelf?.pullRemoteRefresh(completion) + readMsg = messageArray.last + weakSelf?.newMsg = messageArray.last + } + for msg in datas { + if let object = msg.messageObject as? NIMNotificationObject { + if let content = object.content as? NIMTeamNotificationContent, content.operationType == .invite { + if weakSelf?.filterInviteSet.contains(msg.messageId) == true { + continue + } else { + weakSelf?.filterInviteSet.insert(msg.messageId) + } + } + } + print("message text : ", msg.text as Any) + if let model = weakSelf?.modelFromMessage(message: msg), NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: msg) == false { + weakSelf?.filterRevokeMessage([model]) + if order == .desc { + if weakSelf?.addTimeForHistoryMessage(msg) == true { + count = count + 1 + } + count = count + 1 + weakSelf?.messages.insert(model, at: 0) + } else { + if weakSelf?.addTimeMessage(msg) == true { + count = count + 1 + } + count = count + 1 + weakSelf?.messages.append(model) + } + } + } + completion(error, count, weakSelf?.messages) + + if weakSelf?.session.sessionType == .P2P { + if let nearMsg = readMsg { + weakSelf?.markRead(messages: [nearMsg]) { error in + NELog.infoLog( + ModuleName + " " + (weakSelf?.className ?? "ChatViewModel"), + desc: "CALLBACK markRead " + (error?.localizedDescription ?? "no error") + ) + } + } + } else if weakSelf?.session.sessionType == .team { + weakSelf?.markRead(messages: messageArray) { error in + NELog.infoLog( + ModuleName + " " + (weakSelf?.className ?? "ChatViewModel"), + desc: "CALLBACK markRead " + (error?.localizedDescription ?? "no error") + ) + } } + } else { + completion(error, 0, weakSelf?.messages) } } } @@ -182,78 +247,73 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel [MessageModel]?, Int) -> Void) { NELog.infoLog(ModuleName + " " + className, desc: #function) weak var weakSelf = self - repo.getIncompleteSessionInfo(session: session) { error, sessionInfos in - if error == nil { - let sessionInfo = sessionInfos?.first - // 记录可信时间戳 - weakSelf?.credibleTimestamp = sessionInfo?.timestamp ?? 0 - if weakSelf?.anchor == nil { - weakSelf?.getMessageHistory(self.newMsg) { error, value, models in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK getMessageHistory " + (error?.localizedDescription ?? "no error") - ) - completion(error, value, 0, models, 0) - } - } else { - // 有锚点消息,从两个方向拉去消息 - weakSelf?.newMsg = weakSelf?.anchor - weakSelf?.oldMsg = weakSelf?.anchor - - let group = DispatchGroup() - - var moreEnd = 0 - var newEnd = 0 - var historyDatas = [MessageModel]() - var newDatas = [MessageModel]() - - var err: Error? + // 记录可信时间戳 + if anchor == nil { + weakSelf?.getMessagesModelDynamically(.desc, message: nil) { error, count, models in + NELog.infoLog( + ModuleName + " " + self.className, + desc: "CALLBACK getMessageHistory " + (error?.localizedDescription ?? "no error") + ) + completion(error, count, 0, models, 0) + } - group.enter() - weakSelf?.dropDownRemoteRefresh { error, value, models in + } else { + // 有锚点消息,从两个方向拉去消息 + weakSelf?.newMsg = weakSelf?.anchor + weakSelf?.oldMsg = weakSelf?.anchor + + let group = DispatchGroup() + + var moreEnd = 0 + var newEnd = 0 + var historyDatas = [MessageModel]() + var newDatas = [MessageModel]() + + var err: Error? + group.enter() + weakSelf?.getMessagesModelDynamically(.desc, message: weakSelf?.anchor) { error, value, models in + moreEnd = value + if error != nil { + err = error + } + if let ms = models { + historyDatas.append(contentsOf: ms) + } + print("drop down remote refresh : ", historyDatas.count) + group.leave() + } - moreEnd = value - if error != nil { - err = error - } - if let ms = models { - historyDatas.append(contentsOf: ms) - } - print("drop down remote refresh : ", historyDatas.count) - group.leave() - } + group.enter() + weakSelf?.getMessagesModelDynamically(.asc, message: weakSelf?.anchor) { error, value, models in + NELog.infoLog( + ModuleName + " " + self.className, + desc: "CALLBACK pullRemoteRefresh " + (error?.localizedDescription ?? "no error") + ) + newEnd = value + if err != nil { + err = error + } + if let ms = models { + newDatas.append(contentsOf: ms) + } + print("pull remote refresh : ", newDatas.count) + group.leave() + } - group.enter() - weakSelf?.pullRemoteRefresh { error, value, models in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK pullRemoteRefresh " + (error?.localizedDescription ?? "no error") - ) - newEnd = value - if err != nil { - err = error - } - if let ms = models { - newDatas.append(contentsOf: ms) - } - print("pull remote refresh : ", newDatas.count) - group.leave() + group.notify(queue: DispatchQueue.main, execute: { + var finalDatas = [MessageModel]() + finalDatas.append(contentsOf: historyDatas) + if let anchorMessage = weakSelf?.anchor { + let model = self.modelFromMessage(message: anchorMessage) + weakSelf?.filterRevokeMessage([model]) + if NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: anchorMessage) == false { + weakSelf?.messages.insert(model, at: moreEnd) + finalDatas.append(model) } - - group.notify(queue: DispatchQueue.main, execute: { - var finalDatas = [MessageModel]() - finalDatas.append(contentsOf: historyDatas) - if let anchorMessage = weakSelf?.anchor { - let model = self.modelFromMessage(message: anchorMessage) - weakSelf?.filterRevokeMessage([model]) - weakSelf?.messages.insert(model, at: historyDatas.count) - finalDatas.append(model) - } - finalDatas.append(contentsOf: newDatas) - completion(err, moreEnd, newEnd, finalDatas, historyDatas.count) - }) } - } + finalDatas.append(contentsOf: newDatas) + completion(err, moreEnd, newEnd, finalDatas, historyDatas.count) + }) } } @@ -270,8 +330,8 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel if let messageArray = messages, messageArray.count > 0 { self?.oldMsg = messageArray.first for msg in messageArray { - self?.addTimeMessage(msg) - if let model = self?.modelFromMessage(message: msg) { + if let model = self?.modelFromMessage(message: msg), NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: msg) == false { + self?.addTimeMessage(msg) self?.filterRevokeMessage([model]) self?.messages.append(model) } @@ -313,8 +373,8 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel .isMessageCredible(message: messageArray.first ?? NIMMessage()) if let isTrust = isCredible, isTrust { for msg in messageArray.reversed() { - self?.addTimeForHistoryMessage(msg) - if let model = self?.modelFromMessage(message: msg) { + if let model = self?.modelFromMessage(message: msg), NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: msg) == false { + self?.addTimeForHistoryMessage(msg) self?.messages.insert(model, at: 0) } } @@ -378,8 +438,8 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel weakSelf?.newMsg = messageArray.first } for msg in messageArray { - weakSelf?.addTimeForHistoryMessage(msg) - if let model = weakSelf?.modelFromMessage(message: msg) { + if let model = weakSelf?.modelFromMessage(message: msg), NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: msg) == false { + weakSelf?.addTimeForHistoryMessage(msg) weakSelf?.messages.insert(model, at: 0) } } @@ -398,11 +458,9 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel } } completion(error, messageArray.count, weakSelf?.messages) - } else { completion(error, 0, weakSelf?.messages) } - } else { completion(error, 0, nil) } @@ -412,55 +470,19 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel // 下拉获取历史消息 public func dropDownRemoteRefresh(_ completion: @escaping (Error?, NSInteger, [MessageModel]?) -> Void) { + getMessagesModelDynamically(.desc, message: oldMsg, completion) NELog.infoLog(ModuleName + " " + className, desc: #function) - // completion(nil, true, nil) - let option = NIMHistoryMessageSearchOption() - option.startTime = 0 - option.endTime = oldMsg?.timestamp ?? 0 - option.limit = messagPageNum - option.sync = true - let isCredible = isMessageCredible(message: oldMsg ?? NIMMessage()) - if isCredible { // 继续拉去本地消息 - getMoreMessageHistory(completion) - } else { - // 不可信拉去远端消息 - getRemoteHistoryMessage( - direction: .old, - updateCredible: false, - option: option, - completion - ) - } } // 上拉获取最新消息 public func pullRemoteRefresh(_ completion: @escaping (Error?, NSInteger, [MessageModel]?) -> Void) { +// var message = messages.last?.message +// if message == nil, let tip = messages.last as? MessageTipsModel { +// message = tip.tipMessage +// } + getMessagesModelDynamically(.asc, message: newMsg, completion) NELog.infoLog(ModuleName + " " + className, desc: #function) - let option = NIMHistoryMessageSearchOption() - option.startTime = newMsg?.timestamp ?? 0 - option.endTime = 0 - option.limit = messagPageNum - let isCredible = isMessageCredible(message: newMsg ?? NIMMessage()) - if isCredible { - if anchor != nil { - // 搜索历史记录进入 - searchMessageHistory( - direction: .new, - startTime: newMsg?.timestamp ?? 0, - endTime: 0, - completion - ) - } - - } else { - getRemoteHistoryMessage( - direction: .new, - updateCredible: false, - option: option, - completion - ) - } } // 搜索历史记录查询的本地消息 @@ -485,8 +507,8 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel weakSelf?.newMsg = messageArray.last } for msg in messageArray { - weakSelf?.addTimeMessage(msg) - if let model = weakSelf?.modelFromMessage(message: msg) { + if let model = weakSelf?.modelFromMessage(message: msg), NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: msg) == false { + weakSelf?.addTimeMessage(msg) weakSelf?.messages.append(model) } } @@ -637,6 +659,31 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel if msg.isDeleted == true { continue } + if NotificationMessageUtils.isDiscussSeniorTeamUpdateCustomNoti(message: msg) { + continue + } + if let object = msg.messageObject as? NIMNotificationObject { + if let content = object.content as? NIMTeamNotificationContent, content.operationType == .invite { + if filterInviteSet.contains(msg.messageId) { + continue + } else { + filterInviteSet.insert(msg.messageId) + } + } + } + /* 后续解散群离开群弹框优化 + if msg.messageType == .notification, session.sessionType == .team { + if team?.clientCustomInfo?.contains(discussTeamKey) == true { + return + } + let value = NotificationMessageUtils.isTeamLeaveOrDismiss(message: msg) + if value.isLeave == true { + delegate?.didLeaveTeam() + } else if value.isDismiss == true { + delegate?.didDismissTeam() + } + + }*/ count += 1 // 自定义消息处理 if msg.messageType == .custom { @@ -802,6 +849,26 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel NELog.infoLog(ModuleName + " " + className, desc: #function + ", pinAccount: " + (model?.pinAccount ?? "nil")) var pinItem = OperationItem.pinItem() var items = [OperationItem]() + + if model?.message?.deliveryState == .failed || model?.message?.deliveryState == .delivering, model?.message?.messageType != .rtcCallRecord { + switch model?.message?.messageType { + case .text: + items.append(contentsOf: [ + OperationItem.copyItem(), + OperationItem.deleteItem(), + ]) + return items + case .audio, .video, .image, .location, .file: + items.append(contentsOf: [ + OperationItem.deleteItem(), + ]) + return items + default: + break + } + + return nil + } switch model?.message?.messageType { case .location: items.append(contentsOf: [ @@ -818,8 +885,6 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel OperationItem.replayItem(), OperationItem.forwardItem(), pinItem, -// OperationItem.selectItem(), -// OperationItem.collectionItem(), OperationItem.deleteItem(), ] @@ -831,8 +896,6 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel OperationItem.replayItem(), OperationItem.forwardItem(), pinItem, -// OperationItem.selectItem(), -// OperationItem.collectionItem(), OperationItem.deleteItem(), ] case .audio: @@ -842,10 +905,10 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel items = [ OperationItem.replayItem(), pinItem, -// OperationItem.selectItem(), -// OperationItem.collectionItem(), OperationItem.deleteItem(), ] + case .rtcCallRecord: + items = [OperationItem.deleteItem()] default: if let isPin = model?.isPined, isPin { @@ -854,13 +917,11 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel items = [ OperationItem.replayItem(), pinItem, -// OperationItem.selectItem(), -// OperationItem.collectionItem(), OperationItem.deleteItem(), ] } - if model?.message?.from == NIMSDK.shared().loginManager.currentAccount() { + if model?.message?.from == NIMSDK.shared().loginManager.currentAccount(), model?.message?.messageType != .rtcCallRecord { items.append(OperationItem.recallItem()) } return items @@ -899,17 +960,20 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel } // history message insert message at first of messages, send message add last of messages - private func addTimeMessage(_ message: NIMMessage) { + @discardableResult + private func addTimeMessage(_ message: NIMMessage) -> Bool { NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId: " + message.messageId) let lastTs = messages.last?.message?.timestamp ?? 0.0 let curTs = message.timestamp let dur = curTs - lastTs if (dur / 60) > 5 { messages.append(timeModel(message)) + return true } + return false } - private func addTimeForHistoryMessage(_ message: NIMMessage) { + private func addTimeForHistoryMessage(_ message: NIMMessage) -> Bool { NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId: " + message.messageId) let firstTs = messages.first?.message?.timestamp ?? 0.0 let curTs = message.timestamp @@ -919,7 +983,9 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel model.type = .time model.text = String.stringFromDate(date: Date(timeIntervalSince1970: firstTs)) messages.insert(model, at: 0) + return true } + return false } private func timeModel(_ message: NIMMessage) -> MessageModel { @@ -965,6 +1031,8 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel // <#code#> case .location: model = MessageLocationModel(message: message) + case .rtcCallRecord: + model = MessageCallRecordModel(message: message) default: // 未识别的消息类型,默认为文本消息类型,text为未知消息 message.text = "未知消息" @@ -1006,14 +1074,19 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel private func getReplyMessage(message: NIMMessage) -> MessageModel? { NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId: " + message.messageId) - guard let id = message.repliedMessageId else { + guard let id = message.repliedMessageId, id.count > 0 else { return nil } - if let message = ConversationProvider.shared.messagesInSession(session, messageIds: [id])? + if let m = ConversationProvider.shared.messagesInSession(session, messageIds: [id])? .first { - return modelFromMessage(message: message) + let model = modelFromMessage(message: m) + model.isReplay = true + return model } - return nil + let message = NIMMessage() + let model = modelFromMessage(message: message) + model.isReplay = true + return model } private func getUserInfo(_ userId: String, _ completion: @escaping (User?, NSError?) -> Void) { @@ -1277,6 +1350,7 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel if message.messageType == .text { muta[revokeLocalMessageContent] = message.text } + messageNew.timestamp = message.timestamp messageNew.from = message.from messageNew.localExt = muta let setting = NIMMessageSetting() @@ -1298,6 +1372,25 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel } } + public func refreshReceipts() { + if session.sessionType != .team { + return + } + if repo.settingProvider.getMessageRead() == false { + return + } + print("refresh team id : ", session.sessionId) + var receiptsMessages = [NIMMessage]() + messages.forEach { model in + if let message = model.message, message.setting?.teamReceiptEnabled == true, + let unreadCount = message.teamReceiptInfo?.unreadCount, unreadCount > 0 { + print("unread count : ", unreadCount as Any) + receiptsMessages.append(message) + } + } + repo.refreshReceipts(receiptsMessages) + } + // MARK: NIMConversationManagerDelegate // remote diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift index fd58f73d..f3c9de99 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift @@ -5,7 +5,7 @@ import Foundation import NIMSDK import CoreText - +import NECoreIMKit @objc public protocol TeamChatViewModelDelegate: ChatViewModelDelegate { func onTeamRemoved(team: NIMTeam) @@ -14,7 +14,6 @@ public protocol TeamChatViewModelDelegate: ChatViewModelDelegate { @objcMembers public class TeamChatViewModel: ChatViewModel, NIMTeamManagerDelegate { - public var team: NIMTeam? private let className = "TeamChatViewModel" // override init(session: NIMSession) { // super.init(session: session) diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift index a50a0110..4e224587 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift @@ -5,7 +5,7 @@ import Foundation import NIMSDK import NEChatKit - +import NECoreIMKit @objcMembers public class TeamMemberSelectVM: NSObject { public var chatRepo: ChatRepo = .init() diff --git a/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift b/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift index 117e917a..82aa3051 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift @@ -39,5 +39,5 @@ public class ChatUIConfig: NSObject { public var messageColor = UIColor.ne_darkText /// 发送文件大小限制(单位:MB) - public var fileSizeLimit: Double? + public var fileSizeLimit: Double = 200 } diff --git a/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/ChatRouter.swift b/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/ChatRouter.swift index eac23609..7f7706c2 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/ChatRouter.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/ChatRouter.swift @@ -28,13 +28,17 @@ public class ChatRouter: NSObject { guard let session = param["session"] as? NIMSession else { return } - if let anchor = param["anchor"] as? NIMMessage { - let groupVC = GroupChatViewController(session: session, anchor: anchor) - nav?.pushViewController(groupVC, animated: true) - } else { - let groupVC = GroupChatViewController(session: session, anchor: nil) - nav?.pushViewController(groupVC, animated: true) + + let anchor = param["anchor"] as? NIMMessage + let groupVC = GroupChatViewController(session: session, anchor: anchor) + for (i, vc) in (nav?.viewControllers ?? []).enumerated() { + if vc.isMember(of: GroupChatViewController.self) { + nav?.viewControllers[i] = groupVC + nav?.popToViewController(groupVC, animated: true) + return + } } + nav?.pushViewController(groupVC, animated: true) } } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift b/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift index f8a856f2..f40a3c5a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift @@ -7,6 +7,7 @@ import Foundation @_exported import NECoreKit @_exported import NECommonUIKit @_exported import NECommonKit +@_exported import NECoreIMKit let coreLoader = CoreLoader() func chatLocalizable(_ key: String) -> String { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift b/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift index 9378dfef..6e98fc13 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift @@ -4,31 +4,21 @@ // found in the LICENSE file. import UIKit -// import AMapFoundationKit +import NIMSDK @objcMembers public class NEChatUIKitClient: NSObject { public static let instance = NEChatUIKitClient() - override init() {} - - /// 获取更多面板数据 - /// - Returns: 返回更多操作数据 - public func getMoreActionData() -> [NEMoreItemModel] { - var moreAction = [NEMoreItemModel]() + public var moreAction = [NEMoreItemModel]() + override init() { let picture = NEMoreItemModel() picture.image = UIImage.ne_imageNamed(name: "chat_takePicture") picture.title = chatLocalizable("chat_takePicture") picture.type = .takePicture moreAction.append(picture) -// let rtc = NEMoreItemModel() -// rtc.image = UIImage.ne_imageNamed(name: "chat_rtc") -// rtc.title = chatLocalizable("chat_rtc") -// rtc.type = .rtc -// moreAction.append(rtc) - let location = NEMoreItemModel() location.image = UIImage.ne_imageNamed(name: "chat_location") location.title = chatLocalizable("chat_location") @@ -41,6 +31,26 @@ public class NEChatUIKitClient: NSObject { file.type = .file moreAction.append(file) - return moreAction + if XKitServiceManager.getInstance().serviceIsRegister("NERtcCallUIKit") == true { + let rtc = NEMoreItemModel() + rtc.image = UIImage.ne_imageNamed(name: "chat_rtc") + rtc.title = chatLocalizable("chat_rtc") + rtc.type = .rtc + moreAction.append(rtc) + } + } + + /// 获取更多面板数据 + /// - Returns: 返回更多操作数据 + public func getMoreActionData(sessionType: NIMSessionType) -> [NEMoreItemModel] { + var more = [NEMoreItemModel]() + moreAction.forEach { model in + if model.type != .rtc { + more.append(model) + } else if sessionType == .P2P { + more.append(model) + } + } + return more } } diff --git a/NEContactUIKit/NEContactUIKit.podspec b/NEContactUIKit/NEContactUIKit.podspec index 8b247ab8..fbf614e0 100644 --- a/NEContactUIKit/NEContactUIKit.podspec +++ b/NEContactUIKit/NEContactUIKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEContactUIKit' - s.version = '9.3.0' + s.version = '9.2.10' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -24,9 +24,9 @@ Pod::Spec.new do |s| # s.source = { :git => 'https://github.com/chenyu-home/ContactKitUI.git', :tag => s.version.to_s } s.pod_target_xcconfig = { + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64', 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } - s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } s.ios.deployment_target = '9.0' s.swift_version = '5.0' @@ -34,6 +34,6 @@ Pod::Spec.new do |s| s.resource = 'NEContactUIKit/Assets/**/*' s.dependency 'NEContactKit' s.dependency 'NECommonUIKit' - s.dependency 'YXAlog_iOS' + s.dependency 'YXAlog' end diff --git a/NEContactUIKit/NEContactUIKit/Assets/en.lproj/Localizable.strings b/NEContactUIKit/NEContactUIKit/Assets/en.lproj/Localizable.strings index 7cda82eb..b3b869a5 100644 --- a/NEContactUIKit/NEContactUIKit/Assets/en.lproj/Localizable.strings +++ b/NEContactUIKit/NEContactUIKit/Assets/en.lproj/Localizable.strings @@ -7,6 +7,8 @@ "alert_tip"="tip"; "alert_sure"="ok"; "alert_cancel"="cancel"; + +"account"="Account"; "noteName"="Nick Name"; "remove_black" = "Remove"; @@ -14,6 +16,7 @@ "mine_groupchat"="My Group"; "save"="Save"; "input_noteName"="Please enter nick name"; +"birthday"="birthday"; "phone"="mobile"; "email"="e-mail"; "sign"="What's Up"; @@ -22,6 +25,7 @@ "add_blackList"="block"; "send_friend_apply"="Contact request sent"; "validation_message"="Verify message"; +"no_validation_message"="No Validation Message"; "clear"="Clear"; "agreed"="Added"; "refused"="Rejected"; @@ -31,12 +35,10 @@ "select"="Select"; "select_contact"="Please select Contact"; "user_not_exist"="No contact"; +"no_friend"="No Friend"; "chat"="Chat"; "message_remind"="Message notification"; "clear_all_validate_message"="Wether to clear all verification"; "sure_delte_friend"="Wether to delete Contact?"; "input_userId"="Input user ID"; - - - - +"space_not_support"="All Spaces are not supported"; diff --git a/NEContactUIKit/NEContactUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NEContactUIKit/NEContactUIKit/Assets/zh-Hans.lproj/Localizable.strings index 7d493222..aa63bba9 100644 --- a/NEContactUIKit/NEContactUIKit/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEContactUIKit/NEContactUIKit/Assets/zh-Hans.lproj/Localizable.strings @@ -7,6 +7,8 @@ "alert_tip"="提示"; "alert_sure"="确定"; "alert_cancel"="取消"; + +"account"="账号"; "noteName"="备注名"; "remove_black" = "解除"; @@ -14,6 +16,7 @@ "mine_groupchat"="我的群聊"; "save"="保存"; "input_noteName"="请输入备注名"; +"birthday"="生日"; "phone"="手机"; "email"="邮箱"; "sign"="个性签名"; @@ -22,6 +25,7 @@ "add_blackList"="加入黑名单"; "send_friend_apply"="好友申请已发送"; "validation_message"="验证消息"; +"no_validation_message"="暂无验证消息"; "clear"="清空"; "agreed"="已同意"; "refused"="已拒绝"; @@ -31,8 +35,10 @@ "select"="选择"; "select_contact"="请选择联系人"; "user_not_exist"="该用户不存在"; +"no_friend"="暂无好友"; "chat"="聊天"; "message_remind"="消息提醒"; "clear_all_validate_message"="是否要清除所有验证消息?"; "sure_delte_friend"="是否确定删除好友?"; -"input_userId"="输入查找用户id"; +"input_userId"="请输入账号"; +"space_not_support"="不支持全空格"; diff --git a/NEContactUIKit/NEContactUIKit/Classes/Base/ContactBaseViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Base/ContactBaseViewCell.swift index 9e0f5d7e..6dd817fa 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Base/ContactBaseViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Base/ContactBaseViewCell.swift @@ -29,6 +29,7 @@ open class ContactBaseViewCell: UITableViewCell { name.textColor = .white name.textAlignment = .center name.font = UIFont.systemFont(ofSize: 14.0) + name.adjustsFontSizeToFitWidth = true return name }() diff --git a/NEContactUIKit/NEContactUIKit/Classes/Extension/ContactImageExtension.swift b/NEContactUIKit/NEContactUIKit/Classes/Extension/ContactImageExtension.swift index 55d91ee2..90494e69 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Extension/ContactImageExtension.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Extension/ContactImageExtension.swift @@ -6,7 +6,7 @@ import Foundation public extension UIImage { class func ne_imageNamed(name: String?) -> UIImage? { - guard let imageName = name else { + guard let imageName = name, !imageName.isEmpty else { return nil } return coreLoader.loadImage(imageName) diff --git a/NEContactUIKit/NEContactUIKit/Classes/Team/Views/TeamTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Team/Views/TeamTableViewCell.swift index e33d9708..c0dcf7cf 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Team/Views/TeamTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Team/Views/TeamTableViewCell.swift @@ -89,7 +89,7 @@ public class TeamTableViewCell: UITableViewCell { avatarImage.sd_setImage(with: URL(string: url), completed: nil) } else { // random avatar - avatarImage.image = randomAvatar(teamId: team.teamId) +// avatarImage.image = randomAvatar(teamId: team.teamId) } } @@ -98,7 +98,7 @@ public class TeamTableViewCell: UITableViewCell { return nil } // mod: 0 1 2 3 4 - let mod = Int(tid) ?? 0 % 5 + let mod = (Int(tid) ?? 0) % 5 let name = "icon_" + String(mod) return UIImage.ne_imageNamed(name: name) } diff --git a/NEContactUIKit/NEContactUIKit/Classes/UserInfo/UserInfoHeaderView.swift b/NEContactUIKit/NEContactUIKit/Classes/UserInfo/UserInfoHeaderView.swift index 5a6b8101..6f94033d 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/UserInfo/UserInfoHeaderView.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/UserInfo/UserInfoHeaderView.swift @@ -12,6 +12,13 @@ public class UserInfoHeaderView: UIView { public var nameLabel = UILabel() public var titleLabel = UILabel() public var detailLabel = UILabel() + lazy var lineView: UIView = { + let view = UIView() + view.backgroundColor = .ne_greyLine + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .white @@ -61,6 +68,14 @@ public class UserInfoHeaderView: UIView { detailLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8), detailLabel.heightAnchor.constraint(equalToConstant: 22), ]) + + addSubview(lineView) + NSLayoutConstraint.activate([ + lineView.leftAnchor.constraint(equalTo: leftAnchor), + lineView.rightAnchor.constraint(equalTo: rightAnchor), + lineView.bottomAnchor.constraint(equalTo: bottomAnchor), + lineView.heightAnchor.constraint(equalToConstant: 6), + ]) } required init?(coder: NSCoder) { @@ -77,7 +92,7 @@ public class UserInfoHeaderView: UIView { avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) nameLabel.isHidden = true } - detailLabel.text = user.userId + // title var showName = user.alias?.count ?? 0 > 0 ? user.alias : user.userInfo?.nickName if showName == nil || showName?.count == 0 { @@ -90,5 +105,7 @@ public class UserInfoHeaderView: UIView { .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name } } + + detailLabel.text = "\(localizable("account")):\(user.userId ?? "")" } } diff --git a/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift index 10e95fae..e36dbbf4 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift @@ -12,12 +12,24 @@ public class ContactRemakNameViewController: ContactBaseViewController, UITextFi typealias ModifyBlock = (_ user: User) -> Void var completion: ModifyBlock? - var user: User? - let viewmodel = ContactUserViewModel() - - lazy var aliasInput: UITextField = getInput() + let textLimit = 15 + lazy var aliasInput: UITextField = { + let textField = UITextField() + textField.backgroundColor = .white + textField.clipsToBounds = true + textField.layer.cornerRadius = 8 + textField.font = UIFont.systemFont(ofSize: 16.0) + textField.translatesAutoresizingMaskIntoConstraints = false + let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 0)) + textField.leftView = leftSpace + textField.leftViewMode = .always + textField.delegate = self + textField.clearButtonMode = .whileEditing + textField.addTarget(self, action: #selector(textFieldChange), for: .editingChanged) + return textField + }() // lazy var rightBtn: ExpandButton = { // let btn = ExpandButton(frame: CGRect(x: 0, y: 0, width: 60, height: 44)) @@ -59,26 +71,18 @@ public class ContactRemakNameViewController: ContactBaseViewController, UITextFi } } - func getInput() -> UITextField { - let textField = UITextField() - textField.backgroundColor = .white - textField.clipsToBounds = true - textField.layer.cornerRadius = 8 - textField.font = UIFont.systemFont(ofSize: 16.0) - textField.translatesAutoresizingMaskIntoConstraints = false - let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 0)) - textField.leftView = leftSpace - textField.leftViewMode = .always - textField.delegate = self - textField.clearButtonMode = .whileEditing - return textField - } - func saveAlias() { // guard let alais = aliasInput.text, alais.count > 0 else { // view.makeToast("请填写备注名", duration: 2, position: .center) // return // } + if let text = aliasInput.text, + text.count > 0, + text.trimmingCharacters(in: .whitespaces).isEmpty { + view.makeToast(localizable("space_not_support"), duration: 2, position: .center) + aliasInput.text = "" + return + } user?.alias = aliasInput.text if let u = user { view.makeToastActivity(.center) @@ -115,13 +119,13 @@ public class ContactRemakNameViewController: ContactBaseViewController, UITextFi } */ - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - let text = "\(textField.text ?? "")\(string)" - print("text count : ", text.count) - if text.count > 30 { - return false + public func textFieldChange() { + guard let _ = aliasInput.markedTextRange else { + if let text = aliasInput.text, + text.count > textLimit { + aliasInput.text = String(text.prefix(textLimit)) + } + return } - return true } } diff --git a/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactUserViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactUserViewController.swift index 37718ca9..716a89eb 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactUserViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/UserInfo/ViewController/ContactUserViewController.swift @@ -111,60 +111,66 @@ public class ContactUserViewController: ContactBaseViewController, UITableViewDe if isFriend { data = [ - [UserItem( - title: localizable("noteName"), - detailTitle: user?.alias, - value: false, - textColor: UIColor.darkText, - cellClass: TextWithRightArrowCell.self - )], [ - UserItem(title: localizable("phone"), detailTitle: user?.userInfo?.mobile, + UserItem(title: localizable("noteName"), + detailTitle: user?.alias, value: false, - textColor: UIColor.darkText, cellClass: TextWithDetailTextCell.self), - UserItem( - title: localizable("email"), - detailTitle: user?.userInfo?.email, - value: false, - textColor: UIColor.darkText, - cellClass: TextWithDetailTextCell.self - ), - UserItem( - title: localizable("sign"), - detailTitle: user?.userInfo?.sign, - value: false, - textColor: UIColor.darkText, - cellClass: TextWithDetailTextCell.self - ), + textColor: UIColor.darkText, + cellClass: TextWithRightArrowCell.self), + ], + [ + UserItem(title: localizable("birthday"), + detailTitle: user?.userInfo?.birth, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithDetailTextCell.self), + UserItem(title: localizable("phone"), + detailTitle: user?.userInfo?.mobile, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithDetailTextCell.self), + UserItem(title: localizable("email"), + detailTitle: user?.userInfo?.email, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithDetailTextCell.self), + UserItem(title: localizable("sign"), + detailTitle: user?.userInfo?.sign, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithDetailTextCell.self), ], - [UserItem( - title: localizable("add_blackList"), - detailTitle: "", - value: isBlack, - textColor: UIColor.darkText, - cellClass: TextWithSwitchCell.self - )], [ - UserItem(title: localizable("chat"), detailTitle: "", value: false, - textColor: UIColor(hexString: "#337EFF"), cellClass: CenterTextCell.self), - UserItem( - title: localizable("delete_friend"), - detailTitle: "", - value: false, - textColor: UIColor.red, - cellClass: CenterTextCell.self - ), + UserItem(title: localizable("add_blackList"), + detailTitle: "", + value: isBlack, + textColor: UIColor.darkText, + cellClass: TextWithSwitchCell.self), + ], + [ + UserItem(title: localizable("chat"), + detailTitle: "", + value: false, + textColor: UIColor(hexString: "#337EFF"), + cellClass: CenterTextCell.self), + UserItem(title: localizable("delete_friend"), + detailTitle: "", + value: false, + textColor: UIColor.red, + cellClass: CenterTextCell.self), ], ] } else { - data = [[UserItem( - title: localizable("add_friend"), - detailTitle: user?.alias, - value: false, - textColor: UIColor(hexString: "#337EFF"), - cellClass: CenterTextCell.self - )]] + data = [ + [ + UserItem(title: localizable("add_friend"), + detailTitle: user?.alias, + value: false, + textColor: UIColor(hexString: "#337EFF"), + cellClass: CenterTextCell.self), + ], + ] } tableView.reloadData() } @@ -235,7 +241,12 @@ public class ContactUserViewController: ContactBaseViewController, UITableViewDe deleteFriend(user: user) } if item.title == localizable("add_friend") { - addFriend() + if let uId = user?.userId, + viewModel.isFriend(account: uId) { + loadData() + } else { + addFriend() + } } } @@ -334,6 +345,15 @@ public class ContactUserViewController: ContactBaseViewController, UITableViewDe NELog.errorLog("ContactUserViewController", desc: "❌add friend failed :\(err)") } else { weakSelf?.showToast(localizable("send_friend_apply")) + if let model = weakSelf?.viewModel, + model.isBlack(account: account) { + weakSelf?.viewModel.removeBlackList(account: account) { err in + NELog.infoLog( + self.className, + desc: #function + "CALLBACK " + (err?.localizedDescription ?? "no error") + ) + } + } } } } diff --git a/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewController/ValidationMessageViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewController/ValidationMessageViewController.swift index 7e38f67f..4b626437 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewController/ValidationMessageViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewController/ValidationMessageViewController.swift @@ -19,17 +19,20 @@ public class ValidationMessageViewController: ContactBaseViewController { // Do any additional setup after loading the view. title = localizable("validation_message") + emptyView.setttingContent(content: localizable("no_validation_message")) // viewModel.getValidationMessage() setupUI() weak var weakSelf = self viewModel.getValidationMessage { - NELog.infoLog(ModuleName + " " + self.tag, desc: "✅ getValidationMessage SUCCESS") + NELog.infoLog(ModuleName + " " + (weakSelf?.tag ?? "ValidationMessageViewController"), desc: "✅ getValidationMessage SUCCESS") weakSelf?.tableView.reloadData() } viewModel.dataRefresh = { + weakSelf?.emptyView.isHidden = (weakSelf?.viewModel.datas.count ?? 0) > 0 weakSelf?.tableView.reloadData() } + emptyView.isHidden = viewModel.datas.count > 0 } func setupUI() { @@ -63,6 +66,14 @@ public class ValidationMessageViewController: ContactBaseViewController { SystemNotificationCell.self, forCellReuseIdentifier: "\(SystemNotificationCell.self)" ) + + view.addSubview(emptyView) + NSLayoutConstraint.activate([ + emptyView.topAnchor.constraint(equalTo: tableView.topAnchor, constant: 100), + emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), + emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), + emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), + ]) } func clearMessage() { @@ -71,6 +82,7 @@ public class ValidationMessageViewController: ContactBaseViewController { weakSelf?.viewModel.clearAllNoti { NELog.infoLog(ModuleName + " " + self.tag, desc: "✅ clearAllNoti SUCCESS") weakSelf?.tableView.reloadData() + weakSelf?.emptyView.isHidden = false } } } diff --git a/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/BaseValidationCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/BaseValidationCell.swift index 5dab715a..ed7c487a 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/BaseValidationCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/BaseValidationCell.swift @@ -5,6 +5,7 @@ import UIKit import NECoreIMKit +import NIMSDK @objcMembers public class BaseValidationCell: ContactBaseViewCell { @@ -61,20 +62,34 @@ public class BaseValidationCell: ContactBaseViewCell { var nickName = "" var teamName = "" // 设置操作者名称 - if let nick = model.sourceName { + + if let alias = model.userInfo?.alias { + nickName = alias + } else if let nick = model.userInfo?.userInfo?.nickName { nickName = nick + } else if let source = model.sourceName { + nickName = source + } + + if model.userInfo == nil, let uid = model.sourceID { + let user = NIMSDK.shared().userManager.userInfo(uid) + if let alias = user?.alias { + nickName = alias + } else if let nick = user?.userInfo?.nickName { + nickName = nick + } } // 设置头像 - if let headerUrl = model.userInfo?.userInfo?.avatarUrl { + if let headerUrl = model.userInfo?.userInfo?.avatarUrl, !headerUrl.isEmpty { avatarImage.sd_setImage(with: URL(string: headerUrl), completed: nil) titleLabel.text = "" - } else if let teamUrl = model.teamInfo?.avatarUrl { + } else if let teamUrl = model.teamInfo?.avatarUrl, !teamUrl.isEmpty { avatarImage.sd_setImage(with: URL(string: teamUrl), completed: nil) titleLabel.text = "" } else { // 无头像设置其name - if let name = model.sourceName { - showNameOnCircleHeader(name) + if !nickName.isEmpty { + showNameOnCircleHeader(nickName) } else { if let id = model.sourceID { showNameOnCircleHeader(id) @@ -114,6 +129,8 @@ public class BaseValidationCell: ContactBaseViewCell { titleLabelContent = "\(nickName) 通过好友申请" case .addFriendReject: titleLabelContent = "\(nickName) 拒绝好友申请" + @unknown default: + titleLabelContent = "\(nickName) 未知操作" } } diff --git a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift index a5c0801d..ec9ef843 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift @@ -36,6 +36,11 @@ public class ContactUserViewModel: NSObject { return contactRepo.isBlackList(account: account) } + public func removeBlackList(account: String, _ completion: @escaping (NSError?) -> Void) { + NELog.infoLog(ModuleName + " " + className, desc: #function + ", account: " + account) + return contactRepo.removeBlackList(account: account, completion) + } + public func update(_ user: User, _ completion: @escaping (Error?) -> Void) { NELog.infoLog(ModuleName + " " + className, desc: #function + ", userId: " + (user.userId ?? "nil")) contactRepo.updateUser(user, completion) diff --git a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift index 5680fdc7..ff40e3c7 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift @@ -15,17 +15,13 @@ public class ContactViewModel: NSObject, ContactRepoSystemNotiDelegate { public var indexs: [String]? private var contactHeaders: [ContactHeadItem]? public var contactRepo = ContactRepo() - private var initalDict: [String: [ContactInfo]] = ["#": []] + private var initalDict = [String: [ContactInfo]]() private let className = "ContactViewModel" var unreadCount = 0 var refresh: RefreshBlock? init(contactHeaders: [ContactHeadItem]?) { - NELog.infoLog( - ModuleName + " " + className, - desc: #function + ", contactHeaders.count: \(contactHeaders?.count ?? 0)" - ) super.init() NELog.infoLog( ModuleName + " " + className, @@ -49,10 +45,10 @@ public class ContactViewModel: NSObject, ContactRepoSystemNotiDelegate { func loadData(_ filters: Set? = nil, completion: @escaping (NSError?) -> Void) { NELog.infoLog(ModuleName + " " + className, desc: #function) - initalDict = ["#": []] weak var weakSelf = self getContactList(filters) { contacts, error in if let users = contacts { + NELog.infoLog("contact loadData", desc: "contact data:\(contacts)") weakSelf?.contacts = users weakSelf?.indexs = self.getIndexs(contactSections: users) if let headSection = weakSelf?.headerSection(headerItem: weakSelf?.contactHeaders) { @@ -69,6 +65,8 @@ public class ContactViewModel: NSObject, ContactRepoSystemNotiDelegate { weak var weakSelf = self contactRepo.getFriendList { [self] friends, error in if var users = friends { + NELog.infoLog("contact bar getFriendList", desc: "friend count:\(friends?.count)") + weakSelf?.initalDict = [String: [ContactInfo]]() if let filterUsers = filters { users = users.filter { user in if let uid = user.userId, filterUsers.contains(uid) { @@ -83,33 +81,55 @@ public class ContactViewModel: NSObject, ContactRepoSystemNotiDelegate { return // return contactList } + + let digitRegular = NSPredicate(format: "SELF MATCHES %@", "[0-9]") + let azRegular = NSPredicate(format: "SELF MATCHES %@", "[A-Z]") + var digitList = [ContactInfo]() + var specialCharList = [ContactInfo]() for contact: User in users { // get inital of name var name = contact.alias != nil ? contact.alias : contact.userInfo?.nickName if name == nil { name = contact.userId } - let inital = name?.initalLetter() + let inital = name?.initalLetter() ?? "#" let contactInfo = ContactInfo() contactInfo.user = contact contactInfo.headerBackColor = UIColor.colorWithString(string: contact.showName() ?? "") - var contactsTemp = weakSelf?.initalDict[inital!] - if contactsTemp == nil { - contactsTemp = [contactInfo] - weakSelf?.initalDict[inital!] = contactsTemp - } else { - weakSelf?.initalDict[inital!]?.append(contactInfo) + if digitRegular.evaluate(with: inital) { // [0-9] + digitList.append(contactInfo) + } else if !azRegular.evaluate(with: inital) { // [#] + specialCharList.append(contactInfo) + } else { // [A-Z] + if weakSelf?.initalDict[inital] != nil { + weakSelf?.initalDict[inital]?.append(contactInfo) + } else { + weakSelf?.initalDict[inital] = [contactInfo] + } } } + digitList.sort { s1, s2 in + s1.user!.showName()! < s2.user!.showName()! + } + specialCharList.sort { s1, s2 in + s1.user!.showName()! < s2.user!.showName()! + } + for key in initalDict.keys { - contactList.append(ContactSection(initial: key, contacts: (weakSelf?.initalDict[key]!)!)) + if var value = weakSelf?.initalDict[key] { + value.sort { s1, s2 in + s1.user!.showName()! < s2.user!.showName()! + } + contactList.append(ContactSection(initial: key, contacts: value)) + } } - let result = contactList.sorted { s1, s2 in + var result = contactList.sorted { s1, s2 in s1.initial < s2.initial } + result.append(ContactSection(initial: "#", contacts: digitList + specialCharList)) completion(result, nil) } } @@ -141,19 +161,26 @@ public class ContactViewModel: NSObject, ContactRepoSystemNotiDelegate { } func getIndexs(contactSections: [ContactSection]?) -> [String]? { - NELog.infoLog( - ModuleName + " " + className, - desc: #function + ", contactSections.count: \(contactSections?.count ?? 0)" - ) - guard let sections = contactSections else { - return nil - } - var indexs: [String] = [] - for section in sections { - if section.initial.count > 0 { - indexs.append(section.initial) - } - } + // 根据用户列表获取导航标签 +// NELog.infoLog( +// ModuleName + " " + className, +// desc: #function + ", contactSections.count: \(contactSections?.count ?? 0)" +// ) +// guard let sections = contactSections else { +// return nil +// } +// var indexs: [String] = [] +// for section in sections { +// if section.initial.count > 0 { +// indexs.append(section.initial) +// } +// } + + // ["A"..."Z", "#"] + let idx = UnicodeScalar("A").value ... UnicodeScalar("Z").value + var indexs = (idx.map { String(UnicodeScalar($0)!) }) + indexs.append("#") + return indexs } } diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactBaseViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactBaseViewController.swift index e1aa3868..aac9390a 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactBaseViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactBaseViewController.swift @@ -7,6 +7,18 @@ import UIKit @objcMembers open class ContactBaseViewController: UIViewController { + lazy var emptyView: NEEmptyDataView = { + let view = NEEmptyDataView( + imageName: "user_empty", + content: "", + frame: CGRect.zero + ) + view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + return view + + }() + override public func viewDidLoad() { super.viewDidLoad() diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactTableViewCell.swift index 809e7ef9..ea7e106a 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactTableViewCell.swift @@ -94,17 +94,19 @@ public class ContactTableViewCell: ContactBaseViewCell, ContactCellDataProtrol { titleLabel.text = user.showName() nameLabel.text = user.shortName(count: 2) -// self.nameLabel.backgroundColor = UIColor(hexString: user.userId!) - if let imageUrl = user.userInfo?.avatarUrl { + if let imageUrl = user.userInfo?.avatarUrl, !imageUrl.isEmpty { + NELog.infoLog("contact p2p cell configData", desc: "imageName:\(imageUrl)") nameLabel.isHidden = true avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) } else { + NELog.infoLog("contact p2p cell configData", desc: "imageName is nil") nameLabel.isHidden = false - avatarImage.image = nil + avatarImage.sd_setImage(with: nil) } arrow.isHidden = true } else { + NELog.infoLog("contact other cell configData", desc: "\(user.alias), image name:\(user.userInfo?.avatarUrl)") nameLabel.text = "" titleLabel.text = user.alias avatarImage.image = UIImage.ne_imageNamed(name: user.userInfo?.avatarUrl) diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsSelectedViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsSelectedViewController.swift index 14c3a10c..e0d6cd5b 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsSelectedViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsSelectedViewController.swift @@ -46,6 +46,7 @@ open class ContactsSelectedViewController: ContactBaseViewController { // Do any additional setup after loading the view. title = localizable("select") + emptyView.setttingContent(content: localizable("no_friend")) // setupUI() // setupNavRightItem() @@ -56,6 +57,7 @@ open class ContactsSelectedViewController: ContactBaseViewController { weakSelf?.setupUI() weakSelf?.setupNavRightItem() weakSelf?.tableView.reloadData() + weakSelf?.emptyView.isHidden = (weakSelf?.viewModel.contacts.count ?? 0) > 0 } } @@ -94,6 +96,14 @@ open class ContactsSelectedViewController: ContactBaseViewController { tableView.topAnchor.constraint(equalTo: collection.bottomAnchor), ]) + view.addSubview(emptyView) + NSLayoutConstraint.activate([ + emptyView.topAnchor.constraint(equalTo: tableView.topAnchor), + emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), + emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), + emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), + ]) + customCells.forEach { (key: Int, value: AnyClass) in if value is ContactCellDataProtrol.Type { self.tableView.register( diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsViewController.swift index de876d23..bff4da75 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/ContactsViewController.swift @@ -107,7 +107,9 @@ open class ContactsViewController: UIViewController, UITableViewDelegate, UITabl } public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - viewModel.contacts[section].contacts.count + NELog.infoLog(ModuleName + " " + className(), desc: "contact section: \(section), count:\(viewModel.contacts[section].contacts.count)") + + return viewModel.contacts[section].contacts.count } public func tableView(_ tableView: UITableView, @@ -120,7 +122,7 @@ open class ContactsViewController: UIViewController, UITableViewDelegate, UITabl cell.setModel(info) if indexPath.section == 0, indexPath.row == 0, viewModel.unreadCount > 0 { cell.redAngleView.isHidden = false - cell.redAngleView.text = "\(viewModel.unreadCount)" + cell.redAngleView.text = viewModel.unreadCount > 99 ? "99+" : "\(viewModel.unreadCount)" } else { cell.redAngleView.isHidden = true } diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/FindFriendViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/FindFriendViewController.swift index 77dee4b4..4c1af9b4 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/FindFriendViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/FindFriendViewController.swift @@ -5,34 +5,18 @@ import UIKit import NECoreKit - +import NECoreIMKit @objcMembers public class FindFriendViewController: ContactBaseViewController, UITextFieldDelegate { let viewModel = FindFriendViewModel() let noResultView = UIView() let hasRequest = false - let searchInput = UITextField() - lazy var emptyView: UIImageView = { - let empty = UIImageView() - empty.translatesAutoresizingMaskIntoConstraints = false - empty.image = coreLoader.loadImage("user_empty") - return empty - }() - - lazy var userLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("user_not_exist") - label.textColor = .ne_emptyTitleColor - label.font = UIFont.systemFont(ofSize: 14.0) - return label - }() - override public func viewDidLoad() { super.viewDidLoad() title = localizable("add_friend") + emptyView.setttingContent(content: localizable("user_not_exist")) setupUI() } @@ -79,6 +63,7 @@ public class FindFriendViewController: ContactBaseViewController, UITextFieldDel searchInput.font = UIFont.systemFont(ofSize: 14.0) searchInput.returnKeyType = .search searchInput.delegate = self + searchInput.clearButtonMode = .always NotificationCenter.default.addObserver( self, @@ -93,14 +78,6 @@ public class FindFriendViewController: ContactBaseViewController, UITextFieldDel emptyView.topAnchor.constraint(equalTo: searchInput.bottomAnchor, constant: 74), // emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) - emptyView.isHidden = true - - view.addSubview(userLabel) - NSLayoutConstraint.activate([ - userLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), - userLabel.topAnchor.constraint(equalTo: emptyView.bottomAnchor, constant: 9), - ]) - userLabel.isHidden = true } public func textFieldShouldReturn(_ textField: UITextField) -> Bool { @@ -119,7 +96,6 @@ public class FindFriendViewController: ContactBaseViewController, UITextFieldDel func textFieldChange() { if let text = searchInput.text, text.count <= 0 { emptyView.isHidden = true - userLabel.isHidden = true } } @@ -136,10 +112,8 @@ public class FindFriendViewController: ContactBaseViewController, UITextFieldDel let userController = ContactUserViewController(user: user) self.navigationController?.pushViewController(userController, animated: true) weakSelf?.emptyView.isHidden = true - weakSelf?.userLabel.isHidden = true } else { weakSelf?.emptyView.isHidden = false - weakSelf?.userLabel.isHidden = false } } else { self.showToast(error?.localizedDescription ?? "") diff --git a/NEConversationUIKit/NEConversationUIKit.podspec b/NEConversationUIKit/NEConversationUIKit.podspec index dc953f57..623dbfd0 100644 --- a/NEConversationUIKit/NEConversationUIKit.podspec +++ b/NEConversationUIKit/NEConversationUIKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEConversationUIKit' - s.version = '9.3.0' + s.version = '9.2.10' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -34,12 +34,12 @@ TODO: Add long description of the pod here. s.resource = 'NEConversationUIKit/Assets/**/*' # s.public_header_files = 'Pod/Classes/**/*.h' s.pod_target_xcconfig = { + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64', 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } - s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } s.dependency 'NECommonUIKit' s.dependency 'NEConversationKit' - s.dependency 'YXAlog_iOS' + s.dependency 'YXAlog' s.dependency 'NIMSDK_LITE' end diff --git a/NEConversationUIKit/NEConversationUIKit/Assets/en.lproj/Localizable.strings b/NEConversationUIKit/NEConversationUIKit/Assets/en.lproj/Localizable.strings index ea450d01..8a06b04e 100644 --- a/NEConversationUIKit/NEConversationUIKit/Assets/en.lproj/Localizable.strings +++ b/NEConversationUIKit/NEConversationUIKit/Assets/en.lproj/Localizable.strings @@ -16,15 +16,16 @@ "search"="Search"; "search_keyword"="Enter the key words"; "user_not_exist"="Not Exist"; +"session_empty"="No Session"; "hm"="HH:mm"; "mdhm"="MM.dd HH:mm"; "ymdhm"="yyyy.MM.dd HH:mm"; -"voice"="[aduio]"; -"picture"="[picture]"; -"video"="[Video]"; -"location"="[Loaction]"; -"notification"="[Tip]"; -"file"="[File]"; +"voice"="[aduio Message]"; +"picture"="[picture Message]"; +"video"="[Video Message]"; +"location"="[Geographic Loaction]"; +"notification"="[Tip Message]"; +"file"="[File Message]"; "internet_phone"="[Audio_Chat]"; "video_chat"="[Video_Chat]"; "unknown"="[Unknown Message]"; diff --git a/NEConversationUIKit/NEConversationUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NEConversationUIKit/NEConversationUIKit/Assets/zh-Hans.lproj/Localizable.strings index bbeffbf3..8b4c288f 100644 --- a/NEConversationUIKit/NEConversationUIKit/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEConversationUIKit/NEConversationUIKit/Assets/zh-Hans.lproj/Localizable.strings @@ -16,18 +16,19 @@ "search"="搜索"; "search_keyword"="请输入你要搜索的关键字"; "user_not_exist"="该用户不存在"; +"session_empty"="暂无会话"; "hm"="HH:mm"; "mdhm"="MM月dd日 HH:mm"; "ymdhm"="yyyy年MM月dd日 HH:mm"; -"voice"="[语音]"; -"picture"="[图片]"; -"video"="[视频]"; -"location"="[位置]"; -"notification"="[通知]"; -"file"="[文件]"; -"internet_phone"="[网络通话]"; -"video_chat"="[视频聊天]"; +"voice"="[语音消息]"; +"picture"="[图片消息]"; +"video"="[视频消息]"; +"location"="[地理位置]"; +"notification"="[通知消息]"; +"file"="[文件消息]"; +"internet_phone"="[音频通话]"; +"video_chat"="[视频通话]"; "unknown"="[未知消息]"; "appName"="云信IM"; -"message_recalled"="消息已撤回"; +"message_recalled"="此消息已撤回"; diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationController.swift index ea83ebc7..90e41191 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationController.swift @@ -106,6 +106,14 @@ extension ConversationController: ConversationNavViewDelegate { } items.append(addFriend) + let createGroup = PopListItem() + createGroup.showName = localizable("create_discussion_group") + createGroup.image = UIImage.ne_imageNamed(name: "create_discussion") + createGroup.completion = { + weakSelf?.createDiscussGroup() + } + items.append(createGroup) + let createDicuss = PopListItem() createDicuss.showName = localizable("create_senior_group") createDicuss.image = UIImage.ne_imageNamed(name: "create_group") @@ -190,6 +198,7 @@ extension ConversationController: ConversationNavViewDelegate { if message.messageType == .text { muta[revokeLocalMessageContent] = message.text } + messageNew.timestamp = message.timestamp messageNew.from = message.from messageNew.localExt = muta let setting = NIMMessageSetting() diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationListViewController.swift index 7c3de52a..8f320252 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationListViewController.swift @@ -12,6 +12,18 @@ open class ConversationListViewController: UIViewController { private let className = "ConversationListViewController" private var tableViewTopConstraint: NSLayoutConstraint? + private lazy var emptyView: NEEmptyDataView = { + let view = NEEmptyDataView( + imageName: "user_empty", + content: localizable("session_empty"), + frame: CGRect.zero + ) + view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + return view + + }() + override open func viewDidLoad() { super.viewDidLoad() setupSubviews() @@ -48,6 +60,7 @@ open class ConversationListViewController: UIViewController { open func setupSubviews() { view.addSubview(tableView) + view.addSubview(emptyView) view.addSubview(brokenNetworkView) NSLayoutConstraint.activate([ @@ -57,6 +70,13 @@ open class ConversationListViewController: UIViewController { ]) tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor) tableViewTopConstraint?.isActive = true + + NSLayoutConstraint.activate([ + emptyView.topAnchor.constraint(equalTo: tableView.topAnchor, constant: 100), + emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), + emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), + emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), + ]) } func requestData() { @@ -68,8 +88,14 @@ open class ConversationListViewController: UIViewController { viewModel.fetchServerSessions(option: params) { error, recentSessions in if error == nil { NELog.infoLog(ModuleName + " " + self.className, desc: "✅CALLBACK fetchServerSessions SUCCESS") - DispatchQueue.main.async { - weakSelf?.tableView.reloadData() + if let recentList = recentSessions { + NELog.infoLog(ModuleName + " " + self.className, desc: "✅CALLBACK fetchServerSessions SUCCESS count : \(recentList.count)") + if recentList.count > 0 { + weakSelf?.emptyView.isHidden = true + weakSelf?.reloadTableView() + } else { + weakSelf?.emptyView.isHidden = false + } } } else { @@ -77,6 +103,7 @@ open class ConversationListViewController: UIViewController { ModuleName + " " + self.className, desc: "❌CALLBACK fetchServerSessions failed,error = \(error!)" ) + weakSelf?.emptyView.isHidden = false } } } @@ -169,7 +196,10 @@ extension ConversationListViewController { extension ConversationListViewController: UITableViewDelegate, UITableViewDataSource { public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - viewModel.conversationListArray?.count ?? 0 + let count = viewModel.conversationListArray?.count ?? 0 + NELog.infoLog(ModuleName + " " + "ConversationListViewController", + desc: "numberOfRowsInSection count : \(count)") + return count } public func tableView(_ tableView: UITableView, @@ -178,9 +208,11 @@ extension ConversationListViewController: UITableViewDelegate, UITableViewDataSo withIdentifier: "\(NSStringFromClass(ConversationListCell.self))", for: indexPath ) as! ConversationListCell - let conversationModel = viewModel.conversationListArray?[indexPath.row] - cell.topStickInfos = viewModel.stickTopInfos - cell.configData(sessionModel: conversationModel) + if let count = viewModel.conversationListArray?.count, count > indexPath.row { + let conversationModel = viewModel.conversationListArray?[indexPath.row] + cell.topStickInfos = viewModel.stickTopInfos + cell.configData(sessionModel: conversationModel) + } return cell } @@ -215,25 +247,6 @@ extension ConversationListViewController: UITableViewDelegate, UITableViewDataSo model: conversationModel ?? ConversationListModel(), indexPath: indexPath ) - - // 删除cell - if let stickTopInfo = weakSelf?.viewModel.stickTopInfoForSession(session: session) { - weakSelf?.viewModel - .removeStickTopSession(params: stickTopInfo) { error, topSessionInfo in - if let err = error { - NELog.errorLog( - ModuleName + " " + (weakSelf?.className ?? "ConversationListViewController"), - desc: "❌CALLBACK removeStickTopSession failed,error = \(err)" - ) - return - } - NELog.infoLog( - ModuleName + " " + (weakSelf?.className ?? "ConversationListViewController"), - desc: "✅CALLBACK removeStickTopSession SUCCESS" - ) - weakSelf?.viewModel.stickTopInfos[session] = nil - } - } } // 置顶和取消置顶 @@ -355,6 +368,8 @@ extension ConversationListViewController { extension ConversationListViewController: ConversationViewModelDelegate { public func didAddRecentSession() { + NELog.infoLog("ConversationListViewController", desc: "didAddRecentSession") + emptyView.isHidden = (viewModel.conversationListArray?.count ?? 0) > 0 viewModel.sortRecentSession() tableView.reloadData() } @@ -365,6 +380,7 @@ extension ConversationListViewController: ConversationViewModelDelegate { } public func reloadTableView() { + emptyView.isHidden = (viewModel.conversationListArray?.count ?? 0) > 0 viewModel.sortRecentSession() tableView.reloadData() } diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationSearchController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationSearchController.swift index 70d9506b..c959a9db 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationSearchController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/ConversationSearchController.swift @@ -151,6 +151,7 @@ open class ConversationSearchController: ConversationBaseViewController, UITable let tableView = UITableView(frame: .zero, style: .plain) tableView.translatesAutoresizingMaskIntoConstraints = false tableView.separatorStyle = .none + tableView.keyboardDismissMode = .onDrag tableView.delegate = self tableView.dataSource = self tableView.register( @@ -279,6 +280,7 @@ open class ConversationSearchController: ConversationBaseViewController, UITable ) as! SearchSessionHeaderView sectionView.setUpTitle(title: headTitleArr[section]) sectionView.backgroundView = UIView() + sectionView.backgroundView?.backgroundColor = .white return sectionView } diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/View/ConversationListCell.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/View/ConversationListCell.swift index 42585b6a..8dac7f95 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/View/ConversationListCell.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/View/ConversationListCell.swift @@ -10,7 +10,7 @@ open class ConversationListCell: UITableViewCell { // private var viewModel = ConversationViewModel() public var topStickInfos = [NIMSession: NIMStickTopSessionInfo]() private let repo = ConversationRepo() - + private var timeWidth: NSLayoutConstraint? override open func awakeFromNib() { super.awakeFromNib() // Initialization code @@ -52,11 +52,12 @@ open class ConversationListCell: UITableViewCell { ]) NSLayoutConstraint.activate([ - redAngleView.centerXAnchor.constraint(equalTo: headImge.rightAnchor, constant: -3), - redAngleView.centerYAnchor.constraint(equalTo: headImge.topAnchor, constant: 3), + redAngleView.centerXAnchor.constraint(equalTo: headImge.rightAnchor, constant: -8), + redAngleView.centerYAnchor.constraint(equalTo: headImge.topAnchor, constant: 8), redAngleView.heightAnchor.constraint(equalToConstant: 18), ]) - + timeWidth = timeLabel.widthAnchor.constraint(equalToConstant: 0) + timeWidth?.isActive = true NSLayoutConstraint.activate([ timeLabel.rightAnchor.constraint( equalTo: contentView.rightAnchor, @@ -160,6 +161,12 @@ open class ConversationListCell: UITableViewCell { timeLabel .text = dealTime(time: timestampDescriptionForRecentSession(recentSession: rencentSession)) + if let text = timeLabel.text { + let maxSize = CGSize(width: UIScreen.main.bounds.width, height: 0) + let attibutes = [NSAttributedString.Key.font: timeLabel.font] + let labelSize = NSString(string: text).boundingRect(with: maxSize, attributes: attibutes, context: nil) + timeWidth?.constant = labelSize.width + 1 // ceil() + } } // backgroundColor diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift index 12e94056..109a0a05 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift @@ -8,7 +8,6 @@ import NIMSDK let revokeLocalMessage = "revoke_message_local" let revokeLocalMessageContent = "revoke_message_local_content" -// let firstInit = "first_init" public protocol ConversationViewModelDelegate: NSObjectProtocol { func didAddRecentSession() @@ -23,9 +22,10 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, public var stickTopInfos = [NIMSession: NIMStickTopSessionInfo]() public weak var delegate: ConversationViewModelDelegate? private let className = "ConversationViewModel" - let repo = ConversationRepo() + public let repo = ConversationRepo() var cacheUpdateSessionDic = [String: NIMRecentSession]() + var cacheAddSessionDic = [String: ConversationListModel]() override public init() { NELog.infoLog(ModuleName + " " + className, desc: #function) @@ -43,18 +43,46 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, NELog.infoLog(ModuleName + " " + className, desc: #function) weak var weakSelf = self repo.getSessionList { error, conversaitonList in - weakSelf?.conversationListArray = conversaitonList - print("get session list : ", conversaitonList?.count as Any) - conversaitonList?.forEach { model in - if let recentSession = model.recentSession, let sid = recentSession.session?.sessionId { - if let recent = weakSelf?.cacheUpdateSessionDic[sid] { - if let time1 = recentSession.lastMessage?.timestamp, let time2 = recent.lastMessage?.timestamp, time1 < time2 { - model.recentSession = recent + DispatchQueue.main.async { + weakSelf?.conversationListArray = conversaitonList + NELog.infoLog(ModuleName, desc: "get session list : \(conversaitonList?.count ?? 0)") + var set = Set() + conversaitonList?.forEach { model in + NELog.infoLog(ModuleName, desc: "get session sid : \(model.recentSession?.session?.sessionId ?? "nil")") + if let recentSession = model.recentSession, let sid = recentSession.session?.sessionId { + set.insert(sid) + if let recent = weakSelf?.cacheUpdateSessionDic[sid] { + NELog.infoLog(ModuleName, desc: "cacheUpdateSessionDic fitler sid: \(recent.session?.sessionId ?? "nil")") + if let time1 = recentSession.lastMessage?.timestamp, let time2 = recent.lastMessage?.timestamp, time1 < time2 { + model.recentSession = recent + } } + + if let recent = weakSelf?.cacheAddSessionDic[sid]?.recentSession { + NELog.infoLog(ModuleName, desc: "cacheAddSessionDic fitler sid: \(recent.session?.sessionId ?? "nil")") + if let time1 = recentSession.lastMessage?.timestamp, let time2 = recent.lastMessage?.timestamp, time1 < time2 { + model.recentSession = recent + } + } + } + } + NELog.infoLog(ModuleName, desc: "cacheAddSessionDic count: \(weakSelf?.cacheAddSessionDic.count ?? 0)") + weakSelf?.cacheAddSessionDic.forEach { (key: String, value: ConversationListModel) in + NELog.infoLog(ModuleName, desc: "cacheAddSessionDic key: \(key)") + if set.contains(key) == false { + if let recent = weakSelf?.cacheUpdateSessionDic[key] { + if let time1 = value.recentSession?.lastMessage?.timestamp, let time2 = recent.lastMessage?.timestamp, time1 < time2 { + value.recentSession = recent + } + } + NELog.infoLog(ModuleName, desc: "cacheAddSessionDic : \(key)") + weakSelf?.conversationListArray?.append(value) } } + weakSelf?.cacheAddSessionDic.removeAll() + NELog.infoLog(ModuleName, desc: "conversationListArray count : \(weakSelf?.conversationListArray?.count ?? 0)") + completion(error, weakSelf?.conversationListArray) } - completion(error, weakSelf?.conversationListArray) } } @@ -182,13 +210,13 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, // MARK: ==================== ConversationRepoDelegate ========================== public func onNotifyAddStickTopSession(_ newInfo: NIMStickTopSessionInfo) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", sessionId:" + newInfo.session.sessionId) + NELog.infoLog(ModuleName + " " + className, desc: #function + ",onNotifyAddStickTopSession sessionId:" + newInfo.session.sessionId) stickTopInfos[newInfo.session] = newInfo delegate?.reloadTableView() } public func onNotifyRemoveStickTopSession(_ removedInfo: NIMStickTopSessionInfo) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", sessionId:" + removedInfo.session.sessionId) + NELog.infoLog(ModuleName + " " + className, desc: #function + ",onNotifyRemoveStickTopSession sessionId:" + removedInfo.session.sessionId) stickTopInfos[removedInfo.session] = nil delegate?.reloadTableView() } @@ -202,25 +230,64 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, NELog.errorLog(ModuleName + " " + className, desc: "❌sessionId is nil") return } - NELog.infoLog(ModuleName + " " + className, desc: #function + ", targetId:" + targetId) + NELog.infoLog(ModuleName + " " + className, desc: #function + ", did add session targetId:" + targetId) + DispatchQueue.main.async {} + if let object = recentSession.lastMessage?.messageObject as? NIMNotificationObject, object.notificationType == .team { + if let content = object.content as? NIMTeamNotificationContent { + if content.operationType == .dismiss || (content.operationType == .leave && content.sourceID == NIMSDK.shared().loginManager.currentAccount()) { + NELog.infoLog( + ModuleName + " " + className, + desc: #function + "didAdd team dismiss or leave noti" + (recentSession.session?.sessionId ?? "nil") + ) + repo.deleteLocalSession(recentSession: recentSession) + return + } + } + } + weak var weakSelf = self - let listModel = ConversationListModel() + var listModel = ConversationListModel() + if let sid = recentSession.session?.sessionId { + print("session session id : ", sid) + if let model = cacheAddSessionDic[sid] { + listModel = model + NELog.infoLog( + ModuleName + " " + className, + desc: #function + "didAdd team has added" + (recentSession.session?.sessionId ?? "nil") + ) + } + cacheAddSessionDic[sid] = listModel + } listModel.recentSession = recentSession if recentSession.session?.sessionType == .P2P { repo.getUserInfo(userId: targetId) { user, error in if error == nil { - DispatchQueue.main.async { - listModel.userInfo = user + listModel.userInfo = user + if let model = weakSelf?.sessionIsExist(listModel) { + NELog.infoLog( + ModuleName, + desc: #function + "conversation session user : " + "\(user?.userId ?? "nil")" + ) + model.userInfo = user + } else { weakSelf?.conversationListArray?.append(listModel) - weakSelf?.delegate?.didAddRecentSession() } + weakSelf?.delegate?.didAddRecentSession() } } } else if recentSession.session?.sessionType == .team { repo.getTeamInfo(teamId: targetId) { error, teamInfo in listModel.teamInfo = teamInfo - weakSelf?.conversationListArray?.append(listModel) + if let model = weakSelf?.sessionIsExist(listModel) { + NELog.infoLog( + ModuleName, + desc: #function + "conversation session team : " + "\(teamInfo?.teamId ?? "nil")" + ) + model.teamInfo = teamInfo + } else { + weakSelf?.conversationListArray?.append(listModel) + } weakSelf?.delegate?.didAddRecentSession() } } @@ -229,20 +296,41 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, public func didUpdate(_ recentSession: NIMRecentSession, totalUnreadCount: Int) { NELog.infoLog( ModuleName + " " + className, - desc: #function + ", sessionId:" + (recentSession.session?.sessionId ?? "nil") + desc: #function + "recentSession, didUpdate sessionId:" + (recentSession.session?.sessionId ?? "nil") ) - print("did update last msg : ", recentSession.lastMessage?.text as Any) + + if let object = recentSession.lastMessage?.messageObject as? NIMNotificationObject, object.notificationType == .team { + if let content = object.content as? NIMTeamNotificationContent { + if content.operationType == .dismiss || (content.operationType == .leave && content.sourceID == NIMSDK.shared().loginManager.currentAccount()) { + NELog.infoLog( + ModuleName + " " + className, + desc: #function + "didUpdate team dismiss or leave noti" + (recentSession.session?.sessionId ?? "nil") + ) + repo.deleteLocalSession(recentSession: recentSession) + return + } + } + } + if let sid = recentSession.session?.sessionId { cacheUpdateSessionDic[sid] = recentSession + if let model = cacheAddSessionDic[sid], let recent = model.recentSession { + if let time1 = recentSession.lastMessage?.timestamp, let time2 = recent.lastMessage?.timestamp, time1 > time2 { + model.recentSession = recentSession + } + } } + if let _ = conversationListArray { for i in 0 ..< conversationListArray!.count { let listModel = conversationListArray![i] + NELog.infoLog( + ModuleName + " " + className, + desc: #function + "update session id : " + (listModel.recentSession?.session?.sessionId ?? "nil") + ) if recentSession.session?.sessionId == listModel.recentSession?.session?.sessionId { -// conversationListArray?.remove(at: i) listModel.recentSession = recentSession delegate?.reloadTableView() -// delegate?.didUpdateRecentSession(index: i) break } } @@ -252,8 +340,11 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, public func didRemove(_ recentSession: NIMRecentSession, totalUnreadCount: Int) { NELog.infoLog( ModuleName + " " + className, - desc: #function + ", sessionId:" + (recentSession.session?.sessionId ?? "nil") + desc: #function + ",didRemove recentSession sessionId:" + (recentSession.session?.sessionId ?? "nil") ) + if let sid = recentSession.session?.sessionId { + cacheUpdateSessionDic.removeValue(forKey: sid) + } if let conversationArr = conversationListArray { for i in 0 ..< conversationArr.count { if conversationArr[i].recentSession?.session?.sessionId == recentSession.session? @@ -266,7 +357,7 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, delegate?.reloadTableView() } - // MARK: ========================NIMTeamManagerDelegate========================= + // MARK: ========================NIMUserManagerDelegate========================= public func onFriendChanged(_ user: NIMUser) { NELog.infoLog(ModuleName + " " + className, desc: #function + ", userId:" + (user.userId ?? "nil")) @@ -299,7 +390,14 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, } } - public func onTeamAdded(_ team: NIMTeam) {} + public func onTeamAdded(_ team: NIMTeam) { + NELog.infoLog(ModuleName + " " + className, desc: #function + "onTeamAdded, teamId:" + (team.teamId ?? "nil")) + guard let tid = team.teamId else { + return + } + let _ = repo.createTeamSession(tid) + delegate?.didAddRecentSession() + } public func onTeamRemoved(_ team: NIMTeam) { NELog.infoLog(ModuleName + " " + className, desc: #function + ", teamId:" + (team.teamId ?? "nil")) @@ -320,4 +418,16 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, } } } + + private func sessionIsExist(_ model: ConversationListModel) -> ConversationListModel? { + if let array = conversationListArray { + for index in 0 ..< array.count { + let m = array[index] + if m.recentSession?.session?.sessionId == model.recentSession?.session?.sessionId { + return m + } + } + } + return nil + } } diff --git a/NEMapKit/NEMapKit.podspec b/NEMapKit/NEMapKit.podspec index 1baf0da8..9e922ab0 100644 --- a/NEMapKit/NEMapKit.podspec +++ b/NEMapKit/NEMapKit.podspec @@ -21,10 +21,12 @@ Pod::Spec.new do |s| TODO: Add long description of the pod here. DESC - s.homepage = 'http://netease.im' + s.homepage = 'https://github.com/xushandong/NEMapKit' + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license = { :'type' => 'Copyright', :'text' => ' Copyright 2022 Netease '} s.author = 'yunxin engineering department' s.source = { :git => 'ssh://git@g.hz.netease.com:22222/yunxin-app/xkit-ios.git', :tag => s.version.to_s } + # s.social_media_url = 'https://twitter.com/' s.ios.deployment_target = '9.0' diff --git a/NEMapKit/NEMapKit/Classes/NEMapService.m b/NEMapKit/NEMapKit/Classes/NEMapService.m index 19f2bd90..f99f4a98 100644 --- a/NEMapKit/NEMapKit/Classes/NEMapService.m +++ b/NEMapKit/NEMapKit/Classes/NEMapService.m @@ -42,6 +42,7 @@ - (void)setupMapClient { - (void)setupMapSdkConfig { // 初始化高德SDK + [[AMapServices sharedServices] setApiKey:@"46a3a36bb9d26934a26c6ce2b04aab6f"]; [AMapServices sharedServices].enableHTTPS = YES; } diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Frame@2x-4.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Frame@2x-4.png deleted file mode 100644 index 0f6ea9a6..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Frame@2x-4.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Frame@3x-4.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Frame@3x-4.png deleted file mode 100644 index 4d47a424..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Frame@3x-4.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Frame@2x-1.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Frame@2x-1.png deleted file mode 100644 index 072e58ff..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Frame@2x-1.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Frame@3x-1.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Frame@3x-1.png deleted file mode 100644 index 3c849522..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/emoji.imageset/Frame@3x-1.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Frame@2x-3.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Frame@2x-3.png deleted file mode 100644 index 38c3fb8b..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Frame@2x-3.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Frame@3x-3.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Frame@3x-3.png deleted file mode 100644 index 235f905e..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Frame@3x-3.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Frame@2x.png deleted file mode 100644 index 91f82535..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Frame@3x.png deleted file mode 100644 index ada47463..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/mic.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Frame@2x-2.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Frame@2x-2.png deleted file mode 100644 index aa7702f7..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Frame@2x-2.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Frame@3x-2.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Frame@3x-2.png deleted file mode 100644 index c9c54c1f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Frame@3x-2.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/sendMessage_failed.imageset/sendMessage_failed.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/sendMessage_failed.imageset/sendMessage_failed.png deleted file mode 100644 index 46d65710..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/sendMessage_failed.imageset/sendMessage_failed.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Contents.json deleted file mode 100644 index c7958429..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame 214@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame 214@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Frame 214@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Frame 214@2x.png deleted file mode 100644 index 92db4e7c..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Frame 214@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Frame 214@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Frame 214@3x.png deleted file mode 100644 index d5d2b7f2..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowDown.imageset/Frame 214@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Contents.json deleted file mode 100644 index 1e58aaa3..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector 87@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector 87@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Vector 87@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Vector 87@2x.png deleted file mode 100644 index f016602e..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Vector 87@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Vector 87@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Vector 87@3x.png deleted file mode 100644 index f7365d80..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowRight.imageset/Vector 87@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Contents.json deleted file mode 100644 index c7958429..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame 214@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame 214@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Frame 214@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Frame 214@2x.png deleted file mode 100644 index 2b954ea3..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Frame 214@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Frame 214@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Frame 214@3x.png deleted file mode 100644 index 1201d4ab..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/arrowUp.imageset/Frame 214@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/back@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/back@2x.png deleted file mode 100644 index 84a02c61..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/back@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/back@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/back@3x.png deleted file mode 100644 index fb907104..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/backArrow.imageset/back@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Frame@2x.png deleted file mode 100644 index 09437669..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Frame@3x.png deleted file mode 100644 index 60648a9d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Contents.json deleted file mode 100644 index 221d581f..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame 1016@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame 1016@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Frame 1016@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Frame 1016@2x.png deleted file mode 100644 index f35b38b1..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Frame 1016@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Frame 1016@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Frame 1016@3x.png deleted file mode 100644 index 4403d35d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/memberPlaceholder.imageset/Frame 1016@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Contents.json deleted file mode 100644 index 28819b06..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame 1018@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame 1018@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Frame 1018@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Frame 1018@2x.png deleted file mode 100644 index a4cb4bd3..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Frame 1018@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Frame 1018@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Frame 1018@3x.png deleted file mode 100644 index ac3d2429..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/rolePlaceholder.imageset/Frame 1018@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Frame@2x.png deleted file mode 100644 index 510d989f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Frame@3x.png deleted file mode 100644 index a4c9a4c5..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/Contents.json deleted file mode 100644 index c2fd49ca..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "select@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "select@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/select@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/select@2x.png deleted file mode 100644 index c405145b..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/select@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/select@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/select@3x.png deleted file mode 100644 index 8566dac8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/select.imageset/select@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/Contents.json deleted file mode 100644 index a21177d3..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "添加@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "添加@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git "a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/\346\267\273\345\212\240@2x.png" "b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/\346\267\273\345\212\240@2x.png" deleted file mode 100644 index bebcf2e5..00000000 Binary files "a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/\346\267\273\345\212\240@2x.png" and /dev/null differ diff --git "a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/\346\267\273\345\212\240@3x.png" "b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/\346\267\273\345\212\240@3x.png" deleted file mode 100644 index 33c96fc5..00000000 Binary files "a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/sign_add.imageset/\346\267\273\345\212\240@3x.png" and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/Contents.json deleted file mode 100644 index c5aa7629..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "unselect@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "unslect@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/unselect@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/unselect@2x.png deleted file mode 100644 index 2d699bb8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/unselect@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/unslect@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/unslect@3x.png deleted file mode 100644 index 08d6c8fe..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/unselect.imageset/unslect@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/Contents.json deleted file mode 100644 index db27807a..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "addOther_icon@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "addOther_icon@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/addOther_icon@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/addOther_icon@2x.png deleted file mode 100644 index 16f6097b..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/addOther_icon@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/addOther_icon@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/addOther_icon@3x.png deleted file mode 100644 index 08dce661..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addOther_icon.imageset/addOther_icon@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/Contents.json deleted file mode 100644 index 14b9694c..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "addService_icon@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "addService_icon@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/addService_icon@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/addService_icon@2x.png deleted file mode 100644 index 4d10a406..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/addService_icon@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/addService_icon@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/addService_icon@3x.png deleted file mode 100644 index 580aacfb..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/addService_icon.imageset/addService_icon@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/Contents.json deleted file mode 100644 index 366436aa..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "cell_arrow_icon@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "cell_arrow_icon@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/cell_arrow_icon@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/cell_arrow_icon@2x.png deleted file mode 100644 index 41a4a1ff..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/cell_arrow_icon@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/cell_arrow_icon@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/cell_arrow_icon@3x.png deleted file mode 100644 index 1ebc9e36..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/cell_arrow_icon.imageset/cell_arrow_icon@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/Contents.json deleted file mode 100644 index a706fae8..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "chat_message_receive@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "chat_message_receive@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/chat_message_receive@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/chat_message_receive@2x.png deleted file mode 100644 index 1fdd05b0..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/chat_message_receive@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/chat_message_receive@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/chat_message_receive@3x.png deleted file mode 100644 index 8d74569f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_receive.imageset/chat_message_receive@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/Contents.json deleted file mode 100644 index 0136120c..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "chat_message_send@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "chat_message_send@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/chat_message_send@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/chat_message_send@2x.png deleted file mode 100644 index d342d9eb..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/chat_message_send@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/chat_message_send@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/chat_message_send@3x.png deleted file mode 100644 index 7852b2e2..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/chat_message_send.imageset/chat_message_send@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/Contents.json deleted file mode 100644 index a22aefff..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "home_addChannel@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "home_addChannel@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/home_addChannel@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/home_addChannel@2x.png deleted file mode 100644 index 9abd0ae8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/home_addChannel@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/home_addChannel@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/home_addChannel@3x.png deleted file mode 100644 index 89c674bf..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_addChannel.imageset/home_addChannel@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/Contents.json deleted file mode 100644 index e1e19aa6..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "home_setupServer@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "home_setupServer@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/home_setupServer@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/home_setupServer@2x.png deleted file mode 100644 index fe69cbbe..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/home_setupServer@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/home_setupServer@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/home_setupServer@3x.png deleted file mode 100644 index 14953f2a..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/home_setupServer.imageset/home_setupServer@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/Contents.json deleted file mode 100644 index 951fba53..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "mine_create@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "mine_create@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/mine_create@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/mine_create@2x.png deleted file mode 100644 index 9841dbdf..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/mine_create@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/mine_create@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/mine_create@3x.png deleted file mode 100644 index 350cd68f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/mine_create.imageset/mine_create@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/Contents.json deleted file mode 100644 index d0e53980..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "otherService_search_icon@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "otherService_search_icon@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/otherService_search_icon@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/otherService_search_icon@2x.png deleted file mode 100644 index cb2dbf9c..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/otherService_search_icon@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/otherService_search_icon@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/otherService_search_icon@3x.png deleted file mode 100644 index 6a960f08..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/otherService_search_icon.imageset/otherService_search_icon@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/Contents.json deleted file mode 100644 index 83eb1daf..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "uploadPic_bg_icon@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "uploadPic_bg_icon@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/uploadPic_bg_icon@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/uploadPic_bg_icon@2x.png deleted file mode 100644 index b5cbc9ab..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/uploadPic_bg_icon@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/uploadPic_bg_icon@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/uploadPic_bg_icon@3x.png deleted file mode 100644 index 5679e5f3..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/uploadPic_bg_icon.imageset/uploadPic_bg_icon@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/Contents.json deleted file mode 100644 index ed6c29e2..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "upload_camera@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "upload_camera@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/upload_camera@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/upload_camera@2x.png deleted file mode 100644 index 5b7ae800..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/upload_camera@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/upload_camera@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/upload_camera@3x.png deleted file mode 100644 index 988ac838..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Home/upload_camera.imageset/upload_camera@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Vector@2x.png deleted file mode 100644 index 09bc30be..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Vector@3x.png deleted file mode 100644 index 1d28b755..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/camera.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Vector@2x.png deleted file mode 100644 index 4721c521..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Vector@3x.png deleted file mode 100644 index b00bd55e..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/count_header.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Vector@2x.png deleted file mode 100644 index afcebe86..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Vector@3x.png deleted file mode 100644 index cbafa396..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Vector@2x.png deleted file mode 100644 index afcebe86..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Vector@3x.png deleted file mode 100644 index cbafa396..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/dot_image_disable.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Contents.json deleted file mode 100644 index c20c93f7..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group 389@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group 389@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Group 389@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Group 389@2x.png deleted file mode 100644 index ab7dbd9d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Group 389@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Group 389@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Group 389@3x.png deleted file mode 100644 index ade59432..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_header.imageset/Group 389@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Vector@2x.png deleted file mode 100644 index f44bdaea..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Vector@3x.png deleted file mode 100644 index 6c56fd15..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/id_group_sort.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/Contents.json deleted file mode 100644 index 7e073d79..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "invitemember_success@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "invitemember_success@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/invitemember_success@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/invitemember_success@2x.png deleted file mode 100644 index 15801fcc..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/invitemember_success@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/invitemember_success@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/invitemember_success@3x.png deleted file mode 100644 index 15801fcc..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/invitemember_success.imageset/invitemember_success@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Vector@2x.png deleted file mode 100644 index ad1ba57c..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Vector@3x.png deleted file mode 100644 index 9de1ccb2..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/lock.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Contents.json deleted file mode 100644 index 798a6cec..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group 390@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group 390@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Group 390@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Group 390@2x.png deleted file mode 100644 index fe976b46..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Group 390@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Group 390@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Group 390@3x.png deleted file mode 100644 index 418325fa..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/member_header.imageset/Group 390@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/Contents.json deleted file mode 100644 index 0c85eb3f..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "channel_noMore@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "channel_noMore@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/channel_noMore@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/channel_noMore@2x.png deleted file mode 100644 index b392057d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/channel_noMore@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/channel_noMore@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/channel_noMore@3x.png deleted file mode 100644 index 7d4a3732..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/searchServer_noMoreData.imageset/channel_noMore@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/Contents.json deleted file mode 100644 index 1fc9c30c..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "servers_noMore@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "servers_noMore@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/servers_noMore@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/servers_noMore@2x.png deleted file mode 100644 index f2d188fe..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/servers_noMore@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/servers_noMore@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/servers_noMore@3x.png deleted file mode 100644 index 9178c9ef..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Server/servers_noMore.imageset/servers_noMore@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Vector@2x.png deleted file mode 100644 index 94c1d80f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Vector@3x.png deleted file mode 100644 index 062ac756..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Selection.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Contents.json deleted file mode 100644 index 6a4d508b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Vector@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Vector@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Vector@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Vector@2x.png deleted file mode 100644 index c6650106..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Vector@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Vector@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Vector@3x.png deleted file mode 100644 index 73c3a9a8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/Setting.imageset/Vector@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Contents.json deleted file mode 100644 index 4bdf5bae..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x-1.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x-1.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Frame@2x-1.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Frame@2x-1.png deleted file mode 100644 index 091a686d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Frame@2x-1.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Frame@3x-1.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Frame@3x-1.png deleted file mode 100644 index 2c806fb8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allow.imageset/Frame@3x-1.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Contents.json deleted file mode 100644 index 5c4d3b18..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Frame@2x.png deleted file mode 100644 index 95a388e8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Frame@3x.png deleted file mode 100644 index 198fa556..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/allowSeleted.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/Contents.json deleted file mode 100644 index 7ee51000..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "image 86@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "image 86@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/image 86@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/image 86@2x.png deleted file mode 100644 index 90ae2799..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/image 86@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/image 86@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/image 86@3x.png deleted file mode 100644 index 9715babf..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/bgImage.imageset/image 86@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Contents.json deleted file mode 100644 index 5c4d3b18..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Frame@2x.png deleted file mode 100644 index 4a4bc5c8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Frame@3x.png deleted file mode 100644 index 907d325d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_member.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/Contents.json deleted file mode 100644 index 5349fd24..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "channel_noMoreData@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "channel_noMoreData@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/channel_noMoreData@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/channel_noMoreData@2x.png deleted file mode 100644 index 0bc13f6f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/channel_noMoreData@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/channel_noMoreData@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/channel_noMoreData@3x.png deleted file mode 100644 index 4854f626..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/channel_noMoreData.imageset/channel_noMoreData@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Contents.json deleted file mode 100644 index 5c4d3b18..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Frame@2x.png deleted file mode 100644 index bebef76f..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Frame@3x.png deleted file mode 100644 index c1f6128d..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/deny.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Contents.json deleted file mode 100644 index 5c4d3b18..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Frame@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Frame@2x.png deleted file mode 100644 index 7ec96cf8..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Frame@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Frame@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Frame@3x.png deleted file mode 100644 index 005a1f90..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/denySelected.imageset/Frame@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Contents.json deleted file mode 100644 index 535209c9..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x-2.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x-2.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Frame@2x-2.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Frame@2x-2.png deleted file mode 100644 index c37a9a62..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Frame@2x-2.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Frame@3x-2.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Frame@3x-2.png deleted file mode 100644 index ea576701..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extend.imageset/Frame@3x-2.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Contents.json deleted file mode 100644 index 535209c9..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame@2x-2.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame@3x-2.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Frame@2x-2.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Frame@2x-2.png deleted file mode 100644 index a39d14c1..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Frame@2x-2.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Frame@3x-2.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Frame@3x-2.png deleted file mode 100644 index 0a0c2a52..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/extendSelected.imageset/Frame@3x-2.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Contents.json deleted file mode 100644 index c3567749..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Frame 245@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Frame 245@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Frame 245@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Frame 245@2x.png deleted file mode 100644 index 2cf4456e..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Frame 245@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Frame 245@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Frame 245@3x.png deleted file mode 100644 index 77c29b7c..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server.imageset/Frame 245@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Contents.json b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Contents.json deleted file mode 100644 index bfcf9f2d..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group 329@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group 329@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Group 329@2x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Group 329@2x.png deleted file mode 100644 index c1d2cce4..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Group 329@2x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Group 329@3x.png b/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Group 329@3x.png deleted file mode 100644 index 667e2fd5..00000000 Binary files a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/channel/server_menu.imageset/Group 329@3x.png and /dev/null differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/en.lproj/Localizable.strings b/NEQChatUIKit/NEQChatUIKit/Assets/en.lproj/Localizable.strings deleted file mode 100644 index ac1a8db2..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/en.lproj/Localizable.strings +++ /dev/null @@ -1,165 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -//MAKR:common -"ok"="Ok"; -"exceed"="Exceed"; -"person"="Member"; -"limit"="Limit"; - - -//MARK: Server -"qchat_setting"="Server Settings"; -"qchat_delete_server"="Delete Server"; -"qchat_leave_server"="Exit Server"; -"qchat_permisssion"="Permission"; -"qchat_server_theme"="Server Theme"; -"qchat_server_name"="Server Name"; -"qchat_id_group"="Role"; -"qchat_group_default_permission"="Default Permission for everyone"; -"qchat_sort"="sort"; -"qchat_create_new_id_group"="Create new Role"; -"qchat_group_name"="Role Name"; -"qchat_manager_member"="Role management"; -"qchat_edit"="Edit"; -"qchat_save"="Save"; -"qchat_nickname"="Nick Name"; -"qcaht_edit_nickname"="Edit Nick Name"; -"qchat_kick_out"="Kick out"; -"qchat_prohibit"="Prohibit"; -"qchat_manager_server"="Manage Server"; -"qchat_manager_channel"="Manage all cannel info"; -"qchat_manager_role"="Manage Role"; -"qchat_send_message"="Send Message"; -"qchat_delete_message"="Delete other's message in Server"; -"qchat_recall_message"="Recall other's message in Server"; -"qchat_at_any"="@ anyone"; -"qchat_at_all"="@ everyone"; -"qchat_modify_own_server"="Edit my info in Server"; -"qchat_modify_other_server"="Edit other's Server info"; -"qchat_invite_member"="Invite Permission"; -"qchat_kickout_member"="Kick out"; -"qchat_manager_channel_list"="Manage channel members"; -"qchat_common_permission"="Common Permission"; -"qchat_message_permission"="Message Permission"; -"qchat_member_permission"="Member Permission"; -"qchat_member"="Member"; -"qchat_id_group_sort"="Role Sort"; -"qchat_sure"="Ok"; -"qchat_cancel"="cancel"; -"qchat_tip"="Tip"; -"qchat_select"="Select"; -"qchat_please_input_topic"="Please enter the theme"; -"qchat_not_empty_servername"="Please Name the server"; -"qchat_not_empty_header_url"="Please upload Avator"; -"qchat_not_empty_select_memeber"="Please Select member"; -"qchat_please_input_role_name"="Please set the role name"; -"qchat_sure_delete_user"="wether to delete this member"; -"qchat_delete_success"="Delete successfully"; -"qchat_add_success"="Add successfully"; -"qchat_add_Server"="create Server"; -"qchat_mine_add"="create"; -"qchat_join_otherServer"="Join other Server"; - -//MARK: Channel -"create_channel"="Create New Channel"; -"delete_channel"="Delete Channel"; -"confirm_delete_channel"="Sure to Remove ?"; - -"create"="Creat"; -"cancel"="Cancel"; -"channel_name"="Channel Name"; -"channel_topic"="Channel Theme"; -"channel_type"="Channel Type"; -"input_channel_name"="Enter Name"; -"input_channel_topic"="Enter Theme"; -"public"="Public"; -"private"="Private"; -"online"="Online"; -"offline"="Offline"; -"first_channel"="Channel 1"; -"second_channel"="channel 2"; -"more"="More"; -"has_no_role"="No more role"; -"send_to"="Send to"; -"image_is_nil"= "No picture"; - - -//MARK:toast -"update_channel_suscess"="Save Successfully"; -"delete_channel_suscess"="Delete Successfully"; -"open_soon"="Not Open"; - -//MARK: channel_setting -"channel_setting"="Channel Setting"; -"save"="Save"; -"close"="Close"; -"authority"="Permission"; -"authority_setting"="Permission Setting"; -"list"="List"; -"white_list"="whitelist"; -"black_list"="blacklist"; -"channel_member"="Channel Member"; -"delete_channel"="Delete Channel"; - -"add_group"="Add Role"; -"add_member"="Add member"; -"member_permission_setting"="Member Permission Setting"; -"finish"="Finish"; -"removeMember"="Remove Memebr"; -"removeRole"="Remove Role"; - -//MARK:身份组权限设置 -"auth1"="ManageServer"; -"auth2"="Manage Channel Info"; -"auth3"="Manage Channel Permission"; -"auth4"="Send Message"; -"auth5"="ModifySelfInfo"; -"auth6"="InviteToServer"; -"auth7"="KickOthersInServer"; -"auth8"="ModifyOthersInfoInServer"; -"auth9"="Recall other's Message"; -"auth10"="Delete other's Message"; -"auth11"="RemindOther"; -"auth12"="RemindAll"; -"auth13"="Manage Channel Memeber"; - -//supplement -"delete"="delete"; -"share_thoughts"="Share Thoughts"; -"noMember_add"="No member to add"; -"search_serverId"="Search ServerID"; -"no_serverId"="Not Found"; -"know"="ok"; -"upload_headImage"="Upload Avator"; -"enter_serverName"="Please enter server name"; -"request_sended"="invit sent"; -"message_channel"="Message Channel"; -"server_nochannel"="No Channel"; -"applied"="Applied"; -"join"="Join"; -"modify_nickname"="Click to edit nick name"; -"sure_exit_server"="wether to exit server?"; -"sure_delete_server"="wether to delete server?"; -"serverId_notbe_empty"="Cannot be empty "; -"enter_name"="Enter Name"; -"kick_currentMember"="Wether to kick out this member?"; -"sure_delete"=" Wether to delete?"; -"current_identity"="Current Identity Group"; -"hm"="HH:mm"; -"mdhm"="MM.dd HH:mm"; -"ymdhm"="yyyy.MM.dd HH:mm"; - -//MARK:error toast -"param_error"="Parameter error"; -"no_Permession"="No permission to send message"; -"channelName_cannot_be_empty"="Cannot be empty"; -"network_error"="No internet"; -"cant_join"="Cannot join?"; -"blocked_from_server_cant_join"="You are blocked by this server and cannot join"; -"serverName_limit"="Cannot exceed 50 characters"; -"add_favorite_service"="No Server, Let's join or create one"; -"nickName_not_empty"="Cannot be empty "; -"accid_not_empty"="Cannot be empty"; diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NEQChatUIKit/NEQChatUIKit/Assets/zh-Hans.lproj/Localizable.strings deleted file mode 100644 index 2adab88c..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Assets/zh-Hans.lproj/Localizable.strings +++ /dev/null @@ -1,168 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -//MAKR:common -"ok"="确认"; -"exceed"="超出"; -"person"="人"; -"limit"="限制"; - - -//MARK: Server -"qchat_setting"="服务器设置"; -"qchat_delete_server"="删除服务器"; -"qchat_leave_server"="退出服务器"; -"qchat_permisssion"="权限"; -"qchat_server_theme"="服务器主题"; -"qchat_server_name"="服务器名称"; -"qchat_id_group"="身份组"; -"qchat_group_default_permission"="所有服务器成员默认权限"; -"qchat_sort"="排序"; -"qchat_create_new_id_group"="创建新身份组"; -"qchat_group_name"="身份组名称"; -"qchat_manager_member"="成员管理"; -"qchat_edit"="编辑"; -"qchat_save"="保存"; -"qchat_nickname"="昵称"; -"qcaht_edit_nickname"="编辑昵称"; -"qchat_kick_out"="踢除"; -"qchat_prohibit"="封禁"; -"qchat_manager_server"="管理服务器"; -"qchat_manager_channel"="管理所有频道属性"; -"qchat_manager_role"="管理角色"; -"qchat_send_message"="发送消息"; -"qchat_delete_message"="所有频道中删除他人消息"; -"qchat_recall_message"="所有频道撤回他人消息"; -"qchat_at_any"="@任意人的权限"; -"qchat_at_all"="@所有人的权限"; -"qchat_modify_own_server"="修改自己服务器成员信息"; -"qchat_modify_other_server"="修改他人服务器成员信息"; -"qchat_invite_member"="邀请他人进入server权限"; -"qchat_kickout_member"="踢人"; -"qchat_manager_channel_list"="管理频道名单"; -"qchat_common_permission"="通用权限"; -"qchat_message_permission"="消息权限"; -"qchat_member_permission"="成员权限"; -"qchat_member"="成员"; -"qchat_id_group_sort"="身份组排序"; -"qchat_sure"="确定"; -"qchat_cancel"="取消"; -"qchat_tip"="提示"; -"qchat_select"="选择"; -"qchat_please_input_topic"="请输入主题"; -"qchat_not_empty_servername"="服务器名不能为空"; -"qchat_not_empty_header_url"="请先上传头像"; -"qchat_not_empty_select_memeber"="请选择用户"; -"qchat_please_input_role_name"="请输入身份组名称"; -"qchat_sure_delete_user"="确定删除当前用户?"; -"qchat_delete_success"="删除成功"; -"qchat_add_success"="添加成功"; -"qchat_add_Server"="创建服务器"; -"qchat_mine_add"="自己创建"; -"qchat_join_otherServer"="加入别人服务器"; - -//MARK: Channel -"create_channel"="创建新频道"; -"delete_channel"="删除频道"; -"confirm_delete_channel"="确认要移除"; - -"create"="创建"; -"cancel"="取消"; -"channel_name"="频道名称"; -"channel_topic"="频道主题"; -"channel_type"="频道类型"; -"input_channel_name"="请输入名称"; -"input_channel_topic"="请输入主题"; -"public"="公开"; -"private"="私密"; -"online"="在线"; -"offline"="离线"; -"first_channel"="频道1"; -"second_channel"="频道2"; -"more"="更多"; -"has_no_role"="暂无身份组可添加"; -"send_to"="发送给"; -"image_is_nil"= "图片为空"; - - - -//MARK:toast -"update_channel_suscess"="保存成功"; -"delete_channel_suscess"="删除成功"; -"open_soon"="暂未开放"; - -//MARK: channel_setting -"channel_setting"="频道设置"; -"save"="保存"; -"close"="关闭"; -"authority"="权限"; -"authority_setting"="权限设置"; -"list"="名单"; -"white_list"="白名单"; -"black_list"="黑名单"; -"channel_member"="频道成员"; -"delete_channel"="删除频道"; - - -"add_group"="添加身份组"; -"add_member"="添加成员"; -"member_permission_setting"="成员权限设置"; - -"finish"="完成"; -"removeMember"="移除成员"; -"removeRole"="移除身份组"; - -//MARK:身份组权限设置 -"auth1"="ManageServer"; -"auth2"="管理频道属性"; -"auth3"="管理频道权限"; -"auth4"="发送消息"; -"auth5"="ModifySelfInfo"; -"auth6"="InviteToServer"; -"auth7"="KickOthersInServer"; -"auth8"="ModifyOthersInfoInServer"; -"auth9"="频道中撤回他人消息"; -"auth10"="频道中删除他人消息"; -"auth11"="RemindOther"; -"auth12"="RemindAll"; -"auth13"="管理频道名单"; - -//supplement -"delete"="删除"; -"share_thoughts"="分享心得"; -"noMember_add"="无成员可添加"; -"search_serverId"="搜索服务器ID"; -"no_serverId"="暂无你要的服务器ID"; -"know"="知道了"; -"upload_headImage"="上传头像"; -"enter_serverName"=" 请输入服务器名称"; -"request_sended"="请求已发送"; -"message_channel"="消息频道"; -"server_nochannel"="该服务器下暂无频道"; -"applied"="已申请"; -"join"="加入"; -"modify_nickname"="请点击编辑后修改昵称"; -"sure_exit_server"="确定退出当前服务器?"; -"sure_delete_server"="确定删除当前服务器?"; -"serverId_notbe_empty"="服务器id不能为空"; -"enter_name"="输入名称"; -"kick_currentMember"="确定踢出当前成员?"; -"sure_delete"="确定删除"; -"current_identity"="当前身份组"; -"hm"="HH:mm"; -"mdhm"="MM月dd日 HH:mm"; -"ymdhm"="yyyy年MM月dd日 HH:mm"; - -//MARK:error toast -"param_error"="Parameter error"; -"no_Permession"="暂无权限在该频道发言"; -"channelName_cannot_be_empty"="频道名称不能为空"; -"network_error"="当前网络错误"; -"cant_join"="无法加入?"; -"blocked_from_server_cant_join"="你被该服务器封禁,无法加入。"; -"serverName_limit"="服务器命名不超过50个字符"; -"add_favorite_service"="暂无服务器,\n赶紧去添加心仪的服务器吧"; -"nickName_not_empty"="昵称不能为空"; -"accid_not_empty"="accid 不能为空"; diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatBaseCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatBaseCell.swift deleted file mode 100644 index 21d370da..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatBaseCell.swift +++ /dev/null @@ -1,17 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatBaseCell: UITableViewCell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatCenterTextCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatCenterTextCell.swift deleted file mode 100644 index 7d80e99d..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatCenterTextCell.swift +++ /dev/null @@ -1,40 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatCenterTextCell: QChatCornerCell { - public var titleLabel: UILabel = .init() - public var line = UIView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - titleLabel.font = UIFont.systemFont(ofSize: 16) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - titleLabel.textColor = .ne_redText - titleLabel.textAlignment = .center - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - titleLabel.text = "title" - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(line) - NSLayoutConstraint.activate([ - line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - line.heightAnchor.constraint(equalToConstant: 1.0), - line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatImageTextCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatImageTextCell.swift deleted file mode 100644 index 914d115d..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatImageTextCell.swift +++ /dev/null @@ -1,89 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatImageTextCell: QChatStateCell { - var circleView = UIImageView() - override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - // circle view - circleView.translatesAutoresizingMaskIntoConstraints = false - circleView.layer.cornerRadius = 16 - circleView.clipsToBounds = true - circleView.backgroundColor = .ne_defautAvatarColor - contentView.addSubview(circleView) - NSLayoutConstraint.activate([ - circleView.widthAnchor.constraint(equalToConstant: 36), - circleView.heightAnchor.constraint(equalToConstant: 36), - circleView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 40), - circleView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), - ]) -// short name label - contentView.addSubview(shortNameLabel) - NSLayoutConstraint.activate([ - shortNameLabel.widthAnchor.constraint(equalTo: circleView.widthAnchor), - shortNameLabel.heightAnchor.constraint(equalTo: circleView.heightAnchor), - shortNameLabel.leftAnchor.constraint(equalTo: circleView.leftAnchor), - shortNameLabel.topAnchor.constraint(equalTo: circleView.topAnchor), - ]) -// name label - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: circleView.rightAnchor, constant: 12), - nameLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - nameLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) -// line - let line = UIView() - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(line) - NSLayoutConstraint.activate([ - line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - line.heightAnchor.constraint(equalToConstant: 1), - line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -1), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public lazy var avatarImage: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.clipsToBounds = true - avatar.backgroundColor = .ne_defautAvatarColor - return avatar - }() - - public lazy var shortNameLabel: UILabel = { - let name = UILabel() - name.translatesAutoresizingMaskIntoConstraints = false - name.textColor = .white - name.textAlignment = .center - name.font = UIFont.systemFont(ofSize: 14.0) - return name - }() - - public lazy var nameLabel: UILabel = { - let label = UILabel() - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 14.0) - label.textColor = .ne_darkText - return label - }() - - public func setup(accid: String?, nickName: String?) { - let name = nickName?.count ?? 0 > 0 ? nickName : accid - nameLabel.text = name - guard let n = name else { return } - shortNameLabel.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n - circleView.backgroundColor = UIColor.colorWithString(string: accid) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatSectionView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatSectionView.swift deleted file mode 100644 index 98e024d0..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatSectionView.swift +++ /dev/null @@ -1,33 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatSectionView: UITableViewHeaderFooterView { - public var titleLabel = UILabel() - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - contentView.backgroundColor = .ne_lightBackgroundColor - titleLabel.font = UIFont.systemFont(ofSize: 12) - titleLabel.textColor = .ne_greyText - titleLabel.translatesAutoresizingMaskIntoConstraints = false - - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 33), - titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8), - titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor), - titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -33), - ]) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatStateCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatStateCell.swift deleted file mode 100644 index 3d2bd6fa..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatStateCell.swift +++ /dev/null @@ -1,65 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -enum RightStyle { - case none - case indicate - case delete -} - -class QChatStateCell: QChatCornerCell { - private var style: RightStyle = .none - public var rightImage = UIImageView() - var rightImageMargin: NSLayoutConstraint? - public var rightStyle: RightStyle { - get { - style - } - set { - style = newValue - switch style { - case .none: - rightImage.image = nil - case .indicate: - rightImage.image = UIImage.ne_imageNamed(name: "arrowRight") - case .delete: - rightImage.image = UIImage.ne_imageNamed(name: "delete") - } - } - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - rightImage.contentMode = .center - rightImage.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(rightImage) - rightImageMargin = rightImage.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -36 - ) - rightImageMargin?.isActive = true - NSLayoutConstraint.activate([ - rightImage.widthAnchor.constraint(equalToConstant: 20), - rightImage.heightAnchor.constraint(equalToConstant: 20), - rightImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatTextArrowCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatTextArrowCell.swift deleted file mode 100644 index a4dcc855..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatTextArrowCell.swift +++ /dev/null @@ -1,17 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatTextArrowCell: QChatTextCell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - rightStyle = .indicate - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatTextCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatTextCell.swift deleted file mode 100644 index baf04109..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatTextCell.swift +++ /dev/null @@ -1,68 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatTextCell: QChatStateCell { - public var titleLabel: UILabel = .init() - public var detailLabel: UILabel = .init() - public var line = UIView() - - var titleLeftMargin: NSLayoutConstraint? - - var detailRightMargin: NSLayoutConstraint? - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - titleLabel.font = UIFont.systemFont(ofSize: 16) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - titleLabel.textColor = .ne_darkText - contentView.addSubview(titleLabel) - titleLeftMargin = titleLabel.leftAnchor.constraint( - equalTo: contentView.leftAnchor, - constant: 36 - ) - titleLeftMargin?.isActive = true - NSLayoutConstraint.activate([ - // self.titleLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 120), - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - titleLabel.text = localizable("delete") - - detailLabel.font = UIFont.systemFont(ofSize: 16) - detailLabel.translatesAutoresizingMaskIntoConstraints = false - detailLabel.textColor = .ne_lightText - contentView.addSubview(detailLabel) - - detailRightMargin = detailLabel.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -60 - ) - detailRightMargin?.isActive = true - NSLayoutConstraint.activate([ - detailLabel.leftAnchor.constraint(equalTo: titleLabel.rightAnchor, constant: 0), - detailLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 40), - detailLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - detailLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - detailLabel.textAlignment = .right - - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(line) - NSLayoutConstraint.activate([ - line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - line.heightAnchor.constraint(equalToConstant: 1.0), - line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatUnfoldCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatUnfoldCell.swift deleted file mode 100644 index 39eed2b4..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatUnfoldCell.swift +++ /dev/null @@ -1,65 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatUnfoldCell: QChatCornerCell { - lazy var arrowImage: UIImageView = { - let arrow = UIImageView() - arrow.translatesAutoresizingMaskIntoConstraints = false - arrow.image = UIImage.ne_imageNamed(name: "arrowDown") - return arrow - }() - - lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_greyText - label.font = DefaultTextFont(14) - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI() { - contentView.addSubview(contentLabel) - NSLayoutConstraint.activate([ - contentLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - contentLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - ]) - - contentView.addSubview(arrowImage) - NSLayoutConstraint.activate([ - arrowImage.leftAnchor.constraint(equalTo: contentLabel.rightAnchor, constant: 5), - arrowImage.centerYAnchor.constraint(equalTo: contentLabel.centerYAnchor), - ]) - } - - func changeToArrowUp() { - arrowImage.image = UIImage.ne_imageNamed(name: "arrowUp") - } - - func changeToArrowDown() { - arrowImage.image = UIImage.ne_imageNamed(name: "arrowDown") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatBaseViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatBaseViewController.swift deleted file mode 100644 index 5001c10a..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatBaseViewController.swift +++ /dev/null @@ -1,25 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreKit - -class QChatBaseViewController: NEBaseViewController { - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatNavigationController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatNavigationController.swift deleted file mode 100644 index 53418ac4..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatNavigationController.swift +++ /dev/null @@ -1,22 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -public class QChatNavigationController: UINavigationController { - override public func viewDidLoad() { - super.viewDidLoad() - } - - override public func pushViewController(_ viewController: UIViewController, animated: Bool) { - if children.count > 0 { - viewController.hidesBottomBarWhenPushed = true - if children.count > 1 { - viewController.hidesBottomBarWhenPushed = false - } - } - super.pushViewController(viewController, animated: true) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatTableViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatTableViewController.swift deleted file mode 100644 index 3d019589..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseViewController/QChatTableViewController.swift +++ /dev/null @@ -1,67 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreKit - -public class QChatTableViewController: NEBaseViewController, UITableViewDelegate, - UITableViewDataSource { - public var tableView: UITableView = .init(frame: .zero, style: .grouped) - public var topConstraint: NSLayoutConstraint? - public var bottomConstraint: NSLayoutConstraint? - - override public func viewDidLoad() { - super.viewDidLoad() - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - ]) - - if #available(iOS 11.0, *) { - self.topConstraint = self.tableView.topAnchor.constraint( - equalTo: self.view.safeAreaLayoutGuide.topAnchor, - constant: 0 - ) - self.bottomConstraint = self.tableView.bottomAnchor - .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) - - } else { - // Fallback on earlier versions - topConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor) - bottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - } - topConstraint?.isActive = true - bottomConstraint?.isActive = true - - tableView.sectionHeaderHeight = 38 - tableView.sectionFooterHeight = 0 - tableView.rowHeight = 62 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath) - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - 0 - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/Model/QChatRoles.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/Model/QChatRoles.swift deleted file mode 100644 index e248e2d1..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/Model/QChatRoles.swift +++ /dev/null @@ -1,28 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -public enum RoundedType { - case none - case top - case bottom - case all -} - -public struct RoleModel { - public var role: ChannelRole? - public var member: MemberRole? - public var title: String? - public var corner: RoundedType? - public var isPlacehold: Bool = false -} - -public struct QChatRoles { - public var roles: [RoleModel] = .init() - public var timeTag: TimeInterval? - public var pageSize: Int = 5 -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/Model/RoleStatusInfoExt.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/Model/RoleStatusInfoExt.swift deleted file mode 100644 index 024e7bc6..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/Model/RoleStatusInfoExt.swift +++ /dev/null @@ -1,16 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -public struct RoleStatusInfoExt { - public var status: RoleStatusInfo? - public var title: String? - - public init(status: RoleStatusInfo?) { - self.status = status - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/ChannelHeaderView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/ChannelHeaderView.swift deleted file mode 100644 index a9a39a57..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/ChannelHeaderView.swift +++ /dev/null @@ -1,66 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class ChannelHeaderView: UIView { - var titleLabel = UILabel() - var detailLabel = UILabel() - var settingButton = UIButton() - private var prefixLabel = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - prefixLabel.font = .systemFont(ofSize: 16) - prefixLabel.textColor = .ne_lightText - prefixLabel.text = "#" - prefixLabel.translatesAutoresizingMaskIntoConstraints = false - addSubview(prefixLabel) - NSLayoutConstraint.activate([ - prefixLabel.topAnchor.constraint(equalTo: topAnchor, constant: 20), - prefixLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 20), - prefixLabel.widthAnchor.constraint(equalToConstant: 20), - prefixLabel.heightAnchor.constraint(equalToConstant: 26), - ]) - - titleLabel.font = .systemFont(ofSize: 18) - titleLabel.textColor = .ne_darkText - titleLabel.text = localizable("first_channel") - titleLabel.translatesAutoresizingMaskIntoConstraints = false - addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 20), - titleLabel.leftAnchor.constraint(equalTo: prefixLabel.rightAnchor, constant: 0), - titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -81), - titleLabel.heightAnchor.constraint(equalToConstant: 26), - ]) - - detailLabel.textColor = .ne_greyText - detailLabel.font = .systemFont(ofSize: 14) - detailLabel.text = localizable("share_thoughts") - detailLabel.translatesAutoresizingMaskIntoConstraints = false - addSubview(detailLabel) - NSLayoutConstraint.activate([ - detailLabel.leftAnchor.constraint(equalTo: prefixLabel.leftAnchor), - detailLabel.topAnchor.constraint(equalTo: prefixLabel.bottomAnchor, constant: 0), - detailLabel.heightAnchor.constraint(equalToConstant: 20), - detailLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), - ]) - - settingButton.setImage(UIImage.ne_imageNamed(name: "Setting"), for: .normal) - settingButton.translatesAutoresizingMaskIntoConstraints = false - addSubview(settingButton) - NSLayoutConstraint.activate([ - settingButton.topAnchor.constraint(equalTo: topAnchor, constant: 10), - settingButton.rightAnchor.constraint(equalTo: rightAnchor, constant: -16), - settingButton.widthAnchor.constraint(equalToConstant: 40), - settingButton.heightAnchor.constraint(equalToConstant: 32), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/CornerButton.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/CornerButton.swift deleted file mode 100644 index 7dc01feb..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/CornerButton.swift +++ /dev/null @@ -1,123 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class CornerButton: UIButton { - var cornerLayer = CAShapeLayer() - override var isSelected: Bool { - get { - super.isSelected - } - set { - cornerLayer.fillColor = newValue ? selectedColor.cgColor : color.cgColor - super.isSelected = newValue - } - } - - override var isUserInteractionEnabled: Bool { - get { - super.isUserInteractionEnabled - } - set { - super.isUserInteractionEnabled = newValue - alpha = newValue ? 1.0 : 0.5 - } - } - -// public var ne_selected: Bool { -// get { -// return self.isSelected -// } -// set { -// if newValue { - //// cornerLayer.fillColor = UIColor.purple.cgColor -// }else { - //// cornerLayer.fillColor = color.cgColor -// } -// self.isSelected = newValue -// } -// } - -// public var fillColor: UIColor = .white - public var color: UIColor = .white - public var selectedColor: UIColor = .white - private var type: CornerType = .none - public var edgeInset: UIEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: 0) - public var cornerType: CornerType { - get { type } - set { - if type != newValue { - type = newValue - sizeToFit() - } - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - translatesAutoresizingMaskIntoConstraints = false - clipsToBounds = true - cornerLayer.fillColor = color.cgColor - cornerLayer.strokeColor = UIColor.ne_borderColor.cgColor -// self.backgroundColor = .ne_lightBackgroundColor - layer.insertSublayer(cornerLayer, below: imageView?.layer) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override func layoutSublayers(of layer: CALayer) { - super.layoutSublayers(of: layer) - drawRoundedCorner(rect: bounds) - - print(#function) - } - -// public override func draw(_ rect: CGRect) { -// drawRoundedCorner(rect: rect) -// } - - public func drawRoundedCorner(rect: CGRect) { - var path = UIBezierPath() - let roundRect = CGRect( - x: rect.origin.x + edgeInset.left, - y: rect.origin.y + edgeInset.top, - width: rect.width - (edgeInset.left + edgeInset.right), - height: rect.height - (edgeInset.top + edgeInset.bottom) - ) - if type == .none { - path = UIBezierPath(rect: roundRect) - } - var corners = UIRectCorner() - if type.contains(CornerType.topLeft) { - corners = corners.union(.topLeft) - } - if type.contains(CornerType.topRight) { - corners = corners.union(.topRight) - } - if type.contains(CornerType.bottomLeft) { - corners = corners.union(.bottomLeft) - } - if type.contains(CornerType.bottomRight) { - corners = corners.union(.bottomRight) - } - - path = UIBezierPath( - roundedRect: roundRect, - byRoundingCorners: corners, - cornerRadii: CGSize(width: 10, height: 10) - ) - cornerLayer.path = path.cgPath -// cornerLayer.fillColor = self.isSelected ? selectedColor.cgColor : color.cgColor -// cornerLayer.strokeColor = UIColor.ne_borderColor.cgColor - } - -// @objc -// private func didSelect(sender: AnyObject) { -// self.isSelected = !self.isSelected -// } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatImageTextOnlineCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatImageTextOnlineCell.swift deleted file mode 100644 index 2b53f906..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatImageTextOnlineCell.swift +++ /dev/null @@ -1,41 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatImageTextOnlineCell: QChatImageTextCell { - var online: Bool { - get { - onlineView.isHidden - } - set { - onlineView.isHidden = !newValue - alpha = newValue ? 1.0 : 0.5 - } - } - - private var onlineView = UIView() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - onlineView.backgroundColor = .ne_greenColor - onlineView.layer.borderColor = UIColor.white.cgColor - onlineView.layer.borderWidth = 2 - onlineView.clipsToBounds = true - onlineView.layer.cornerRadius = 6 - onlineView.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(onlineView) - NSLayoutConstraint.activate([ - onlineView.centerXAnchor.constraint(equalTo: circleView.centerXAnchor, constant: 16), - onlineView.centerYAnchor.constraint(equalTo: circleView.centerYAnchor, constant: 16), - onlineView.widthAnchor.constraint(equalToConstant: 12), - onlineView.heightAnchor.constraint(equalToConstant: 12), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatMemberInfoView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatMemberInfoView.swift deleted file mode 100644 index ed985d70..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatMemberInfoView.swift +++ /dev/null @@ -1,319 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -protocol QChatMemberInfoViewDelegate: AnyObject { - func didClickUserHeader(_ accid: String?) -} - -class QChatMemberInfoView: UIView { - var contentView: UIView = .init() - public var avatar = UIImageView() - public var shortName = UILabel() - public var name = UILabel() - public var groupView = UIView() - -// private var onlineView = UIView() - private var originY: CGFloat = 0 - private var originMaxY: CGFloat = 0 - private var topConstaint: NSLayoutConstraint = .init() -// var online:Bool { -// get { -// return onlineView.backgroundColor == .ne_greenColor -// } -// set { -// onlineView.backgroundColor = newValue ? .ne_greenColor : .ne_greyText -// } -// } - - public var labelsWidth: CGFloat = 0 - public var maxWidth: CGFloat = kScreenWidth - 2 * kScreenInterval - public var labelMargin: CGFloat = 6 - public var labelHeight: CGFloat = 25 - public var isFirstRow = true - public weak var delegate: QChatMemberInfoViewDelegate? - - public var accid: String? - - init(inView: UIView) { - super.init(frame: inView.bounds) - translatesAutoresizingMaskIntoConstraints = false - backgroundColor = UIColor(white: 0, alpha: 0.4) - inView.addSubview(self) - NSLayoutConstraint.activate([ - topAnchor.constraint(equalTo: inView.topAnchor), - leftAnchor.constraint(equalTo: inView.leftAnchor), - rightAnchor.constraint(equalTo: inView.rightAnchor), - bottomAnchor.constraint(equalTo: inView.bottomAnchor), - ]) - commonUI() - addPanGesture() - originMaxY = inView.frame.size.height - 360 - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - addSubview(contentView) - contentView.translatesAutoresizingMaskIntoConstraints = false - topConstaint = contentView.topAnchor.constraint(equalTo: bottomAnchor, constant: 0) -// topConstaint = contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 360) - NSLayoutConstraint.activate([ - topConstaint, - contentView.leftAnchor.constraint(equalTo: leftAnchor), - contentView.rightAnchor.constraint(equalTo: rightAnchor), - contentView.heightAnchor.constraint(equalToConstant: 360), - ]) - - let indicatorView = UIView() - indicatorView.translatesAutoresizingMaskIntoConstraints = false - indicatorView.backgroundColor = .white - indicatorView.layer.cornerRadius = 4 - contentView.addSubview(indicatorView) - NSLayoutConstraint.activate([ - indicatorView.topAnchor.constraint(equalTo: contentView.topAnchor), - indicatorView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - indicatorView.widthAnchor.constraint(equalToConstant: 41), - indicatorView.heightAnchor.constraint(equalToConstant: 4), - ]) - - let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "bgImage")) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.layer.cornerRadius = 10 - imageView.clipsToBounds = true - contentView.addSubview(imageView) - NSLayoutConstraint.activate([ - imageView.topAnchor.constraint(equalTo: indicatorView.bottomAnchor, constant: 5), - imageView.leftAnchor.constraint(equalTo: contentView.leftAnchor), - imageView.rightAnchor.constraint(equalTo: contentView.rightAnchor), - imageView.heightAnchor.constraint(equalToConstant: 70), - ]) - let whiteBgView = UIView() - whiteBgView.backgroundColor = .white - whiteBgView.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(whiteBgView) - NSLayoutConstraint.activate([ - whiteBgView.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: -5), - whiteBgView.leftAnchor.constraint(equalTo: contentView.leftAnchor), - whiteBgView.rightAnchor.constraint(equalTo: contentView.rightAnchor), - whiteBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.backgroundColor = .ne_defautAvatarColor - avatar.layer.borderWidth = 2 - avatar.layer.borderColor = UIColor.white.cgColor - avatar.layer.cornerRadius = 30 - avatar.clipsToBounds = true - contentView.addSubview(avatar) - NSLayoutConstraint.activate([ - avatar.topAnchor.constraint(equalTo: indicatorView.bottomAnchor, constant: 50), - avatar.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - avatar.heightAnchor.constraint(equalToConstant: 60), - avatar.widthAnchor.constraint(equalToConstant: 60), - ]) - avatar.isUserInteractionEnabled = true - let tap = UITapGestureRecognizer() - tap.numberOfTapsRequired = 1 - tap.numberOfTouchesRequired = 1 - avatar.addGestureRecognizer(tap) - tap.addTarget(self, action: #selector(headerClick)) - -// onlineView.translatesAutoresizingMaskIntoConstraints = false -// onlineView.backgroundColor = .ne_greenColor -// onlineView.layer.borderWidth = 2 -// onlineView.layer.borderColor = UIColor.white.cgColor -// onlineView.layer.cornerRadius = 7 -// onlineView.clipsToBounds = true -// contentView.addSubview(onlineView) -// NSLayoutConstraint.activate([ -// onlineView.centerXAnchor.constraint(equalTo: avatar.centerXAnchor, constant: 23), -// onlineView.centerYAnchor.constraint(equalTo: avatar.centerYAnchor, constant: 23), -// onlineView.heightAnchor.constraint(equalToConstant: 14), -// onlineView.widthAnchor.constraint(equalToConstant: 14) -// ]) - - shortName.translatesAutoresizingMaskIntoConstraints = false - shortName.font = .systemFont(ofSize: 22) - shortName.textColor = .white - shortName.textAlignment = .center - contentView.addSubview(shortName) - NSLayoutConstraint.activate([ - shortName.topAnchor.constraint(equalTo: avatar.topAnchor), - shortName.leftAnchor.constraint(equalTo: avatar.leftAnchor), - shortName.rightAnchor.constraint(equalTo: avatar.rightAnchor), - shortName.bottomAnchor.constraint(equalTo: avatar.bottomAnchor), - ]) - - name.translatesAutoresizingMaskIntoConstraints = false - name.font = .boldSystemFont(ofSize: 24) - name.textColor = .ne_darkText - contentView.addSubview(name) - NSLayoutConstraint.activate([ - name.topAnchor.constraint(equalTo: avatar.bottomAnchor, constant: 14), - name.leftAnchor.constraint(equalTo: avatar.leftAnchor), - name.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - name.heightAnchor.constraint(equalToConstant: 30), - ]) - - let groupName = UILabel() - groupName.translatesAutoresizingMaskIntoConstraints = false - groupName.font = .systemFont(ofSize: 14) - groupName.text = localizable("qchat_id_group") - groupName.textColor = .ne_darkText - contentView.addSubview(groupName) - NSLayoutConstraint.activate([ - groupName.topAnchor.constraint(equalTo: name.bottomAnchor, constant: 30), - groupName.leftAnchor.constraint(equalTo: name.leftAnchor), - groupName.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - groupName.heightAnchor.constraint(equalToConstant: 20), - ]) - - let line = UIView() - line.translatesAutoresizingMaskIntoConstraints = false - line.backgroundColor = .ne_greyLine - contentView.addSubview(line) - NSLayoutConstraint.activate([ - line.topAnchor.constraint(equalTo: groupName.bottomAnchor, constant: 8), - line.leftAnchor.constraint(equalTo: name.leftAnchor), - line.rightAnchor.constraint(equalTo: name.rightAnchor), - line.heightAnchor.constraint(equalToConstant: 1), - ]) - - groupView.translatesAutoresizingMaskIntoConstraints = false - groupView.backgroundColor = .white - contentView.addSubview(groupView) - NSLayoutConstraint.activate([ - groupView.topAnchor.constraint(equalTo: line.bottomAnchor, constant: 2), - groupView.leftAnchor.constraint(equalTo: name.leftAnchor), - groupView.rightAnchor.constraint(equalTo: name.rightAnchor), - groupView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - } - - public func setupRoles(dataArray: [String]) { - for i in 0 ..< dataArray.count { - let label = IDGroupLabel(content: dataArray[i]) - label.textInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8) - label.translatesAutoresizingMaskIntoConstraints = false - groupView.addSubview(label) - let labelSize = label.sizeThatFits(CGSize(width: maxWidth, height: labelHeight)) - - // 剩余宽度是否满足,下一个label的宽度,如不满足则换行 - if (maxWidth - labelsWidth) >= labelSize.width, isFirstRow { - NSLayoutConstraint.activate([ - i == 0 ? label.leftAnchor.constraint( - equalTo: groupView.leftAnchor, - constant: kScreenInterval - ) : label.leftAnchor.constraint( - equalTo: groupView.leftAnchor, - constant: kScreenInterval + labelsWidth - ), - label.topAnchor.constraint(equalTo: groupView.topAnchor, constant: 8), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant: labelSize.height), - ]) - } else { - // 换行重置,labels总宽度 - if isFirstRow { - labelsWidth = kScreenInterval - } - isFirstRow = false - NSLayoutConstraint.activate([ - label.leftAnchor.constraint( - equalTo: groupView.leftAnchor, - constant: labelsWidth - ), - label.topAnchor.constraint( - equalTo: groupView.topAnchor, - constant: 8 + labelHeight + labelMargin - ), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant: labelSize.height), - ]) - } - -// if i == dataArray.count - 1 { -// NSLayoutConstraint.activate([ -// label.bottomAnchor.constraint(equalTo: groupView.bottomAnchor) -// ]) -// } - labelsWidth += (labelSize.width + labelMargin) - } - } - - func addPanGesture() { - addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan))) - addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap))) - } - - @objc func tap(pan: UIPanGestureRecognizer) { - dismiss() - } - - @objc func pan(pan: UIPanGestureRecognizer) { - let position = pan.translation(in: superview) - let velocity = pan.velocity(in: superview) - print("velocity:\(velocity) position:\(position)") - switch pan.state { - case .began: - print("start pan") - originY = contentView.frame.origin.y - - case .changed: - if (originY + position.y) > originMaxY { - contentView.frame.origin.y = originY + position.y - } - - case .ended: - print("ended pan") - if velocity.y > 600 || contentView.frame.origin.y > originMaxY + 160 { - dismiss() - } - - default: - print("default pan") - } - } - - func present() { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - self.topConstaint.constant = -360 - UIView.animate(withDuration: 0.3) { - self.layoutIfNeeded() - } completion: { result in - } - } - } - - func dismiss() { - if superview == nil { - return - } - topConstaint.constant = 0 - UIView.animate(withDuration: 0.3) { - self.layoutIfNeeded() - } completion: { result in - self.removeFromSuperview() - } - } - - public func setup(accid: String?, nickName: String?) { - let name = nickName?.count ?? 0 > 0 ? nickName : accid - self.name.text = name - self.accid = accid - guard let n = name else { return } - shortName.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n - avatar.backgroundColor = UIColor.colorWithString(string: accid) - } - - @objc func headerClick() { - delegate?.didClickUserHeader(accid) - removeFromSuperview() - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatPermissionSettingCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatPermissionSettingCell.swift deleted file mode 100644 index b5951b47..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatPermissionSettingCell.swift +++ /dev/null @@ -1,148 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -protocol QChatPermissionSettingCellDelegate: AnyObject { - func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) -} - -class QChatPermissionSettingCell: QChatCornerCell { - public weak var delegate: QChatPermissionSettingCellDelegate? - private var model: RoleStatusInfoExt? - private var button: UIButton? - private var titleLabel = UILabel() - private var enable: Bool { - get { - (buttons.first?.isUserInteractionEnabled) != nil - } - set { - for button in buttons { - button.isUserInteractionEnabled = newValue - } - } - } - - private var index: Int { - get { - selectedIndex - } - set { - selectedIndex = newValue - button = buttons[selectedIndex] - button?.isSelected = true - } - } - - private var selectedIndex = -1 - private var buttons = [CornerButton]() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - titleLabel.font = UIFont.systemFont(ofSize: 16) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - titleLabel.textColor = .ne_darkText - titleLabel.text = localizable("delete") - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35), - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - - let denyButton = CornerButton(frame: .zero) - denyButton.color = .white - denyButton.selectedColor = UIColor.red - denyButton.tag = 0 + 10 - denyButton.setImage(UIImage.ne_imageNamed(name: "deny"), for: .normal) - denyButton.setImage(UIImage.ne_imageNamed(name: "denySelected"), for: .selected) - denyButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - denyButton.cornerType = CornerType.topLeft.union(CornerType.bottomLeft) - buttons.append(denyButton) - - let midButton = CornerButton(frame: .zero) - midButton.tag = 1 + 10 - midButton.color = .white - midButton.selectedColor = UIColor.ne_borderColor - midButton.setImage(UIImage.ne_imageNamed(name: "extend"), for: .normal) - midButton.setImage(UIImage.ne_imageNamed(name: "extendSelected"), for: .selected) - midButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - buttons.append(midButton) - - let allowButton = CornerButton(frame: .zero) - allowButton.tag = 2 + 10 - allowButton.color = .white - allowButton.selectedColor = UIColor.ne_greenColor - allowButton.setImage(UIImage.ne_imageNamed(name: "allow"), for: .normal) - allowButton.setImage(UIImage.ne_imageNamed(name: "allowSeleted"), for: .selected) - allowButton.cornerType = CornerType.topRight.union(CornerType.bottomRight) - allowButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - buttons.append(allowButton) - - contentView.addSubview(allowButton) - NSLayoutConstraint.activate([ - allowButton.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), - allowButton.widthAnchor.constraint(equalToConstant: 32), - allowButton.heightAnchor.constraint(equalToConstant: 26), - allowButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - - contentView.addSubview(midButton) - NSLayoutConstraint.activate([ - midButton.rightAnchor.constraint(equalTo: allowButton.leftAnchor, constant: 0), - midButton.widthAnchor.constraint(equalToConstant: 32), - midButton.heightAnchor.constraint(equalToConstant: 26), - midButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - - contentView.addSubview(denyButton) - NSLayoutConstraint.activate([ - denyButton.rightAnchor.constraint(equalTo: midButton.leftAnchor, constant: 0), - denyButton.widthAnchor.constraint(equalToConstant: 32), - denyButton.heightAnchor.constraint(equalToConstant: 26), - denyButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - denyButton.leftAnchor.constraint(equalTo: titleLabel.rightAnchor), - ]) - } - - public func updateModel(model: RoleStatusInfoExt?) { - self.model = model - titleLabel.text = model?.title - index = (model?.status?.status.rawValue ?? 0) + 1 - } - - @objc func buttonEvent(sender: CornerButton) { - if sender.tag - 10 == selectedIndex { - return - } - selectedIndex = sender.tag - 10 - if let type = model?.status?.type { - let update = RoleStatusInfo( - type: type, - status: status(rawValue: selectedIndex - 1) ?? .Extend - ) - delegate?.didSelected(cell: self, model: update) - } - } - - public func selectedSuccess(success: Bool) { - if success { - if let button = button { - button.isSelected = !button.isSelected - } - if selectedIndex >= 0, selectedIndex < buttons.count { - let new = buttons[selectedIndex] - new.isSelected = !new.isSelected - button = new - } - model?.status?.status = status(rawValue: selectedIndex - 1) ?? .Extend - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatTextEditCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatTextEditCell.swift deleted file mode 100644 index 341ae5a0..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatTextEditCell.swift +++ /dev/null @@ -1,86 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -@objc protocol QChatTextEditCellDelegate: AnyObject { -// @objc optional func textFieldDidChangeSelection(cell: QChatTextEditCell, -// _ textField: UITextField) - @objc optional func textDidChange(_ textField: UITextField) -} - -class QChatTextEditCell: QChatCornerCell, UITextFieldDelegate { - var limit: Int? - var canEdit = true - var editTotast = "" - public var textFied = UITextField() - public weak var delegate: QChatTextEditCellDelegate? - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - textFied.textColor = .ne_darkText - textFied.font = UIFont.systemFont(ofSize: 16) - textFied.clearButtonMode = .whileEditing - textFied.translatesAutoresizingMaskIntoConstraints = false - NotificationCenter.default.addObserver( - self, - selector: #selector(textFieldDidChangeValue(_:)), - name: UITextField.textDidChangeNotification, - object: textFied - ) - contentView.addSubview(textFied) - NSLayoutConstraint.activate([ - textFied.leftAnchor.constraint(equalTo: leftAnchor, constant: 36), - textFied.topAnchor.constraint(equalTo: topAnchor), - textFied.bottomAnchor.constraint(equalTo: bottomAnchor), - textFied.rightAnchor.constraint(equalTo: rightAnchor, constant: -36), - ]) - textFied.delegate = self - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MAKR: UITextFieldDelegate - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - if let l = limit { - let text = "\(textField.text ?? "")\(string)" - if text.count > l { - return false - } - } - return true - } - - func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { - print("1 textFieldShouldEndEditing") - return true - } - - func textFieldDidEndEditing(_ textField: UITextField) { - print("2 textFieldDidEndEditing") - } - - func textFieldDidChangeSelection(_ textField: UITextField) { - print("3 textFieldDidChangeSelection:\(textField.text)") -// if let d = delegate { -// d.textFieldDidChangeSelection?(cell: self, textField) -// } - } - - func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - if canEdit == false, editTotast.count > 0 { - UIApplication.shared.keyWindow?.makeToast(editTotast) - } - return canEdit - } - - @objc func textFieldDidChangeValue(_ noti: Notification) { - if let d = delegate, let text = noti.object as? UITextField { - d.textDidChange?(text) - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatTextSelectionCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatTextSelectionCell.swift deleted file mode 100644 index 5b1ab2cc..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/View/QChatTextSelectionCell.swift +++ /dev/null @@ -1,43 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatTextSelectionCell: QChatTextCell { - var selectedImageView = UIImageView(image: UIImage.ne_imageNamed(name: "selection")) - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectedImageView.contentMode = .center - selectedImageView.translatesAutoresizingMaskIntoConstraints = false - selectedImageView.image = UIImage.ne_imageNamed(name: "Selection") - contentView.addSubview(selectedImageView) - NSLayoutConstraint.activate([ - selectedImageView.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -36 - ), - selectedImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0), - selectedImageView.bottomAnchor.constraint( - equalTo: contentView.bottomAnchor, - constant: 0 - ), - selectedImageView.widthAnchor.constraint(equalToConstant: 15), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func selected(selected: Bool) { - selectedImageView.isHidden = !selected - } - -// override func setSelected(_ selected: Bool, animated: Bool) { -// super.setSelected(selected, animated: animated) -// selectedImageView.isHidden = !selected -// } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatAddMemberVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatAddMemberVC.swift deleted file mode 100644 index 7bacebba..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatAddMemberVC.swift +++ /dev/null @@ -1,233 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import CoreAudio -import MJRefresh - -typealias AddMemberRoleBlock = (_ memberRole: MemberRole?) -> Void -public class QChatAddMemberVC: QChatSearchVC { - public var channel: ChatChannel? - private var serverMembers: [ServerMemeber]? - private var channelMembers: [ServerMemeber]? - private var lastTimeTag: Double? -// public var didAddMemberRole: AddMemberRoleBlock? - - public init(channel: ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override public func viewDidLoad() { - super.viewDidLoad() - title = localizable("add_member") - tableView.register( - QChatImageTextCell.self, - forCellReuseIdentifier: "\(QChatImageTextCell.self)" - ) - tableView.rowHeight = 60 - tableView.mj_header = MJRefreshNormalHeader( - refreshingTarget: self, - refreshingAction: #selector(loadData) - ) - tableView.mj_footer = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMore) - ) - loadData() - } - - @objc func loadData() { - lastTimeTag = 0 - var param = GetServerMembersByPageParam() - param.serverId = channel?.serverId - param.limit = 50 - param.timeTag = lastTimeTag - QChatServerProvider.shared.getServerMembers(param) { [weak self] error, sMembers in - print("sMembers:\(sMembers) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - self?.emptyView.isHidden = false - - } else { - if !sMembers.isEmpty { - self?.lastTimeTag = sMembers.last?.createTime -// var filteredMemberArray = sMembers - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的成员 - var ids = [String]() - for member in sMembers { - if let id = member.accid { - ids.append(id) - } - } - let param = GetExistingAccidsOfMemberRolesParam( - serverId: sid, - channelId: cid, - accids: ids - ) - QChatRoleProvider.shared - .getExistingMemberRoles(param: param) { error, existMemberArray in - var filterMembers = [ServerMemeber]() - if let existMembers = existMemberArray, !existMembers.isEmpty { - for m in sMembers { - if existMembers.contains(where: { existMember in - m.accid == existMember.accid - }) { - } else { - filterMembers.append(m) - } - } - self?.serverMembers = filterMembers - self?.emptyView.isHidden = !filterMembers.isEmpty - - } else { - self?.serverMembers = sMembers - self?.emptyView.isHidden = !sMembers.isEmpty - } - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() - } - } else { - self?.emptyView.isHidden = !sMembers.isEmpty - self?.serverMembers = sMembers - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() - } - } else { - // 空白页 - self?.emptyView.isHidden = false - } - } - } - } - - @objc func loadMore() { - var param = GetServerMembersByPageParam() - param.serverId = channel?.serverId - param.limit = 50 - param.timeTag = lastTimeTag - QChatServerProvider.shared.getServerMembers(param) { [weak self] error, sMembers in - print("sMembers:\(sMembers) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - if !sMembers.isEmpty { - self?.lastTimeTag = sMembers.last?.createTime - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的成员 - var ids = [String]() - for member in sMembers { - if let id = member.accid { - ids.append(id) - } - } - let param = GetExistingAccidsOfMemberRolesParam( - serverId: sid, - channelId: cid, - accids: ids - ) - QChatRoleProvider.shared - .getExistingMemberRoles(param: param) { error, existMemberArray in - if let existMembers = existMemberArray, !existMembers.isEmpty { - for m in sMembers { - if existMembers.contains(where: { existMember in - m.accid == existMember.accid - }) { - } else { - self?.serverMembers?.append(m) - } - } - } - self?.emptyView.removeFromSuperview() - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() - } - } else { - for m in sMembers { - self?.serverMembers?.append(m) - } - self?.emptyView.isHidden = true - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() - } - } else { - self?.emptyView.isHidden = true - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() - } - } - } - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - serverMembers?.count ?? 0 - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatImageTextCell.self)", - for: indexPath - ) as! QChatImageTextCell - cell.backgroundColor = .white - cell.rightStyle = .indicate - let member = serverMembers?[indexPath.row] - cell.setup(accid: member?.accid, nickName: member?.nick) - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - // 成员权限设置 - let member = serverMembers?[indexPath.row] - addMemberInChannel(member: member, index: indexPath.row) - } - - private func addMemberInChannel(member: ServerMemeber?, index: Int) { - let param = AddMemberRoleParam( - serverId: channel?.serverId, - channelId: channel?.channelId, - accid: member?.accid - ) - QChatRoleProvider.shared.addMemberRole(param) { error, memberRole in - if error != nil { - self.showToast(error?.localizedDescription ?? "") - } else { - self.serverMembers?.remove(at: index) - self.tableView.reloadData() - let settingVC = QChatMemberPermissionSettingVC( - channel: self.channel, - memberRole: memberRole - ) - self.navigationController?.pushViewController(settingVC, animated: true) -// if let block = self.didAddMemberRole { -// block(memberRole) -// } - } - } - } - - private lazy var emptyView: EmptyDataView = { - let view = EmptyDataView( - imageName: "memberPlaceholder", - content: localizable("noMember_add"), - frame: CGRect( - x: 0, - y: 60, - width: self.view.bounds.size.width, - height: self.view.bounds.size.height - ) - ) - self.view.addSubview(view) - return view - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift deleted file mode 100644 index c0070a1b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift +++ /dev/null @@ -1,234 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import MJRefresh - -typealias AddChannelRoleBlock = (_ role: ChannelRole?) -> Void -public class QChatAddRoleGroupVC: QChatSearchVC { - public var channel: ChatChannel? - private var serverRoles: [ServerRole]? - private var channelRoles: [ChannelRole]? -// public var didAddChannelRole: AddChannelRoleBlock? - private var priority: Int? - private lazy var placeholderView: EmptyDataView = .init( - imageName: "rolePlaceholder", - content: localizable("has_no_role"), - frame: CGRect( - x: 0, - y: 60, - width: self.view.bounds.size.width, - height: self.view.bounds.size.height - ) - ) - - override public func viewDidLoad() { - super.viewDidLoad() - title = localizable("add_group") - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - tableView.mj_header = MJRefreshNormalHeader( - refreshingTarget: self, - refreshingAction: #selector(loadData) - ) - tableView.mj_footer = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMore) - ) - view.addSubview(placeholderView) - loadData() - } - - init(channel: ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc func loadData() { - priority = 0 - // 加载server的身份组 - var param = GetServerRoleParam() - param.serverId = channel?.serverId - param.limit = 50 - param.priority = priority - print("thread:\(Thread.current)") - QChatRoleProvider.shared.getRoles(param) { [weak self] error, roles, sets in - print("sRoles:\(roles) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - // 空白页 - self?.placeholderView.isHidden = false - } else { - if let roleArray = roles, !roleArray.isEmpty { - self?.priority = roleArray.last?.priority - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的身份组 - var ids = [UInt64]() - for role in roleArray { - if let id = role.roleId { - ids.append(id) - } - } - let param = GetExistingChannelRolesByServerRoleIdsParam( - serverId: sid, - channelId: cid, - roleIds: ids - ) - QChatRoleProvider.shared - .getExistingChannelRoles(param: param) { error, channelRoles in - if let existRoles = channelRoles, !existRoles.isEmpty { - var tmp = [ServerRole]() - print("roleArray: \(roleArray)") - for role in roleArray { - if existRoles.contains(where: { existRole in - role.roleId == existRole.parentRoleId - }) { - } else { - tmp.append(role) - } - } - self?.serverRoles = tmp - self?.placeholderView.isHidden = !tmp.isEmpty - - } else { - self?.serverRoles = roleArray - self?.placeholderView.isHidden = !roleArray.isEmpty - } - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() - } - } else { - self?.serverRoles = roleArray - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() - } - } else { - // 空白页 - self?.placeholderView.isHidden = false - } - } - } - } - - @objc func loadMore() { - // 加载server的身份组 - var param = GetServerRoleParam() - param.serverId = channel?.serverId - param.limit = 50 - param.priority = priority - QChatRoleProvider.shared.getRoles(param) { [weak self] error, roles, sets in - print("sRoles:\(roles) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - if let roleArray = roles, !roleArray.isEmpty { - self?.priority = roleArray.last?.priority - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的身份组 - var ids = [UInt64]() - for role in roleArray { - if let id = role.roleId { - ids.append(id) - } - } - let param = GetExistingChannelRolesByServerRoleIdsParam( - serverId: sid, - channelId: cid, - roleIds: ids - ) - QChatRoleProvider.shared - .getExistingChannelRoles(param: param) { error, channelRoles in - if let existRoles = channelRoles, !existRoles.isEmpty { - for role in roleArray { - if existRoles.contains(where: { existRole in - role.roleId == existRole.parentRoleId - }) { - } else { - self?.serverRoles?.append(role) - } - } - } else { - for role in roleArray { - self?.serverRoles?.append(role) - } - } - - self?.placeholderView.isHidden = true - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() - } - } else { - for role in roleArray { - self?.serverRoles?.append(role) - } - self?.placeholderView.isHidden = true - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() - } - - } else { - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() - } - } - } - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - serverRoles?.count ?? 0 - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - cell.backgroundColor = .white - cell.titleLabel.text = serverRoles?[indexPath.row].name - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let role = serverRoles?[indexPath.row] - guard let sId = channel?.serverId, let cId = channel?.channelId, - let roleId = role?.roleId else { - return - } - // 1.添加到频道下 - let param = AddChannelRoleParam(serverId: sId, channelId: cId, parentRoleId: roleId) - QChatRoleProvider.shared.addChannelRole(param: param) { [weak self] error, cRole in - if error == nil { - // 2.跳转到身份组权限设置 - self?.navigationController?.pushViewController( - QChatGroupPermissionSettingVC(cRole: cRole), - animated: true - ) - // 3.此页面移除该数据并刷新 - self?.serverRoles?.remove(at: indexPath.row) - if self?.serverRoles?.count ?? 0 > 0 { - self?.placeholderView.isHidden = true - self?.tableView.reloadData() - } else { - self?.placeholderView.isHidden = false - } -// if let block = self?.didAddChannelRole { -// block(cRole) -// } - } else { - self?.view.makeToast(error?.localizedDescription) - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift deleted file mode 100644 index 3b4893d6..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift +++ /dev/null @@ -1,377 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -public class QChatChannelAuthoritySettingVC: QChatTableViewController { - var channel: ChatChannel? - var viewModel: QChatAuthoritySettingViewModel? - var sectionTitle: [String] = ["", localizable("qchat_id_group"), localizable("qchat_member")] - var staticData: [String] = [localizable("add_group"), localizable("add_member")] - var memberData: [String] = [localizable("add_member"), localizable("add_group")] - var isEdit = false - private let className = "QChatChannelAuthoritySettingVC" - - init(channel: ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - viewModel = QChatAuthoritySettingViewModel(channel: self.channel) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func viewWillAppear(_ animated: Bool) { - print("viewWillAppear") - loadData() - } - - override public func viewDidLoad() { - super.viewDidLoad() - commonUI() - } - - func commonUI() { - title = localizable("authority_setting") - navigationItem.rightBarButtonItem = UIBarButtonItem( - title: localizable("qchat_edit"), - style: .plain, - target: self, - action: #selector(edit) - ) - tableView.rowHeight = 50 - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - tableView.register( - QChatImageTextCell.self, - forCellReuseIdentifier: "\(QChatImageTextCell.self)" - ) - tableView.register( - QChatCenterTextCell.self, - forCellReuseIdentifier: "\(QChatCenterTextCell.self)" - ) - tableView.register( - QChatSectionView.self, - forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" - ) - } - - func loadData() { - // 获取频道下的身份组 - viewModel?.firstGetChannelRoles { [weak self] error, roles in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelAuthoritySettingVC"), - desc: "CALLBACK firstGetChannelRoles " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - } - } - - // 获取频道下的成员 - viewModel?.firstGetMembers { [weak self] error, members in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelAuthoritySettingVC"), - desc: "CALLBACK firstGetMembers " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - } - } - } - - // MARK: - event - - @objc func edit() { - isEdit = !isEdit - let title = isEdit ? localizable("finish") : localizable("qchat_edit") - navigationItem.rightBarButtonItem = UIBarButtonItem( - title: title, - style: .plain, - target: self, - action: #selector(edit) - ) - tableView.reloadData() - } - - // MARK: - delegate - - func numberOfSections(in tableView: UITableView) -> Int { - sectionTitle.count - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - switch section { - case 0: - return staticData.count - case 1: - return viewModel?.rolesData.roles.count ?? 0 - case 2: - return viewModel?.membersData.roles.count ?? 0 - default: - return 0 - } - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - switch indexPath.section { - case 0: - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - } else { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - cell.titleLabel.text = staticData[indexPath.row] - cell.rightStyle = .indicate - return cell - case 1: - let role = viewModel?.rolesData.roles[indexPath.row] - if role!.isPlacehold { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatCenterTextCell.self)", - for: indexPath - ) as! QChatCenterTextCell - cell.titleLabel.text = role?.title - cell.titleLabel.textColor = .ne_greyText - cell.titleLabel.font = .systemFont(ofSize: 14) - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - } else { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - cell.titleLabel.text = role?.role?.name - if role?.role?.type == .everyone { - cell.rightStyle = .none - } else { - cell.rightStyle = isEdit ? .delete : .none - } - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - } - - case 2: - let role = viewModel?.membersData.roles[indexPath.row] - if role!.isPlacehold { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatCenterTextCell.self)", - for: indexPath - ) as! QChatCenterTextCell - cell.titleLabel.textColor = .ne_greyText - cell.titleLabel.font = .systemFont(ofSize: 14) - cell.titleLabel.text = role?.title - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - } else { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatImageTextCell.self)", - for: indexPath - ) as! QChatImageTextCell - cell.rightStyle = isEdit ? .delete : .none - let member = viewModel?.membersData.roles[indexPath.row].member - cell.setup(accid: member?.accid, nickName: member?.nick) - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - } - default: - return UITableViewCell() - } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let head = tableView - .dequeueReusableHeaderFooterView( - withIdentifier: "\(QChatSectionView.self)" - ) as! QChatSectionView - head.titleLabel.text = sectionTitle[section] - if section == 2, viewModel?.membersData.roles.count == 0 { - head.titleLabel.text = "" - } - return head - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - switch indexPath.section { - case 0: - if indexPath.row == 0 { - // add group - let addRoleVC = QChatAddRoleGroupVC(channel: viewModel?.channel) - navigationController?.pushViewController(addRoleVC, animated: true) - - } else { - // add member - let addMemberVC = QChatAddMemberVC(channel: viewModel?.channel) - navigationController?.pushViewController(addMemberVC, animated: true) - } - - case 1: -// group - guard let model = viewModel?.rolesData.roles[indexPath.row] else { - return - } - if model.isPlacehold { - // 加载更多 - viewModel?.getChannelRoles { [weak self] error, roles in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelAuthoritySettingVC"), - desc: "CALLBACK getChannelRoles " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - } - } - } else { - if isEdit { - // delete role - deleteRole(role: model.role, index: indexPath.row) - } else { - // enter authority setting - let settingVC = QChatGroupPermissionSettingVC(cRole: model.role) - navigationController?.pushViewController(settingVC, animated: true) - } - } - - case 2: -// member - guard let model = viewModel?.membersData.roles[indexPath.row] else { - return - } - if model.isPlacehold { - // 加载更多 - viewModel?.getMembers { [weak self] error, members in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelAuthoritySettingVC"), - desc: "CALLBACK getMembers " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - } - } - } else { - if isEdit { - // delete member - deleteMember(member: model.member, index: indexPath.row) - } else { - // enter member authority setting - let settingVC = QChatMemberPermissionSettingVC( - channel: channel, - memberRole: model.member - ) - navigationController?.pushViewController(settingVC, animated: true) - } - } - default: - break - } - } - - private func deleteRole(role: ChannelRole?, index: Int) { - let name = role?.name ?? "" - let message = localizable("confirm_delete_channel") + name + localizable("qchat_id_group") + - "?" - let alertVC = UIAlertController.reconfimAlertView( - title: localizable("removeRole"), - message: message - ) { - self.viewModel?.removeChannelRole(role: role, index: index) { [weak self] error in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelAuthoritySettingVC"), - desc: "CALLBACK removeChannelRole " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - } - } - } - present(alertVC, animated: true, completion: nil) - } - - private func deleteMember(member: MemberRole?, index: Int) { - var name = member?.accid ?? "" - if let n = member?.nick, n.count > 0 { - name = n - } - let message = localizable("confirm_delete_channel") + name + localizable("qchat_member") + - "?" - let alertVC = UIAlertController.reconfimAlertView( - title: localizable("removeMember"), - message: message - ) { - self.viewModel?.removeMemberRole(member: member, index: index) { [weak self] error in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelAuthoritySettingVC"), - desc: "CALLBACK removeMemberRole " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - } - } - } - present(alertVC, animated: true, completion: nil) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelMembersVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelMembersVC.swift deleted file mode 100644 index da2832ca..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelMembersVC.swift +++ /dev/null @@ -1,186 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import MJRefresh - -public class QChatChannelMembersVC: QChatTableViewController, QChatMemberInfoViewDelegate { - public var channel: ChatChannel? - private var channelMembers: [ServerMemeber]? - var memberInfoView: QChatMemberInfoView? - var lastMember: ServerMemeber? - - override public func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() - } - - func commonUI() { - title = localizable("channel_member") - let header = - ChannelHeaderView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 78)) - header.settingButton.addTarget( - self, - action: #selector(enterChannelSetting), - for: .touchUpInside - ) - header.titleLabel.text = channel?.name - header.detailLabel.text = channel?.topic - tableView.tableHeaderView = header - tableView.register( - QChatImageTextOnlineCell.self, - forCellReuseIdentifier: "\(QChatImageTextOnlineCell.self)" - ) - tableView.mj_footer = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) - tableView.mj_header = MJRefreshNormalHeader( - refreshingTarget: self, - refreshingAction: #selector(loadData) - ) - } - - @objc func loadData() { - var param = ChannelMembersParam( - serverId: channel?.serverId ?? 0, - channelId: channel?.channelId ?? 0 - ) - param.limit = 50 - QChatChannelProvider.shared - .getChannelMembers(param: param) { [weak self] error, cMembersResult in - print( - "cMembersResult.memberArray:\(cMembersResult?.memberArray) thread:\(Thread.current) " - ) - self?.channelMembers = cMembersResult?.memberArray - self?.lastMember = cMembersResult?.memberArray?.last - self?.tableView.reloadData() - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - } - } - - @objc func loadMoreData() { - var param = ChannelMembersParam( - serverId: channel?.serverId ?? 0, - channelId: channel?.channelId ?? 0 - ) - param.timeTag = lastMember?.createTime - param.limit = 50 - QChatChannelProvider.shared - .getChannelMembers(param: param) { [weak self] error, cMembersResult in - print( - "more cMembersResult.memberArray:\(cMembersResult?.memberArray) thread:\(Thread.current) " - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - return - } - if let members = cMembersResult?.memberArray, members.count > 0 { - for m in members { - self?.channelMembers?.append(m) - } - self?.lastMember = members.last - self?.tableView.reloadData() - } else { -// end - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() - } - } - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - channelMembers?.count ?? 0 - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatImageTextOnlineCell.self)", - for: indexPath - ) as! QChatImageTextOnlineCell - let member = channelMembers![indexPath.row] as ServerMemeber - cell.setup(accid: member.accid, nickName: member.nick) - cell.online = false - if channelMembers?.count == 1 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - } else { - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - } else if indexPath.row == channelMembers!.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - } - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let m = channelMembers![indexPath.row] - memberInfoView = QChatMemberInfoView(inView: UIApplication.shared.keyWindow!) - memberInfoView?.setup(accid: m.accid, nickName: m.nick) - memberInfoView?.delegate = self - memberInfoView?.present() - loadRolesOfMember(member: m) - } - - func loadRolesOfMember(member: ServerMemeber) { - let param = GetServerRolesByAccIdParam(serverId: channel?.serverId, accid: member.accid) - QChatRoleProvider.shared.getServerRolesByAccId(param: param) { [weak self] error, roles in - print("roles:\(roles?.count) error: \(error)") - guard let roleList = roles else { - return - } - var names = [String]() - - for r in roleList { - names.append(r.name ?? "") - } - self?.memberInfoView?.setupRoles(dataArray: names) - } - } - - @objc func enterChannelSetting() { - let settingVC = QChatChannelSettingVC() - settingVC.didUpdateChannel = { [weak self] channel in - self?.channel = channel - guard let head = self?.tableView.tableHeaderView as? ChannelHeaderView else { - return - } - head.titleLabel.text = channel?.name - head.detailLabel.text = channel?.topic - } - - settingVC.didDeleteChannel = { [weak self] channel in - self?.navigationController?.popViewController(animated: true) - } - - settingVC.viewModel = QChatUpdateChannelViewModel(channel: channel) - let nav = UINavigationController(rootViewController: settingVC) - nav.modalPresentationStyle = .fullScreen - present(nav, animated: true, completion: nil) - } - - func didClickUserHeader(_ accid: String?) { - if let uid = accid { - if IMKitEngine.instance.isMySelf(uid) { - Router.shared.use( - MeSettingRouter, - parameters: ["nav": navigationController as Any], - closure: nil - ) - } else { - Router.shared.use( - ContactUserInfoPageRouter, - parameters: ["nav": navigationController as Any, "uid": uid as Any], - closure: nil - ) - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelSettingVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelSettingVC.swift deleted file mode 100644 index 5a09449b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelSettingVC.swift +++ /dev/null @@ -1,276 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -typealias UpdateChannelSuccess = (_ channel: ChatChannel?) -> Void - -public class QChatChannelSettingVC: QChatTableViewController, QChatTextEditCellDelegate { - var viewModel: QChatUpdateChannelViewModel? - var didUpdateChannel: UpdateChannelSuccess? - var didDeleteChannel: UpdateChannelSuccess? - - var sections: [String]? - var cells = [String]() - private let className = "QChatChannelSettingVC" - - override public func viewDidLoad() { - super.viewDidLoad() - loadData() - commonUI() - } - - func loadData() { - sections = [ - localizable("channel_name"), - localizable("channel_topic"), - localizable("authority"), - localizable("list"), - "", - ] - - let listName = viewModel?.channel? - .visibleType == .isPublic ? localizable("black_list") : localizable("white_list") - - cells = [ - viewModel?.channel?.name ?? "", - viewModel?.channel?.topic ?? "", - localizable("authority_setting"), - listName, - localizable("delete_channel"), - ] - } - - func commonUI() { - title = localizable("channel_setting") - navigationItem.rightBarButtonItem = UIBarButtonItem( - title: localizable("save"), - style: .plain, - target: self, - action: #selector(save) - ) - navigationItem.leftBarButtonItem = UIBarButtonItem( - title: localizable("close"), - style: .plain, - target: self, - action: #selector(close) - ) - navigationItem.rightBarButtonItem?.tintColor = .ne_blueText - tableView.rowHeight = 50 - tableView.register( - QChatTextEditCell.self, - forCellReuseIdentifier: "\(QChatTextEditCell.self)" - ) - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - tableView.register( - QChatCenterTextCell.self, - forCellReuseIdentifier: "\(QChatCenterTextCell.self)" - ) - tableView.register( - QChatSectionView.self, - forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" - ) - } - -// MARK: deletgate - - func numberOfSections(in tableView: UITableView) -> Int { - sections?.count ?? 0 - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - 1 - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - switch indexPath.section { - case 0: - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.textFied.text = cells[indexPath.section] - cell.textFied.tag = 20 - cell.delegate = self - return cell - case 1: - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.textFied.text = cells[indexPath.section] - cell.textFied.tag = 21 - cell.delegate = self - return cell - case 2, 3: - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.titleLabel.text = cells[indexPath.section] - return cell - case 4: - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatCenterTextCell.self)", - for: indexPath - ) as! QChatCenterTextCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.titleLabel.text = cells[indexPath.section] - return cell - default: - return UITableViewCell() - } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let head = tableView - .dequeueReusableHeaderFooterView( - withIdentifier: "\(QChatSectionView.self)" - ) as! QChatSectionView - head.titleLabel.text = sections?[section] - return head - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - switch indexPath.section { - case 2: - // authority - enterAuthoritySettingVC() - case 3: - // name list - enterListVC() - case 4: -// delete - deleteChannel() - default: - break - } - } - -// MARK: private method - - private func enterAuthoritySettingVC() { - navigationController?.pushViewController( - QChatChannelAuthoritySettingVC(channel: viewModel?.channel), - animated: true - ) - } - - private func enterListVC() { - let listVC = QChatWhiteBlackListVC() - listVC.channel = viewModel?.channel - listVC.type = viewModel?.channel?.visibleType == .isPublic ? .black : .white - navigationController?.pushViewController(listVC, animated: true) - } - - private func deleteChannel() { - let message: String? - if let name = viewModel?.channel?.name { - message = localizable("confirm_delete_channel") + name + "?" - } else { - message = localizable("confirm_delete_channel") + "?" - } - let alertVC = UIAlertController.reconfimAlertView( - title: localizable("delete_channel"), - message: message - ) { - self.viewModel?.deleteChannel(completion: { [weak self] error in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelSettingVC"), - desc: "CALLBACK deleteChannel " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.view.makeToast( - localizable("delete_channel_suscess"), - duration: 1, - completion: { didTap in - // 通知上级页面 - NotificationCenter.default.post( - name: NotificationName.deleteChannel, - object: self?.viewModel?.channel - ) - self?.didDeleteChannel?(self?.viewModel?.channel) - self?.close() - } - ) - } - }) - } - present(alertVC, animated: true, completion: nil) - } - -// MARK: QChatTextEditCellDelegate - - func textDidChange(_ textField: UITextField) { - if textField.tag == 20 { - if textField.text?.count == 0 { - navigationItem.rightBarButtonItem?.tintColor = .ne_greyText - } else { - if var str = textField.text, str.count > 50 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 50)) - print("str:\(str)") - textField.text = str - } - navigationItem.rightBarButtonItem?.tintColor = .ne_blueText - } - viewModel?.channelTmp?.name = textField.text - } else if textField.tag == 21 { - if var str = textField.text, str.count > 64 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 64)) - print("str:\(str)") - textField.text = str - } - viewModel?.channelTmp?.topic = textField.text - } - } - -// MARK: event - - @objc func save() { - viewModel?.updateChannelInfo(completion: { [weak self] error, channel in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatChannelSettingVC"), - desc: "CALLBACK updateChannelInfo " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - return - } - self?.view.makeToast( - localizable("update_channel_suscess"), - duration: 2, - position: .center, - completion: { didTap in - self?.didUpdateChannel?(channel) - NotificationCenter.default.post( - name: NotificationName.updateChannel, - object: channel - ) - // 通知上级页面 - self?.close() - } - ) - }) - } - - @objc func close() { - navigationController?.dismiss(animated: true, completion: nil) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelTypeVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelTypeVC.swift deleted file mode 100644 index a1e99795..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelTypeVC.swift +++ /dev/null @@ -1,74 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -struct ChannelSelection { - var sectionName = "" - var isSeleted = false -} - -protocol QChatChannelTypeVCDelegate: AnyObject { - func didSelected(type: Int) -} - -public class QChatChannelTypeVC: QChatTableViewController { - var dataList = [ChannelSelection]() - weak var delegate: QChatChannelTypeVCDelegate? - var isPrivate: Bool = false - - override public func viewDidLoad() { - super.viewDidLoad() - loadData() - commonUI() - } - - func commonUI() { - title = localizable("channel_type") - tableView.register( - QChatTextSelectionCell.self, - forCellReuseIdentifier: "\(QChatTextSelectionCell.self)" - ) - tableView.selectRow( - at: IndexPath(row: 0, section: 0), - animated: false, - scrollPosition: .top - ) - } - - func loadData() { - dataList.append(ChannelSelection(sectionName: localizable("public"), isSeleted: !isPrivate)) - dataList.append(ChannelSelection(sectionName: localizable("private"), isSeleted: isPrivate)) - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - dataList.count - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: QChatTextSelectionCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextSelectionCell.self)", - for: indexPath - ) as! QChatTextSelectionCell - let item = dataList[indexPath.row] - cell.titleLabel.text = item.sectionName - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - } else { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - cell.setSelected(true, animated: true) - } - cell.selected(selected: item.isSeleted) - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - delegate?.didSelected(type: indexPath.row) - navigationController?.popViewController(animated: true) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelViewController.swift deleted file mode 100644 index 75d31ce9..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatChannelViewController.swift +++ /dev/null @@ -1,219 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -struct Channel { - var sectionName = "" - var contentName = "" -} - -public class QChatChannelViewController: QChatTableViewController, QChatTextEditCellDelegate, - QChatChannelTypeVCDelegate { - var viewModel: QChatChannelViewModel? - var dataList = [Channel]() - // 防重点击创建频道 - var isCreatedChannel = false - private let className = "QChatChannelViewController" - - public init(serverId: UInt64) { - viewModel = QChatChannelViewModel(serverId: serverId) - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() - } - - func commonUI() { - title = localizable("create_channel") - navigationItem.rightBarButtonItem = UIBarButtonItem( - title: localizable("create"), - style: .plain, - target: self, - action: #selector(createChannel) - ) - navigationItem.leftBarButtonItem = UIBarButtonItem( - title: localizable("cancel"), - style: .plain, - target: self, - action: #selector(cancelEvent) - ) - navigationItem.rightBarButtonItem?.tintColor = .ne_greyText - tableView.register( - QChatTextEditCell.self, - forCellReuseIdentifier: "\(QChatTextEditCell.self)" - ) - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - tableView.register( - QChatSectionView.self, - forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" - ) - } - - func loadData() { - dataList - .append(Channel(sectionName: localizable("channel_name"), - contentName: localizable("input_channel_name"))) - dataList.append(Channel( - sectionName: localizable("channel_topic"), - contentName: localizable("input_channel_topic") - )) - dataList - .append(Channel(sectionName: localizable("channel_type"), - contentName: localizable("public"))) - } - - func numberOfSections(in tableView: UITableView) -> Int { - dataList.count - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - 1 - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) - cell.textFied.placeholder = dataList[indexPath.section].contentName - cell.delegate = self - cell.textFied.tag = 11 - return cell - } else if indexPath.section == 1 { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) - cell.textFied.placeholder = dataList[indexPath.section].contentName - cell.delegate = self - cell.textFied.tag = 12 - return cell - } else { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - cell.titleLabel.text = dataList[indexPath.section].contentName - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) - return cell - } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let sectionView = tableView - .dequeueReusableHeaderFooterView( - withIdentifier: "\(QChatSectionView.self)" - ) as! QChatSectionView - sectionView.titleLabel.text = dataList[section].sectionName - return sectionView - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 2 { - // select channel type - let vc = QChatChannelTypeVC() - vc.delegate = self - vc.isPrivate = viewModel?.isPrivate ?? false - navigationController?.pushViewController(vc, animated: true) - } - } - -// MARK: event - - @objc func createChannel() { - guard let name = viewModel?.name, name.count > 0 else { - showToast(localizable("channelName_cannot_be_empty")) - return - } - - if !isCreatedChannel { - isCreatedChannel = true - viewModel?.createChannel { error, channel in - NELog.errorLog( - ModuleName + " " + self.className, - desc: "error:\(error?.localizedDescription) channel:\(channel)" - ) - if error == nil { - // success to chatVC - self.navigationController?.dismiss(animated: true, completion: { - NotificationCenter.default.post( - name: NotificationName.createChannel, - object: channel - ) - }) - } else { - self.view.makeToast(error?.localizedDescription) { didTap in - self.navigationController?.dismiss(animated: true, completion: nil) - } - } - } - } - } - - @objc func cancelEvent() { - print(#function) - dismiss(animated: true, completion: nil) - } - -// MARK: QChatTextEditCellDelegate - - func textDidChange(_ textField: UITextField) { - print("textFieldDidChangeSelection textField:\(textField.text)") - if textField.tag == 11 { - if textField.text?.count == 0 { - navigationItem.rightBarButtonItem?.tintColor = .ne_greyText - } else { - if var str = textField.text, str.count > 50 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 50)) - print("str:\(str)") - textField.text = str - } - navigationItem.rightBarButtonItem?.tintColor = .ne_blueText - } - viewModel?.name = textField.text - } else if textField.tag == 12 { - if var str = textField.text, str.count > 64 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 64)) - print("str:\(str)") - textField.text = str - } - viewModel?.topic = textField.text - } - } - -// MARK: QChatChannelTypeVCDelegate - - func didSelected(type: Int) { - viewModel?.isPrivate = type == 0 ? false : true - if dataList.count >= 3 { - dataList.removeLast() - dataList.append(Channel( - sectionName: localizable("channel_type"), - contentName: type == 0 ? localizable("public") : localizable("private") - )) - tableView.reloadData() - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift deleted file mode 100644 index 9b832f88..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift +++ /dev/null @@ -1,155 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -typealias ChannelUpdateSettingBlock = (_ channelRole: ChannelRole?) -> Void - -public class QChatGroupPermissionSettingVC: QChatTableViewController, - QChatPermissionSettingCellDelegate { -// public var didUpdateBlock: ChannelUpdateSettingBlock? - public var cRole: ChannelRole? - private var commonAuths = [RoleStatusInfoExt]() - private var messageAuths = [RoleStatusInfoExt]() - private var memberAuths = [RoleStatusInfoExt]() - private var auths = [[RoleStatusInfoExt]]() - - public init(cRole: ChannelRole?) { - super.init(nibName: nil, bundle: nil) - self.cRole = cRole - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func viewDidLoad() { - super.viewDidLoad() - if let name = cRole?.name { - title = name + localizable("authority_setting") - } else { - title = localizable("authority_setting") - } - tableView.register( - QChatPermissionSettingCell.self, - forCellReuseIdentifier: "\(QChatPermissionSettingCell.self)" - ) - tableView.register( - QChatSectionView.self, - forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" - ) - tableView.sectionHeaderHeight = 42 - tableView.rowHeight = 48 - reloadData() - } - - private func reloadData() { - if let auths = cRole?.auths { - for auth in auths { - var authExt = RoleStatusInfoExt(status: auth) - let key = "auth" + String(auth.type.rawValue) - authExt.title = localizable(key) - switch auth.type { - case .ManageChannel: - commonAuths.insert(authExt, at: 0) - case .ManageRole: - commonAuths.append(authExt) - case .SendMsg: - messageAuths.append(authExt) -// case .DeleteOtherMsg: -// messageAuths.append(authExt) -// case .RevokeMsg: -// messageAuths.append(authExt) - case .BlackWhiteList: - memberAuths.append(authExt) - default: - break - } - } - if !commonAuths.isEmpty { - self.auths.append(commonAuths) - } - if !messageAuths.isEmpty { - self.auths.append(messageAuths) - } - if !memberAuths.isEmpty { - self.auths.append(memberAuths) - } - tableView.reloadData() - } - } - - func numberOfSections(in tableView: UITableView) -> Int { - auths.count - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - auths[section].count - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatPermissionSettingCell.self)", - for: indexPath - ) as! QChatPermissionSettingCell - let auths = auths[indexPath.section] - let authExt = auths[indexPath.row] - cell.updateModel(model: authExt) - cell.delegate = self - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - } else if indexPath.row == auths.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - return cell - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let view = tableView - .dequeueReusableHeaderFooterView( - withIdentifier: "\(QChatSectionView.self)" - ) as? QChatSectionView - if section == 0 { - view?.titleLabel.text = localizable("qchat_common_permission") - } else if section == 1 { - view?.titleLabel.text = localizable("qchat_message_permission") - } else { - view?.titleLabel.text = localizable("qchat_member_permission") - } - return view - } - - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - 42 - } - - // MARK: QChatPermissionSettingCellDelegate - - func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) { - if let auth = model { - let param = UpdateChannelRoleParam( - serverId: cRole?.serverId, - channelId: cRole?.channelId, - roleId: cRole?.roleId, - commands: [auth] - ) - QChatRoleProvider.shared - .updateChannelRole(param: param) { [weak self] error, channelRole in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - cell?.selectedSuccess(success: false) - } else { - cell?.selectedSuccess(success: true) -// if let block = self?.didUpdateBlock { -// block(channelRole) -// } - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift deleted file mode 100644 index 881c877b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift +++ /dev/null @@ -1,189 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -typealias UpdateSettingBlock = (_ memberRole: MemberRole?) -> Void -public class QChatMemberPermissionSettingVC: QChatTableViewController, - QChatPermissionSettingCellDelegate { - public var channel: ChatChannel? - public var memberRole: MemberRole? -// public var didUpdateBlock: UpdateSettingBlock? - private var commonAuths = [RoleStatusInfoExt]() - private var messageAuths = [RoleStatusInfoExt]() - private var memberAuths = [RoleStatusInfoExt]() - - private var auths = [[Any]]() - - init(channel: ChatChannel?, memberRole: MemberRole?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - self.memberRole = memberRole - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func viewDidLoad() { - super.viewDidLoad() - title = localizable("member_permission_setting") - tableView.register( - QChatPermissionSettingCell.self, - forCellReuseIdentifier: "\(QChatPermissionSettingCell.self)" - ) - tableView.register( - QChatImageTextCell.self, - forCellReuseIdentifier: "\(QChatImageTextCell.self)" - ) - tableView.register( - QChatSectionView.self, - forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" - ) - tableView.sectionHeaderHeight = 42 - tableView.rowHeight = 48 - reloadData() - } - - private func reloadData() { - let members = [memberRole] - auths.append(members as [Any]) - - if let auths = memberRole?.auths { - for auth in auths { - var authExt = RoleStatusInfoExt(status: auth) - let key = "auth" + String(auth.type.rawValue) - authExt.title = localizable(key) - switch auth.type { - case .ManageChannel: - commonAuths.insert(authExt, at: 0) - case .ManageRole: - commonAuths.append(authExt) - case .SendMsg: - messageAuths.append(authExt) -// case .DeleteOtherMsg: -// messageAuths.append(authExt) -// case .RevokeMsg: -// messageAuths.append(authExt) - case .BlackWhiteList: - memberAuths.append(authExt) - default: - break - } - } - - if !commonAuths.isEmpty { - self.auths.append(commonAuths) - } - if !messageAuths.isEmpty { - self.auths.append(messageAuths) - } - if !memberAuths.isEmpty { - self.auths.append(memberAuths) - } - } - tableView.reloadData() - } - - func numberOfSections(in tableView: UITableView) -> Int { - auths.count - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - auths[section].count - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - // 用户 - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatImageTextCell.self)", - for: indexPath - ) as! QChatImageTextCell - let members = auths[indexPath.section] - let m = members[indexPath.row] as? MemberRole - cell.setup(accid: m?.accid, nickName: m?.nick) - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - } else if indexPath.row == auths.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - return cell - } else { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatPermissionSettingCell.self)", - for: indexPath - ) as! QChatPermissionSettingCell - let auths = auths[indexPath.section] - let authExt = auths[indexPath.row] as? RoleStatusInfoExt - cell.updateModel(model: authExt) - cell.delegate = self - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - } else if indexPath.row == auths.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - return cell - } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let view = tableView - .dequeueReusableHeaderFooterView( - withIdentifier: "\(QChatSectionView.self)" - ) as? QChatSectionView - if section == 1 { - view?.titleLabel.text = localizable("qchat_common_permission") - } else if section == 2 { - view?.titleLabel.text = localizable("qchat_message_permission") - } else if section == 3 { - view?.titleLabel.text = localizable("qchat_member_permission") - } - return view - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 56 - } else { - return 48 - } - } - - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if section == 0 { - return 0 - } - return 42 - } - -// MARK: QChatPermissionSettingCellDelegate - - func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) { - if let auth = model { - let param = UpdateMemberRoleParam( - serverId: channel?.serverId, - channelId: channel?.channelId, - accid: memberRole?.accid, - commands: [auth] - ) - QChatRoleProvider.shared - .updateMemberRole(param: param) { [weak self] error, memberRole in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - cell?.selectedSuccess(success: false) - } else { - cell?.selectedSuccess(success: true) -// if let block = self?.didUpdateBlock { -// block(memberRole) -// } - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatSearchVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatSearchVC.swift deleted file mode 100644 index f12f898f..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatSearchVC.swift +++ /dev/null @@ -1,84 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -public class QChatSearchVC: NEBaseViewController, UITableViewDelegate, UITableViewDataSource { - var textField = UITextField() - var tableView = UITableView(frame: .zero, style: .plain) - - override public func viewDidLoad() { - super.viewDidLoad() - commonUI() - } - - func commonUI() { -// textField.placeholder = "ddd"; -// textField.leftView = UIImageView(image: UIImage.ne_imageNamed(name: "search")) -// textField.leftViewMode = .always -// textField.layer.cornerRadius = 8; -// textField.clipsToBounds = true -// textField.translatesAutoresizingMaskIntoConstraints = false -// textField.backgroundColor = .ne_lightBackgroundColor -// self.view.addSubview(textField) -// if #available(iOS 11.0, *) { -// NSLayoutConstraint.activate([ -// textField.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0), -// textField.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20), -// textField.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20), -// textField.heightAnchor.constraint(equalToConstant: 32), -// ]) -// } else { -// NSLayoutConstraint.activate([ -// textField.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20), -// textField.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20), -// textField.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20), -// textField.heightAnchor.constraint(equalToConstant: 32), -// ]) -// } - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(tableView) - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - self.tableView.topAnchor - .constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor - .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor), - ]) - } else { - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: textField.bottomAnchor), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - tableView.sectionHeaderHeight = 0 - tableView.sectionFooterHeight = 0 - tableView.rowHeight = 40 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(UITableViewCell.self)") - } - -// MARK: UITableViewDataSource - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(UITableViewCell.self)", - for: indexPath - ) - return cell - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift deleted file mode 100644 index 0a1d6ff1..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift +++ /dev/null @@ -1,254 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import NECoreKit - -public class QChatWhiteBlackListVC: QChatTableViewController, QChatMemberSelectControllerDelegate { - public var type: RoleType = .white - public var channel: ChatChannel? - private var memberArray: [ServerMemeber]? - private var isEdited: Bool = false - - override public func viewDidLoad() { - super.viewDidLoad() - isEdited = false - title = type == .white ? localizable("white_list") : localizable("black_list") - navigationItem.rightBarButtonItem = UIBarButtonItem( - title: localizable("qchat_edit"), - style: .plain, - target: self, - action: #selector(edit) - ) - - tableView.backgroundColor = .white - tableView.sectionHeaderHeight = 0 - tableView.sectionFooterHeight = 0 - tableView.register(QChatTextCell.self, forCellReuseIdentifier: "\(QChatTextCell.self)") - tableView.register( - QChatImageTextCell.self, - forCellReuseIdentifier: "\(QChatImageTextCell.self)" - ) - loadData() - } - - func loadData() { - let type: ChannelMemberRoleType = type == .white ? .white : .black - let param = GetChannelBlackWhiteMembers( - serverId: channel?.serverId, - channelId: channel?.channelId, - timeTag: 0, - limit: 20, - type: type - ) - QChatChannelProvider.shared - .getBlackWhiteMembersByPage(param: param) { [weak self] error, result in - self?.memberArray = result?.memberArray - self?.tableView.reloadData() - } - } - - func numberOfSections(in tableView: UITableView) -> Int { - 2 - } - - override public func tableView(_ tableView: UITableView, - numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 1 - } else { - return memberArray?.count ?? 0 - } - } - - override public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextCell.self)", - for: indexPath - ) as! QChatTextCell - cell.backgroundColor = .white - cell.rightStyle = .indicate - cell.titleLabel.text = localizable("add_member") - return cell - } else { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatImageTextCell.self)", - for: indexPath - ) as! QChatImageTextCell - cell.backgroundColor = .white - let member = memberArray?[indexPath.row] - cell.setup(accid: member?.accid, nickName: member?.nick) - cell.rightStyle = isEdited ? .delete : .none -// if CoreKitEngine.instance.imAccid == member?.accid, self.type == .white { -// cell.rightStyle = .none -// } - if IMKitEngine.instance.imAccid == member?.accid, type == .white { - cell.rightStyle = .none - } - return cell - } - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 0 { - // present add memeber VC - let memberSelect = QChatMemberSelectController() - memberSelect.serverId = channel?.serverId -// memberSelect.selectType = .ServerMember - memberSelect.delegate = self - memberSelect.completion = { [weak self] datas in - // 选中成员 - if datas.count > 0 { - var seletedMembers = [ServerMemeber]() - for data in datas { - if let m = data.serverMember { - seletedMembers.append(m) - } - } - self? - .addMemberList(members: seletedMembers, type: self?.type ?? .white) { error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - for m in seletedMembers { - self?.memberArray?.append(m) - } - self?.tableView.reloadData() - } - } - } - } - navigationController?.pushViewController(memberSelect, animated: true) - } else { - if isEdited { - guard let member = memberArray?[indexPath.row] else { - return - } - -// if CoreKitEngine.instance.imAccid == member.accid, self.type == .white { -// return -// } - - if IMKitEngine.instance.imAccid == member.accid, type == .white { - return - } - - let name = (member.nick != nil ? member.nick : member.accid) ?? "" - let message = localizable("confirm_delete_channel") + name + - localizable("qchat_member") + "?" - let alertVC = UIAlertController.reconfimAlertView( - title: localizable("removeMember"), - message: message - ) { - let members = [member] - self.removeMemberList(members: members, type: self.type) { [weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - if var members = self?.memberArray { - var index = -1 - for (i, m) in members.enumerated() { - if m.accid == member.accid { - index = i - break - } - } - if index >= 0 { - members.remove(at: index) - self?.memberArray = members - self?.tableView.reloadData() - } - } - } - } - } - present(alertVC, animated: true, completion: nil) - } - } - } - - // 添加黑白名单 - private func addMemberList(members: [ServerMemeber]?, type: RoleType, - _ completion: @escaping (NSError?) -> Void) { - guard let ms = members else { - return - } - var accids = [String]() - for m in ms { - accids.append(m.accid ?? "") - } - let param = UpdateChannelBlackWhiteMembersParam( - serverId: channel?.serverId, - channelId: channel?.channelId, - type: type == .white ? .white : .black, - opeType: .add, - accids: accids - ) - QChatChannelProvider.shared.updateBlackWhiteMembers(param: param, completion) - } - - // 移除黑白名单 - private func removeMemberList(members: [ServerMemeber]?, type: RoleType, - _ completion: @escaping (NSError?) -> Void) { - guard let ms = members else { - return - } - var accids = [String]() - for m in ms { - if let id = m.accid { - accids.append(id) - } - } - let param = UpdateChannelBlackWhiteMembersParam( - serverId: channel?.serverId, - channelId: channel?.channelId, - type: type == .white ? .white : .black, - opeType: .remove, - accids: accids - ) - QChatChannelProvider.shared.updateBlackWhiteMembers(param: param, completion) - } - - // MARK: - event - - @objc func edit() { - isEdited = !isEdited - if isEdited { - navigationItem.rightBarButtonItem?.title = localizable("qchat_save") - // TODO: reload data - } else { - navigationItem.rightBarButtonItem?.title = localizable("qchat_edit") - // TODO: reload data - } - tableView.reloadData() - } - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { - let type: ChannelMemberRoleType = type == .white ? .white : .black - let param = GetExistingChannelBlackWhiteMembersParam( - serverId: channel?.serverId, - channelId: channel?.channelId, - type: type, - accIds: accid - ) - QChatChannelProvider.shared - .getExistingChannelBlackWhiteMembers(param: param) { error, result in - if let members = result?.memberArray, !members.isEmpty { - var accidArray = [String]() - for member in members { - if let id = member.accid { - accidArray.append(id) - } - } - filterMembers(accidArray) - } else { - filterMembers(nil) - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift deleted file mode 100644 index 8d6b61ac..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit -import NEQChatKit - -@objcMembers -public class QChatAuthoritySettingViewModel: NSObject { - public var channel: ChatChannel? - public var rolesData = QChatRoles() - public var membersData = QChatRoles() - - private var repo = QChatRepo() - private let className = "QChatAuthoritySettingViewModel" - - init(channel: ChatChannel?) { - self.channel = channel - } - - func firstGetChannelRoles(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - rolesData.timeTag = 0 - rolesData.roles = [RoleModel]() - getChannelRoles(completion) - } - - func getChannelRoles(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - guard let sid = channel?.serverId, let cid = channel?.channelId else { - completion(NSError.paramError(), nil) - return - } - var param = ChannelRoleParam(serverId: sid, channelId: cid) - param.limit = rolesData.pageSize - param.timeTag = rolesData.timeTag - repo.getChannelRoles(param) { [weak self] error, roleList in - print("error:\(error) roleList:\(roleList)") - if error != nil { - completion(error, self?.rolesData.roles) - } else { - // 移除占位 - if let last = self?.rolesData.roles.last, last.isPlacehold { - self?.rolesData.roles.removeLast() - } - - if let roles = roleList, roles.count > 0 { - // 添加身份组 - for role in roles { - var model = RoleModel() - model.role = role - self?.rolesData.roles.append(model) - } - // 记录最后一个身份组的时间戳 用于下页请求 - self?.rolesData.timeTag = self?.rolesData.roles.last?.role?.createTime - - // 添加占位 - if roles.count >= self?.rolesData.pageSize ?? 5 { - var placeholdModel = RoleModel() - placeholdModel.title = localizable("more") - placeholdModel.isPlacehold = true - self?.rolesData.roles.append(placeholdModel) - } - self?.setRoundedCorner() - // 设置圆角 - completion(error, self?.rolesData.roles) - } else { - // 设置圆角 - self?.setRoundedCorner() - completion(error, self?.rolesData.roles) - } - } - } - } - - func firstGetMembers(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - membersData.pageSize = 50 - membersData.timeTag = 0 - membersData.roles = [RoleModel]() - getMembers(completion) - } - - func getMembers(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - guard let sid = channel?.serverId, let cid = channel?.channelId else { - completion(NSError.paramError(), nil) - return - } - var param = GetMemberRolesParam() - param.serverId = sid - param.channelId = cid - param.limit = membersData.pageSize - param.timeTag = membersData.timeTag - - repo.getMemberRoles(param: param) { [weak self] error, memberRoles in - print("error:\(error) memberArray:\(memberRoles)") - if error != nil { - completion(error, self?.membersData.roles) - } else { - // 移除占位 - if let last = self?.membersData.roles.last, last.isPlacehold { - self?.membersData.roles.removeLast() - } - if let members = memberRoles, members.count > 0 { - // 添加成员 - for member in members { - var model = RoleModel() - model.member = member - self?.membersData.roles.append(model) - } - // 记录最后一个身份组的时间戳 用于下页请求 - self?.membersData.timeTag = self?.membersData.roles.last?.member?.createTime - - // 添加占位 - if members.count == self?.rolesData.pageSize { - var placeholdModel = RoleModel() - placeholdModel.title = localizable("more") - placeholdModel.isPlacehold = true - self?.membersData.roles.append(placeholdModel) - } - self?.setRoundedCorner() - // 设置圆角 - completion(error, self?.membersData.roles) - } else { - // 设置圆角 - self?.setRoundedCorner() - completion(error, self?.membersData.roles) - } - } - } - } - - public func removeChannelRole(role: ChannelRole?, index: Int, - _ completion: @escaping (NSError?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(role?.serverId ?? 0)") - var param = RemoveChannelRoleParam() - param.serverId = role?.serverId - param.roleId = UInt64(role?.roleId ?? 0) - param.channelId = role?.channelId - repo.removeChannelRole(param: param) { [weak self] anError in - if anError == nil { - self?.rolesData.roles.remove(at: index) - completion(anError) - } - completion(anError) - } - } - - public func removeMemberRole(member: MemberRole?, index: Int, - _ completion: @escaping (NSError?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(member?.serverId ?? 0)") - let param = RemoveMemberRoleParam( - serverId: channel?.serverId, - channelId: channel?.channelId, - accid: member?.accid - ) - repo.removeMemberRole(param: param) { [weak self] anError in - if anError == nil { - self?.membersData.roles.remove(at: index) - } - completion(anError) - } - } - -// 本地插入成员 - public func insertLocalMemberAtHead(member: MemberRole) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(member.serverId ?? 0)") - let model = RoleModel(member: member, isPlacehold: false) - membersData.roles.insert(model, at: 0) - setRoundedCorner() - } - -// 本地插入身份组 - public func insertLocalRoleAtHead(role: ChannelRole) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(role.serverId ?? 0)") - let model = RoleModel(role: role, isPlacehold: false) - rolesData.roles.insert(model, at: 0) - setRoundedCorner() - } - - private func setRoundedCorner() { - NELog.infoLog(ModuleName + " " + className, desc: #function) - if rolesData.roles.count > 0 { - if rolesData.roles.count == 1 { - rolesData.roles[0].corner = .all - } else { - rolesData.roles[0].corner = .top - rolesData.roles[rolesData.roles.count - 1].corner = .bottom - } - } - if membersData.roles.count > 0 { - if membersData.roles.count == 1 { - membersData.roles[0].corner = .all - } else { - membersData.roles[0].corner = .top - membersData.roles[membersData.roles.count - 1].corner = .bottom - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatChannelViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatChannelViewModel.swift deleted file mode 100644 index 3e22b096..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatChannelViewModel.swift +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -@objcMembers -public class QChatChannelViewModel: NSObject { - public var serverId: UInt64 - public var name: String? - public var topic: String? - public var type: ChannelType = .messageType - public var isPrivate: Bool = false - private let className = "QChatChannelViewModel" - - public init(serverId: UInt64) { - self.serverId = serverId - } - - override public init() { - serverId = 0 - } - - public func createChannel(_ completion: @escaping (NSError?, ChatChannel?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - let visibleType: ChannelVisibleType = isPrivate ? .isPrivate : .isPublic - let param = CreatChannelParam( - serverId: serverId, - name: name ?? "", - topic: topic, - visibleType: visibleType - ) - QChatChannelProvider.shared.createChannel(param: param) { error, channel in - completion(error, channel) - } - } - - public func getChannelsByPage(parameter: QChatGetChannelsByPageParam, - _ completion: @escaping (NSError?, QChatGetChannelsByPageResult?) - -> Void) { - NELog.infoLog( - ModuleName + " " + className, - desc: #function + ", serverId:\(parameter.serverId ?? 0)" - ) - QChatChannelProvider.shared.getChannelsByPage(param: parameter) { error, channelResult in - completion(error, channelResult) - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift deleted file mode 100644 index 10052991..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit -import NEQChatKit - -@objcMembers -public class QChatUpdateChannelViewModel: NSObject { - public var channel: ChatChannel? - // 临时记录修改的值 - public var channelTmp: ChatChannel? - private let className = "QChatUpdateChannelViewModel" - - init(channel: ChatChannel?) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - self.channel = channel - channelTmp = channel - } - - func updateChannelInfo(completion: @escaping (NSError?, ChatChannel?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - var param = UpdateChannelParam(channelId: channel?.channelId) - param.name = channelTmp?.name - param.topic = channelTmp?.topic - param.custom = channelTmp?.custom - QChatRepo().updateChannelInfo(param) { [weak self] error, channel in - if error == nil { - self?.channel = channel - } - completion(error, channel) - } - } - - func deleteChannel(completion: @escaping (NSError?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - QChatChannelProvider.shared.deleteChannel(channelId: channel?.channelId, completion) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Controller/QChatViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Controller/QChatViewController.swift deleted file mode 100644 index 9d386367..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Controller/QChatViewController.swift +++ /dev/null @@ -1,445 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -// import IQKeyboardManagerSwift -import NIMSDK -import MJRefresh -import NECommonUIKit -import NECommonKit -import NECoreKit - -public class QChatViewController: NEBaseViewController, UINavigationControllerDelegate, - QChatInputViewDelegate, QChatViewModelDelegate, UITableViewDataSource, UITableViewDelegate { - private let tag = "QChatViewController" - private var viewmodel: QChatViewModel? - private var inputViewBottomConstraint: NSLayoutConstraint? - private var tableViewBottomConstraint: NSLayoutConstraint? - - public init(channel: ChatChannel?) { - super.init(nibName: nil, bundle: nil) - viewmodel = QChatViewModel(channel: channel) - viewmodel?.delegate = self - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func viewDidLoad() { - super.viewDidLoad() - commonUI() - addObseve() - loadData() - print("current view frame :", view.frame) - } - - // MARK: lazy Method - - private lazy var brokenNetworkView: NEBrokenNetworkView = { - let view = - NEBrokenNetworkView(frame: CGRect(x: 0, y: kNavigationHeight + KStatusBarHeight, - width: kScreenWidth, height: 36)) - return view - }() - - private lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.showsVerticalScrollIndicator = false - tableView.delegate = self - tableView.dataSource = self - tableView.backgroundColor = .white - tableView.mj_header = MJRefreshNormalHeader( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) - return tableView - }() - - deinit { - NELog.infoLog(ModuleName + " " + self.tag, desc: "✅ QChatViewController release") - } - - func commonUI() { - title = viewmodel?.channel?.name - addLeftAction(UIImage.ne_imageNamed(name: "server_menu"), #selector(enterServerVC), self) - addRightAction( - UIImage.ne_imageNamed(name: "channel_member"), - #selector(enterChannelMemberVC), - self - ) - - view.addSubview(tableView) - tableViewBottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100) - tableViewBottomConstraint?.isActive = true - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint( - equalTo: view.topAnchor, - constant: kNavigationHeight + KStatusBarHeight - ), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - ]) - - tableView.register( - QChatBaseTableViewCell.self, - forCellReuseIdentifier: "\(QChatBaseTableViewCell.self)" - ) - tableView.register( - QChatTextTableViewCell.self, - forCellReuseIdentifier: "\(QChatTextTableViewCell.self)" - ) - tableView.register( - QChatImageTableViewCell.self, - forCellReuseIdentifier: "\(QChatImageTableViewCell.self)" - ) - tableView.register( - QChatTimeTableViewCell.self, - forCellReuseIdentifier: "\(QChatTimeTableViewCell.self)" - ) - // IQKeyboardManager.shared.enable = false - -// NEKeyboardManager.shared.keyboardDistanceFromTextField = 60 - NEKeyboardManager.shared.enable = true - NEKeyboardManager.shared.enableAutoToolbar = false - let inputView = QChatInputView() - var tip = localizable("send_to") - if let cName = viewmodel?.channel?.name { - tip += cName - } - inputView.textField.placeholder = tip - - inputView.translatesAutoresizingMaskIntoConstraints = false - inputView.delegate = self - view.addSubview(inputView) - if #available(iOS 11.0, *) { - self.inputViewBottomConstraint = inputView.bottomAnchor - .constraint(equalTo: self.view.bottomAnchor) -// self.inputViewBottomConstraint = inputView.bottomAnchor.constraint(equalTo: -// self.view.safeAreaLayoutGuide.bottomAnchor) - NSLayoutConstraint.activate([ - inputView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - inputView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - inputView.heightAnchor.constraint(equalToConstant: 100), - ]) - } else { - // Fallback on earlier versions - inputViewBottomConstraint = inputView.bottomAnchor - .constraint(equalTo: view.bottomAnchor) - NSLayoutConstraint.activate([ - inputView.leftAnchor.constraint(equalTo: view.leftAnchor), - inputView.rightAnchor.constraint(equalTo: view.rightAnchor), - inputView.heightAnchor.constraint(equalToConstant: 100), - ]) - } - inputViewBottomConstraint?.isActive = true - - weak var weakSelf = self - NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in - if status == .notReachable, let networkView = weakSelf?.brokenNetworkView { - weakSelf?.view.addSubview(networkView) - } else { - weakSelf?.brokenNetworkView.removeFromSuperview() - } - } - } - - // MARK: event - - @objc func enterChannelMemberVC() { - let memberVC = QChatChannelMembersVC() - memberVC.channel = viewmodel?.channel - navigationController?.pushViewController(memberVC, animated: true) - } - - @objc func enterServerVC() { - navigationController?.popViewController(animated: true) - } - - func loadData() { - weak var weakSelf = self - viewmodel?.getMessageHistory { error, messages in - - if let err = error { - NELog.errorLog(ModuleName + " " + self.tag, desc: "❌getMessageHistory error, error:\(err)") - } else { - if let tempArray = weakSelf?.viewmodel?.messages, tempArray.count > 0 { - weakSelf?.tableView.reloadData() - weakSelf?.tableView.scrollToRow( - at: IndexPath(row: tempArray.count - 1, section: 0), - at: .bottom, - animated: false - ) - if let time = messages?.first?.message?.timestamp { - weakSelf?.viewmodel?.markMessageRead(time: time) - } - } - } - } - } - - @objc func loadMoreData() { - weak var weakSelf = self - viewmodel?.getMoreMessageHistory { error, messageFrames in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK getMoreMessageHistory " + (error?.localizedDescription ?? "no error") - ) - weakSelf?.tableView.reloadData() - weakSelf?.tableView.mj_header?.endRefreshing() - } - } - - func addObseve() { - NotificationCenter.default.addObserver( - self, - selector: #selector(onUpdateChannel), - name: NotificationName.updateChannel, - object: nil - ) - NotificationCenter.default.addObserver( - self, - selector: #selector(onDeleteChannel), - name: NotificationName.deleteChannel, - object: nil - ) - NotificationCenter.default.addObserver(self, - selector: #selector(keyBoardWillShow(_:)), - name: UIResponder.keyboardWillShowNotification, - object: nil) - - NotificationCenter.default.addObserver(self, - selector: #selector(keyBoardWillHide(_:)), - name: UIResponder.keyboardWillHideNotification, - object: nil) - } - - @objc func onUpdateChannel(noti: Notification) { - // enter ChatVC - guard let channel = noti.object as? ChatChannel else { - return - } - viewmodel?.channel = channel - title = viewmodel?.channel?.name - } - - @objc func onDeleteChannel(noti: Notification) { - navigationController?.popToRootViewController(animated: true) - } - - // MARK: 键盘通知相关操作 - - @objc func keyBoardWillShow(_ notification: Notification) { - let keyboardRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! - NSValue).cgRectValue - inputViewBottomConstraint?.constant = -keyboardRect.size.height - tableViewBottomConstraint?.constant = -100 - keyboardRect.size.height - UIView.animate(withDuration: 0.25, animations: { - // self.view.layoutIfNeeded() - }) - if let count = viewmodel?.messages.count, count > 0 { - print("count \(count)") - tableView.scrollToRow(at: IndexPath(row: count - 1, section: 0), at: .bottom, animated: true) - } - } - - @objc func keyBoardWillHide(_ notification: Notification) { - inputViewBottomConstraint?.constant = 0 - tableViewBottomConstraint?.constant = -100 - UIView.animate(withDuration: 0.25, animations: { - // self.view.layoutIfNeeded() - }) - } - - // MARK: QChatInputViewDelegate - - func sendText(text: String?) { - NELog.infoLog(ModuleName + " " + tag, desc: "sendText:\(text ?? "")") - guard let content = text, content.count > 0 else { - return - } - viewmodel?.sendTextMessage(text: content) { [weak self] error in - NELog.infoLog( - ModuleName + " " + (self?.tag ?? "QChatViewController"), - desc: "CALLBACK sendTextMessage " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else {} - } - } - - func willSelectItem(button: UIButton, index: Int) { - if index == 2 { - showBottomAlert(self, false) - } else { - showToast(localizable("open_soon")) - } - } - - // MARK: UIImagePickerControllerDelegate - - public func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [UIImagePickerController - .InfoKey: Any]) { - picker.dismiss(animated: true, completion: nil) - guard let image = info[.originalImage] as? UIImage else { - showToast(localizable("image_is_nil")) - return - } - // 发送消息 - viewmodel?.sendImageMessage(image: image) { [weak self] error in - NELog.infoLog( - ModuleName + " " + (self?.tag ?? "QChatViewController"), - desc: "CALLBACK sendImageMessage " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } - } - } - - // MARK: QChatViewModelDelegate - - public func onRecvMessages(_ messages: [NIMQChatMessage]) { - tableView.reloadData() - if let messageCount = viewmodel?.messages.count, messageCount > 1 { - tableView.scrollToRow( - at: IndexPath(row: messageCount - 1, section: 0), - at: .bottom, - animated: false - ) - if let time = viewmodel?.messages.last?.message?.timestamp { - viewmodel?.markMessageRead(time: time) - } - } - } - - public func send(_ message: NIMQChatMessage, progress: Float) {} - - public func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) { - if let e = error as NSError? { - if e.code == 403 { - showAlert(message: localizable("no_Permession")) {} - } - } - tableView.reloadData() - if let messageCount = viewmodel?.messages.count, messageCount > 1 { - tableView.scrollToRow( - at: IndexPath(row: messageCount - 1, section: 0), - at: .bottom, - animated: false - ) - } - } - - public func willSend(_ message: NIMQChatMessage) { - tableView.reloadData() - if let messageCount = viewmodel?.messages.count, messageCount > 1 { - tableView.scrollToRow( - at: IndexPath(row: messageCount - 1, section: 0), - at: .bottom, - animated: false - ) - } - } - - // MARK: UITableViewDataSource, UITableViewDelegate - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - viewmodel?.messages.count ?? 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let messageFrame = viewmodel?.messages[indexPath.row] - var reuseIdentifier = "\(QChatBaseTableViewCell.self)" - - guard let msgFrame = messageFrame else { - return tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) - } - - if msgFrame.showTime { - reuseIdentifier = "\(QChatTimeTableViewCell.self)" - } else { - // 根据cell类型区分identify - switch msgFrame.message?.messageType { - case .text: - reuseIdentifier = "\(QChatTextTableViewCell.self)" - case .image: - reuseIdentifier = "\(QChatImageTableViewCell.self)" - default: - reuseIdentifier = "\(QChatBaseTableViewCell.self)" - } - } - - if msgFrame.showTime { - let cell = tableView.dequeueReusableCell( - withIdentifier: reuseIdentifier, - for: indexPath - ) as! QChatTimeTableViewCell - cell.messageFrame = messageFrame - return cell - } else { - let cell = tableView.dequeueReusableCell( - withIdentifier: reuseIdentifier, - for: indexPath - ) as! QChatBaseTableViewCell - cell.messageFrame = messageFrame - cell.delegate = self - return cell - } - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - let messageFrame = viewmodel?.messages[indexPath.row] - return messageFrame?.cellHeight ?? 0 - } -} - -// MARK: =============== QChatBaseCellDelegate ================ - -extension QChatViewController: QChatBaseCellDelegate { - func didSelectWithCell(cell: QChatBaseTableViewCell, type: QChatMessageClickType, - message: NIMQChatMessage) { - if type == .message { - didClickMessage(messgae: message) - } else if type == .LongPressMessage {} - } - - func didClickHeader(_ message: NIMQChatMessage) { - if IMKitEngine.instance.isMySelf(message.from) == true { - Router.shared.use( - MeSettingRouter, - parameters: ["nav": navigationController as Any], - closure: nil - ) - } else { - Router.shared.use( - ContactUserInfoPageRouter, - parameters: ["nav": navigationController as Any, "uid": message.from as Any], - closure: nil - ) - } - } - - // click action - func didClickMessage(messgae: NIMQChatMessage) { - if messgae.messageType == .image { - let imageObject = messgae.messageObject as! NIMImageObject - if let imageUrl = imageObject.url { - let showController = PhotoBrowserController(urls: [imageUrl], url: imageUrl) - showController.modalPresentationStyle = .overFullScreen - present(showController, animated: false, completion: nil) - } - - } else if messgae.messageType == .audio {} - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Helper/QChatMessageHelper.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Helper/QChatMessageHelper.swift deleted file mode 100644 index ca13a866..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Helper/QChatMessageHelper.swift +++ /dev/null @@ -1,35 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation - -class QChatMessageHelper { - // 获取图片合适尺寸 - class func getSizeWithMaxSize(_ maxSize: CGSize, size: CGSize, miniWH: CGFloat) -> CGSize { - var realSize = CGSize.zero - - if min(size.width, size.height) > 0 { - if size.width > size.height { - // 宽大 按照宽给高 - let width = CGFloat(min(maxSize.width, size.width)) - realSize = CGSize(width: width, height: width * size.height / size.width) - if realSize.height < miniWH { - realSize.height = miniWH - } - } else { - // 高大 按照高给宽 - let height = CGFloat(min(maxSize.height, size.height)) - realSize = CGSize(width: height * size.width / size.height, height: height) - if realSize.width < miniWH { - realSize.width = miniWH - } - } - } else { - realSize = maxSize - } - - return realSize - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Model/QChatMessageFrame.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Model/QChatMessageFrame.swift deleted file mode 100644 index a14fc714..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/Model/QChatMessageFrame.swift +++ /dev/null @@ -1,119 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NIMSDK -public class QChatMessageFrame: NSObject { - // 是否显示时间 - public var showTime: Bool = false - // 具体时间 - public var time: String? - // 是否显示头像 - public var showAvatar: Bool = true - // 用户头像地址 - public var avatar: String? - // nickname - public var nickname: String? - // 发送者是否为自己 -// public var isSender:Bool? - // 头像frame - public var headFrame: CGRect? - // 内容frame - public var contentFrame: CGRect? - // cell整体高度 - public var cellHeight: CGFloat = 0.0 - // X初始位置 - public var startX: CGFloat = 0.0 - -// public init(isSender:Bool) { -// self.isSender = isSender -// } - - public var message: NIMQChatMessage? { - didSet { - var contentSize = CGSize.zero - - switch message?.messageType { - case .text: // 计算文本 - - contentSize = String.getTextRectSize( - message?.text ?? "", - font: DefaultTextFont(16), - size: CGSize(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude) - ) - if contentSize.height < qChat_min_h { // 小于一行高度,就保持一行 - contentSize.height = qChat_min_h - } - contentSize.width += 2 * qChat_margin - case .image: // 计算图片类型 - if let imageObject = message?.messageObject, - imageObject.isKind(of: NIMImageObject.self) { - let obj = (imageObject as! NIMImageObject) - contentSize = QChatMessageHelper.getSizeWithMaxSize( - qChat_pic_size, - size: obj.size, - miniWH: qChat_min_h - ) - } else { - contentSize = qChat_pic_size - } - - default: - print("others") - } - - // 计算头像 - var headFrameX = qChat_cell_margin - let headFrameY = qChat_margin - - guard let msg = message else { - return - } - - if msg.isOutgoingMsg { // 消息发送者 - headFrameX = kScreenWidth - headFrameX - qChat_headWH - } - headFrame = CGRect( - x: headFrameX, - y: headFrameY, - width: qChat_headWH, - height: qChat_headWH - ) - - let viewY = qChat_margin - - // 聊天气泡的frame - var viewX = 0.0 - - viewX = headFrame!.maxX + qChat_margin - if msg.isOutgoingMsg { // 消息发送者 - viewX = kScreenWidth - contentSize - .width - qChat_margin - qChat_headWH - qChat_cell_margin - } - contentFrame = CGRect( - x: viewX, - y: viewY, - width: contentSize.width, - height: contentSize.height - ) - - // cell 高度 - cellHeight = contentSize.height + qChat_margin - - if let type = message?.messageType { - if type == .text, contentSize.height > qChat_min_h { - if let height = contentFrame?.size.height { - contentFrame?.size.height = height + qChat_margin * 2 - } - cellHeight += qChat_margin * 2 - } - } - - // 起始位置 -// _startX = isSend ? 0 : kChat_angle_w; - startX = 0 - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift deleted file mode 100644 index 5e0a4d07..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift +++ /dev/null @@ -1,166 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NIMSDK -import NECoreKit - -@objc class QChatBubbleButton: UIButton { - // 设置气泡背景图片 - public func setBubbleImage(image: UIImage) { - let image = image - .resizableImage(withCapInsets: UIEdgeInsets(top: 35, left: 25, bottom: 10, right: 25)) - setBackgroundImage(image, for: .normal) - setBackgroundImage(image, for: .highlighted) - } - - override init(frame: CGRect) { - super.init(frame: frame) - imageView?.contentMode = .scaleAspectFill - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } -// //设置气泡背景色 -// public func setBubbleImage(color:UIColor){ -// let image = self.currentBackgroundImage -// } -} - -enum QChatMessageClickType: String { - case message - case LongPressMessage - case head - case retry -} - -protocol QChatBaseCellDelegate: NSObjectProtocol { - // click action - func didSelectWithCell(cell: QChatBaseTableViewCell, type: QChatMessageClickType, - message: NIMQChatMessage) - - func didClickHeader(_ message: NIMQChatMessage) -} - -class QChatBaseTableViewCell: UITableViewCell { - weak var delegate: QChatBaseCellDelegate? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - public var messageFrame: QChatMessageFrame? { - didSet { - self.btnHeadImage.frame = messageFrame?.headFrame ?? CGRect.zero - self.contentBtn.frame = messageFrame?.contentFrame ?? CGRect.zero - - // TODO: 头像赋值 - if let icon = messageFrame?.avatar { - btnHeadImage.setTitle("") - btnHeadImage.sd_setImage(with: URL(string: icon), completed: nil) - } else { - if let sendName = messageFrame?.message?.senderName { - btnHeadImage.setTitle(sendName) - } else { - btnHeadImage.setTitle(messageFrame?.message?.from ?? "") - } - btnHeadImage.sd_setImage(with: nil, completed: nil) - btnHeadImage.backgroundColor = UIColor.colorWithNumber(number: 0) - } - - guard let msg = messageFrame?.message else { - return - } - if msg.isOutgoingMsg { - self.contentBtn - .setBubbleImage(image: UIImage.ne_imageNamed(name: "chat_message_send")!) - // 设置消息状态 判断消息发送是否成功 - if msg.deliveryState == NIMMessageDeliveryState.delivering { - self.activityView.frame = CGRect( - x: contentBtn.left - (5 + 20), - y: contentBtn.top + (contentBtn.height - 20) / 2, - width: 20, - height: 20 - ) - self.activityView.messageStatus = .sending - } else if msg.deliveryState == NIMMessageDeliveryState.deliveried { - self.activityView.messageStatus = .successed - } else { - self.activityView.messageStatus = .failed - } - - } else { - self.contentBtn - .setBubbleImage(image: UIImage.ne_imageNamed(name: "chat_message_receive")!) - } - } - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - contentView.backgroundColor = .white - addContentSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func addContentSubviews() { - contentView.addSubview(btnHeadImage) - contentView.addSubview(contentBtn) - contentView.addSubview(activityView) - } - - override func draw(_ rect: CGRect) { - btnHeadImage.addCorner(conrners: .allCorners, radius: 16) - } - - private lazy var btnHeadImage: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - let tap = UITapGestureRecognizer() - view.addGestureRecognizer(tap) - tap.numberOfTapsRequired = 1 - tap.numberOfTouchesRequired = 1 - tap.addTarget(self, action: #selector(headerClick)) - return view - }() - - public lazy var contentBtn: QChatBubbleButton = { - let btn = QChatBubbleButton(frame: .zero) - btn.addTarget(self, action: #selector(bubbleClick), for: .touchUpInside) - return btn - }() - - public lazy var activityView: QChatActivityIndicatorView = { - let activityView = QChatActivityIndicatorView() - activityView.isHidden = true - return activityView - }() -} - -extension QChatBaseTableViewCell { - @objc func bubbleClick(sender: UIButton) { - if let message = messageFrame?.message { - delegate?.didSelectWithCell(cell: self, type: .message, message: message) - } - } - - @objc func headerClick() { - NELog.infoLog("chat base cell", desc: "header click") - if let message = messageFrame?.message { - delegate?.didClickHeader(message) - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatImageTableViewCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatImageTableViewCell.swift deleted file mode 100644 index 1e8dbce8..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatImageTableViewCell.swift +++ /dev/null @@ -1,49 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import UIKit -import NIMSDK -class QChatImageTableViewCell: QChatBaseTableViewCell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private lazy var contentImageView: UIImageView = { - let imageView = UIImageView() - imageView.contentMode = .scaleAspectFill - self.contentBtn.addSubview(imageView) - imageView.clipsToBounds = true - return imageView - }() - - override public var messageFrame: QChatMessageFrame? { - didSet { - let imageObject = messageFrame?.message?.messageObject as! NIMImageObject - contentImageView.frame = CGRect( - x: qChat_margin, - y: qChat_margin, - width: contentBtn.width - 2 * qChat_margin, - height: contentBtn.height - 2 * qChat_margin - ) - - if let imageUrl = imageObject.url { - contentImageView.sd_setImage( - with: URL(string: imageUrl), - placeholderImage: nil, - options: .retryFailed, - progress: nil, - completed: nil - ) - } else { - contentImageView.image = UIImage() - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatTextTableViewCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatTextTableViewCell.swift deleted file mode 100644 index b57484fd..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatTextTableViewCell.swift +++ /dev/null @@ -1,92 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatTextTableViewCell: QChatBaseTableViewCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - } - - override public var messageFrame: QChatMessageFrame? { - didSet { -// // SHMessage *message = messageFrame.message; - textView.text = messageFrame?.message?.text - var viewY = qChat_margin - if contentBtn.height == qChat_min_h { - viewY = (qChat_min_h - DefaultTextFont(16).lineHeight) / 2 - } - - // 此处要根据发送者还是接收者判断起始x值 - let leftStartMargin = messageFrame?.startX - textView.frame = CGRect( - x: (leftStartMargin ?? 0) + qChat_margin, - y: viewY, - width: contentBtn.width - 2 * qChat_margin - qChat_angle_w, - height: contentBtn.height - 2 * viewY - ) - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private lazy var textView: QChatTextView = { - let textview = QChatTextView() - textview.isEditable = false - textview.isScrollEnabled = false - textview.showsVerticalScrollIndicator = false - textview.textContainer.maximumNumberOfLines = 0 - self.contentBtn.addSubview(textview) - return textview - }() -} - -class QChatTextView: UITextView { - override init(frame: CGRect, textContainer: NSTextContainer?) { - super.init(frame: frame, textContainer: textContainer) - setupUI() - } - - public required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupUI() { - backgroundColor = .clear - textContainer.lineFragmentPadding = 0 - textContainerInset = .zero - dataDetectorTypes = .all - autoresizingMask = [.flexibleWidth, .flexibleHeight] - font = DefaultTextFont(16) - } - - override var textContainerInset: UIEdgeInsets { - set { - let padding = textContainer.lineFragmentPadding - super.textContainerInset = UIEdgeInsets( - top: newValue.top, - left: newValue.left - padding, - bottom: newValue.bottom, - right: newValue.right - padding - ) - } - get { - super.textContainerInset - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift deleted file mode 100644 index 7c0816cc..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift +++ /dev/null @@ -1,39 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatTimeTableViewCell: UITableViewCell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - contentView.addSubview(timeLabel) - NSLayoutConstraint.activate([ - timeLabel.topAnchor.constraint(equalTo: contentView.topAnchor), - timeLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor), - timeLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor), - timeLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public var messageFrame: QChatMessageFrame? { - didSet { - timeLabel.text = messageFrame?.time - } - } - - private lazy var timeLabel: UILabel = { - let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = UIColor.ne_emptyTitleColor - label.textAlignment = .center - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/QChatActivityIndicatorView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/QChatActivityIndicatorView.swift deleted file mode 100644 index 8ee76554..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/QChatActivityIndicatorView.swift +++ /dev/null @@ -1,81 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -enum QChatSendMessageStatus { - case successed - case sending - case failed -} - -class QChatActivityIndicatorView: UIButton { - public var messageStatus: QChatSendMessageStatus? { - didSet { - failBtn.isHidden = true - activity.isHidden = true - activity.stopAnimating() - - switch messageStatus { - case .sending: - self.isHidden = false - activity.isHidden = false - activity.startAnimating() - case .failed: - self.isHidden = false - failBtn.isHidden = false - case .successed: - self.isHidden = true - - default: - print("") - } - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - addSubview(failBtn) - addSubview(activity) - NSLayoutConstraint.activate([ - failBtn.topAnchor.constraint(equalTo: topAnchor), - failBtn.leftAnchor.constraint(equalTo: leftAnchor), - failBtn.bottomAnchor.constraint(equalTo: bottomAnchor), - failBtn.rightAnchor.constraint(equalTo: rightAnchor), - ]) - - NSLayoutConstraint.activate([ - activity.topAnchor.constraint(equalTo: topAnchor), - activity.leftAnchor.constraint(equalTo: leftAnchor), - activity.bottomAnchor.constraint(equalTo: bottomAnchor), - activity.rightAnchor.constraint(equalTo: rightAnchor), - ]) - } - - // MARK: lazy Method - - private lazy var failBtn: UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.isUserInteractionEnabled = false - button.setBackgroundImage(UIImage.ne_imageNamed(name: "sendMessage_failed"), for: .normal) - return button - }() - - private lazy var activity: UIActivityIndicatorView = { - let activity = UIActivityIndicatorView() - activity.translatesAutoresizingMaskIntoConstraints = false - activity.color = .gray - return activity - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/QChatInputView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/QChatInputView.swift deleted file mode 100644 index 03cc6bd7..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/View/QChatInputView.swift +++ /dev/null @@ -1,80 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -protocol QChatInputViewDelegate: AnyObject { - func sendText(text: String?) - func willSelectItem(button: UIButton, index: Int) -} - -class QChatInputView: UIView, UITextFieldDelegate { - public weak var delegate: QChatInputViewDelegate? - var textField = UITextField() - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - backgroundColor = UIColor(hexString: "#EFF1F3") - textField.layer.cornerRadius = 8 - textField.clipsToBounds = true - textField.translatesAutoresizingMaskIntoConstraints = false - textField.backgroundColor = .white - textField.leftViewMode = .always - textField.returnKeyType = .send - textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 40)) - textField.delegate = self - addSubview(textField) - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: leftAnchor, constant: 7), - textField.topAnchor.constraint(equalTo: topAnchor, constant: 6), - textField.rightAnchor.constraint(equalTo: rightAnchor, constant: -7), - textField.heightAnchor.constraint(equalToConstant: 40), - ]) - let imageNames = ["mic", "emoji", "photo", "file", "add"] - var items = [UIButton]() - for i in 0 ... 4 { - let button = UIButton(type: .custom) - button.setImage(UIImage.ne_imageNamed(name: imageNames[i]), for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - button.tag = i + 5 - items.append(button) - if i != 2 { - button.alpha = 0.5 - } - } - let stackView = UIStackView(arrangedSubviews: items) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.distribution = .fillEqually - addSubview(stackView) - NSLayoutConstraint.activate([ - stackView.leftAnchor.constraint(equalTo: leftAnchor), - stackView.rightAnchor.constraint(equalTo: rightAnchor), - stackView.heightAnchor.constraint(equalToConstant: 54), - stackView.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 0), - ]) - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - guard let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) else { - return true - } - textField.text = "" - delegate?.sendText(text: text) - textField.resignFirstResponder() - return true - } - - @objc func buttonEvent(button: UIButton) { - delegate?.willSelectItem(button: button, index: button.tag - 5) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/ViewModel/QChatViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Chat/ViewModel/QChatViewModel.swift deleted file mode 100644 index 7eaa9af0..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Chat/ViewModel/QChatViewModel.swift +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit -import NIMSDK - -@objc -public protocol QChatViewModelDelegate: NSObjectProtocol { - func onRecvMessages(_ messages: [NIMQChatMessage]) - func willSend(_ message: NIMQChatMessage) - func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) - func send(_ message: NIMQChatMessage, progress: Float) -} - -@objcMembers -public class QChatViewModel: NSObject, NIMQChatMessageManagerDelegate { - public var channel: ChatChannel? - public var messages: [QChatMessageFrame] = .init() - public weak var delegate: QChatViewModelDelegate? - private var lastMsg: NIMQChatMessage? - private let className = "QChatViewModel" - - init(channel: ChatChannel?) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - super.init() - self.channel = channel - QChatSystemMessageProvider.shared.addDelegate(delegate: self) - } - - public func sendTextMessage(text: String, _ completion: @escaping (Error?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", text.count:\(text.count)") - if text.count <= 0 { - return - } - if let cid = channel?.channelId, let sid = channel?.serverId { - let message = NIMQChatMessage() - message.text = text - message.from = IMKitEngine.instance.imAccid - QChatSystemMessageProvider.shared.sendMessage( - message: message, - session: NIMSession(forQChat: Int64(cid), qchatServerId: Int64(sid)) - ) { error in - print("sendText error:\(error) ") - completion(error) - } - } - } - - public func sendImageMessage(image: UIImage, _ completion: @escaping (Error?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - if let cid = channel?.channelId, let sid = channel?.serverId { - let message = NIMQChatMessage() - message.messageObject = NIMImageObject(image: image) - message.from = IMKitEngine.instance.imAccid - QChatSystemMessageProvider.shared.sendMessage( - message: message, - session: NIMSession(forQChat: Int64(cid), qchatServerId: Int64(sid)) - ) { error in - print("sendImage error:\(error) ") - completion(error) - } - } - } - - public func getMessageHistory(_ completion: @escaping (Error?, [QChatMessageFrame]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - if let cid = channel?.channelId, let sid = channel?.serverId { - lastMsg = nil - var param = GetMessageHistoryParam(serverId: sid, channelId: cid) - param.lastMsg = lastMsg - QChatSystemMessageProvider.shared - .getMessageHistory(param: param) { [weak self] error, messages in - if let messageArray = messages, messageArray.count > 0 { - self?.lastMsg = messageArray.last - self?.getUserInfo(messages: messageArray) { error, messageExts in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatViewModel"), - desc: "CALLBACK getUserInfo " + (error?.localizedDescription ?? "no error") - ) - for msgExt in messageExts { - self?.addTimeForHistoryMessage(msgExt) - self?.messages.insert(msgExt, at: 0) - } - if let last = messageExts.last, let msg = self?.timeModel(last) { - self?.messages.insert(msg, at: 0) - } - completion(error, messageExts) - } - } else { - completion(error, nil) - } - } - } else { - completion(NSError.paramError(), nil) - } - } - - public func getMoreMessageHistory(_ completion: @escaping (Error?, [QChatMessageFrame]?) - -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - if let cid = channel?.channelId, let sid = channel?.serverId { - var param = GetMessageHistoryParam(serverId: sid, channelId: cid) - param.lastMsg = lastMsg - QChatSystemMessageProvider.shared - .getMessageHistory(param: param) { [weak self] error, messages in - if let messageArray = messages, messageArray.count > 0 { - self?.lastMsg = messageArray.last - self?.getUserInfo(messages: messageArray) { error, messageExts in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "QChatViewModel"), - desc: "CALLBACK getUserInfo " + (error?.localizedDescription ?? "no error") - ) - for msgExt in messageExts { - self?.addTimeForHistoryMessage(msgExt) - self?.messages.insert(msgExt, at: 0) - } - if let last = messageExts.last, let msg = self?.timeModel(last) { - self?.messages.insert(msg, at: 0) - } - completion(error, messageExts) - } - } else { - completion(error, nil) - } - } - } else { - completion(NSError.paramError(), nil) - } - } - - public func getUserInfo(messages: [NIMQChatMessage], - _ completion: @escaping (Error?, [QChatMessageFrame]) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", messages.count:\(messages.count)") - var userIds = [String]() - var lastMsg: NIMQChatMessage? - var tmp = [QChatMessageFrame]() - - for message in messages { -// let isSend = message.from == CoreKitIMEngine.instance.imAccid - let msgExt = QChatMessageFrame() - msgExt.message = message - msgExt.showAvatar = lastMsg?.from != message.from - tmp.append(msgExt) - lastMsg = message - if let userId = message.from, msgExt.showAvatar { - userIds.append(userId) - } - } - if userIds.isEmpty { - completion(nil, tmp) - } else { - FriendProvider.shared.getUserInfoAdvanced(userIds: userIds) { userInfoList, error in - var result = [QChatMessageFrame]() - for msg in tmp { - for u in userInfoList { - if msg.message?.from == u.userId { - msg.avatar = u.userInfo?.thumbAvatarUrl - msg.nickname = u.userInfo?.nickName - } - } - result.append(msg) - } - completion(error, result) - } - } - } - - public func markMessageRead(time: TimeInterval) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - if let cid = channel?.channelId, let sid = channel?.serverId { - var param = MarkMessageReadParam(serverId: sid, channelId: cid) - param.ackTimestamp = time - weak var weakSelf = self - QChatSystemMessageProvider.shared.markMessageRead(param: param) { error in - if error != nil { - NELog.errorLog( - ModuleName + " " + (weakSelf?.className ?? "QChatViewModel"), - desc: "❌markMessageRead failed,error = \(error!)" - ) - } - } - } - } - - // MARK: NIMChatManagerDelegate - - public func onRecvMessages(_ messages: [NIMQChatMessage]) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", messages.count:\(messages.count)") - print("\(#function) messages:\(messages.count)") - var channelMsgs = [NIMQChatMessage]() - for msg in messages { - if msg.qchatChannelId == channel?.channelId { - channelMsgs.append(msg) - } - } - getUserInfo(messages: channelMsgs) { error, msgExts in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK getUserInfo " + (error?.localizedDescription ?? "no error") - ) - for msgExt in msgExts { - self.addTimeMessage(msgExt) - self.messages.append(msgExt) - } - } - delegate?.onRecvMessages(channelMsgs) - } - - public func willSend(_ message: NIMQChatMessage) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId:\(message.messageId)") - print("\(#function)") - if lastMsg == nil { - lastMsg = message - } - getUserInfo(messages: [message]) { error, msgExts in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK getUserInfo " + (error?.localizedDescription ?? "no error") - ) - for msgExt in msgExts { - self.addTimeMessage(msgExt) - self.messages.append(msgExt) - } - } - delegate?.willSend(message) - } - - public func send(_ message: NIMQChatMessage, progress: Float) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId:\(message.messageId)") - print("\(#function) progress\(progress)") - delegate?.send(message, progress: progress) - } - - public func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId:\(message.messageId)") - print("\(#function) message deliveryState:\(message.deliveryState) error:\(error)") - if let e = error as NSError? { - if e.code == 403 { - var index = 0 - for (i, msg) in messages.enumerated() { - if message.messageId == msg.message?.messageId { - index = i - } - } - messages.remove(at: index) - } - } else { - for (i, msg) in messages.enumerated() { - if message.messageId == msg.message?.messageId { - messages[i].message = message - break - } - } - } - delegate?.send(message, didCompleteWithError: error) - } - - private func modelFromMessage(_ message: NIMQChatMessage) -> QChatMessageFrame { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", messageId:\(message.messageId)") -// let isSend = message.from == CoreKitIMEngine.instance.imAccid - let model = QChatMessageFrame() - model.showAvatar = message.from != messages.last?.message?.from - model.message = message - return model - } - - // history message insert message at first of messages, send message add last of messages - private func addTimeMessage(_ message: QChatMessageFrame) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - let lastTs = messages.last?.message?.timestamp ?? 0.0 - let curTs = message.message?.timestamp ?? 0.0 - let dur = curTs - lastTs - if (dur / 60) > 5 { -// let model = QChatMessageFrame(isSender: true) -// model.showTime = true -// model.time = String.stringFromDate(date:Date(timeIntervalSince1970: curTs)) -// model.showAvatar = false -// model.cellHeight = 35 - messages.append(timeModel(message)) - } - } - - private func addTimeForHistoryMessage(_ message: QChatMessageFrame) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - let firstTs = messages.first?.message?.timestamp ?? 0.0 - let curTs = message.message?.timestamp ?? 0.0 - let dur = firstTs - curTs - if (dur / 60) > 5 { - let model = QChatMessageFrame() - model.showTime = true - model.time = String.stringFromDate(date: Date(timeIntervalSince1970: firstTs)) - model.showAvatar = false - model.cellHeight = 35 - messages.insert(model, at: 0) - } - } - - private func timeModel(_ message: QChatMessageFrame) -> QChatMessageFrame { - NELog.infoLog(ModuleName + " " + className, desc: #function) - let curTs = message.message?.timestamp ?? 0.0 - let model = QChatMessageFrame() - model.showTime = true - model.time = String.stringFromDate(date: Date(timeIntervalSince1970: curTs)) - model.showAvatar = false - model.cellHeight = 35 - return model - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatAuthManager.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatAuthManager.swift deleted file mode 100644 index 8f775b6e..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatAuthManager.swift +++ /dev/null @@ -1,51 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import AVFoundation -import Photos - -public typealias QChatAuthCompletion = (_ granted: Bool) -> Void - -@objc -public class QChatAuthManager: NSObject { - /// 查询相机授权 - @objc - public class func hasCameraAuthorization() -> Bool { - let state = AVCaptureDevice.authorizationStatus(for: .video) - return state == .authorized - } - - /// 请求相机权限 - /// @param completion 结果 - @objc - public class func requestCameraAuthorization(_ completion: QChatAuthCompletion?) { - AVCaptureDevice.requestAccess(for: .video) { granted in - DispatchQueue.main.async { - completion?(granted) - } - } - } - - /// 相册权限 - /// - Parameter completion: 结果 - class func photoAlbumPermissions(_ completion: QChatAuthCompletion?) { - let authStatus = PHPhotoLibrary.authorizationStatus() - // .notDetermined .authorized .restricted .denied - if authStatus == .notDetermined { - // 第一次触发授权 alert - PHPhotoLibrary.requestAuthorization { (status: PHAuthorizationStatus) in - self.photoAlbumPermissions(completion) - } - } else if authStatus == .authorized { - if completion != nil { - completion!(true) - } - } else { - if completion != nil { - completion!(false) - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatConstantValue.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatConstantValue.swift deleted file mode 100644 index 895acfab..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatConstantValue.swift +++ /dev/null @@ -1,31 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation - -// 距离cell边缘的距离 -public let qChat_cell_margin = 16.0 -// 控件之间的间距 -public let qChat_margin = 8.0 -// 头像宽高 -public let qChat_headWH = 32.0 -// 时间cell的高度(固定) -public let qChat_timeCellH = 21.0 - -// 图片最大宽高 -public let qChat_pic_size = CGSize(width: 150, height: 200) - -// 聊天小气泡角的宽度(后期扩展使用,目前默认为 0) -public let qChat_angle_w = 0.0 - -// 单行气泡高度 -public let qChat_min_h = 46.0 - -// 内容尾部距离cell边框的间距 -public let qChat_content_margin = 48.0 - -// 内容最大宽度 -public let qChat_content_maxW = - (kScreenWidth - qChat_headWH - qChat_cell_margin - qChat_content_margin - qChat_margin) diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatConstants.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatConstants.swift deleted file mode 100644 index 65292032..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Common/QChatConstants.swift +++ /dev/null @@ -1,104 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -@_exported import NECoreKit -@_exported import NECommonUIKit - -let coreLoader = CoreLoader() -func localizable(_ key: String) -> String { - coreLoader.localizable(key) -} - -func getJSONStringFromDictionary(_ dictionary: [String: Any]) -> String { - if !JSONSerialization.isValidJSONObject(dictionary) { - print("not parse to json string") - return "" - } - if let data = try? JSONSerialization.data(withJSONObject: dictionary, options: []), - let JSONString = String(data: data, encoding: .utf8) { - return JSONString - } - return "" -} - -func getDictionaryFromJSONString(_ jsonString: String) -> NSDictionary? { - if let jsonData = jsonString.data(using: .utf8), - let dict = try? JSONSerialization.jsonObject( - with: jsonData, - options: .mutableContainers - ) as? NSDictionary { - return dict - } - return nil -} - -@objc public protocol ViewModelDelegate: NSObjectProtocol { - func dataDidChange() - func dataDidError(_ error: Error) - @objc optional func dataNoMore() -} - -// MARK: 常量 - -let kScreenWidth: CGFloat = UIScreen.main.bounds.size.width -let kScreenHeight: CGFloat = UIScreen.main.bounds.size.height -let kUISreenWidthScale = kScreenWidth / 375.0 -let kUISreenHeightScale = kScreenHeight / 667.0 -let kNavigationHeight = 44.0 -let KStatusBarHeight = UIApplication.shared.statusBarFrame.height // 获取statusBar的高度 -/// 屏幕间隔 -let kScreenInterval: CGFloat = 20 - -// MARK: 字体 - -let TextFont: ((String, Float) -> UIFont) = { - (fontName: String, fontSize: Float) -> UIFont in - if #available(iOS 9.0, macOS 10,*) { - return UIFont(name: fontName, size: CGFloat(fontSize))! - } else { - return UIFont.systemFont(ofSize: CGFloat(fontSize)) - } -} - -let DefaultTextFont: ((Float) -> UIFont) = { - (fontSize: Float) -> UIFont in - TextFont("PingFangSC-Regular", fontSize) -} - -// MARK: 颜色 - -let TextNormalColor: UIColor = HexRGB(0x333333) -let SubTextColor: UIColor = HexRGB(0x666666) -let PlaceholderTextColor: UIColor = HexRGB(0xA6ADB6) - -let HexRGB: ((Int) -> UIColor) = { (rgbValue: Int) -> UIColor in - HexRGBAlpha(rgbValue, 1.0) -} - -let HexRGBAlpha: ((Int, Float) -> UIColor) = { (rgbValue: Int, alpha: Float) -> UIColor in - UIColor( - red: CGFloat(CGFloat((rgbValue & 0xFF0000) >> 16) / 255), - green: CGFloat(CGFloat((rgbValue & 0xFF00) >> 8) / 255), - blue: CGFloat(CGFloat(rgbValue & 0xFF) / 255), - alpha: CGFloat(alpha) - ) -} - -// MARK: notificationkey - -enum NotificationName { - // 参数 serverId: string - static let createServer = Notification.Name(rawValue: "qchat.createServer") - // param channel: ChatChannel - static let createChannel = Notification.Name(rawValue: "qchat.createChannel") - static let updateChannel = Notification.Name(rawValue: "qchat.updateChannel") - static let deleteChannel = Notification.Name(rawValue: "qchat.deleteChannel") - -// static let login = Notification.Name(rawValue:"qchat.login") - static let logout = Notification.Name(rawValue: "qchat.logout") -} - -public let ModuleName = "NEQChatUIKit" diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/AlertVCExtention.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Extension/AlertVCExtention.swift deleted file mode 100644 index be30513b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/AlertVCExtention.swift +++ /dev/null @@ -1,17 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -extension UIAlertController { - class func reconfimAlertView(title: String?, message: String?, - confirm: @escaping () -> Void) -> UIAlertController { - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: localizable("cancel"), style: .cancel, handler: nil)) - alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in - confirm() - }) - return alert - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/ColorExtension.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Extension/ColorExtension.swift deleted file mode 100644 index 46bae3db..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/ColorExtension.swift +++ /dev/null @@ -1,32 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import UIKit -public extension UIColor { -// MARK: text color - - static let ne_darkText = UIColor(hexString: "#333333") - static let ne_greyText = UIColor(hexString: "#666666") - static let ne_lightText = UIColor(hexString: "#999999") - static let ne_blueText = UIColor(hexString: "#337EFF") - static let ne_redText = UIColor(hexString: "#E6605C") - static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) - static let ne_backcolor = UIColor(hexString: "F2F4F5") - static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") - -// MARK: view background color - static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") - static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") - static let ne_greenColor = UIColor(hexString: "#42C294") - -// MARK: border color - static let ne_borderColor = UIColor(hexString: "#DBDDE4") - -// MARK: line color - static let ne_greyLine = UIColor(hexString: "#F5F8FC") - - static let ne_redColor = UIColor(hexString: "#F24957") -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/NEErrorExtension.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Extension/NEErrorExtension.swift deleted file mode 100644 index 25e9ae94..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/NEErrorExtension.swift +++ /dev/null @@ -1,15 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -extension NSError { - class func paramError() -> NSError { - NSError( - domain: "com.qchat.doamin", - code: 600, - userInfo: ["message": localizable("param_error")] - ) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/QChatImageExtension.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Extension/QChatImageExtension.swift deleted file mode 100644 index 7a727bf5..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/QChatImageExtension.swift +++ /dev/null @@ -1,25 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import CoreGraphics -import UIKit -public extension UIImage { - class func ne_imageNamed(name: String?) -> UIImage? { - guard let imageName = name else { - return nil - } - return coreLoader.loadImage(imageName) -// guard let path = Bundle(for: -// QChatBaseCell.self).resourcePath?.appending("/NEQChatUIKit.bundle") else { -// print("Image:\(imageName) path: nil") -// return nil -// } -// let image = UIImage(named: imageName, in: Bundle(path: path), compatibleWith: nil) -// print("Bundle:\(Bundle(path: path))") -// print("imageName:\(imageName) image:\(image)") -// return image - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/QChatStringExtension.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Extension/QChatStringExtension.swift deleted file mode 100644 index e2801047..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Extension/QChatStringExtension.swift +++ /dev/null @@ -1,43 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation - -extension String { - // 计算文字size - static func getTextRectSize(_ text: String, font: UIFont, size: CGSize) -> CGSize { - let attributes = [NSAttributedString.Key.font: font] - let option = NSStringDrawingOptions.usesLineFragmentOrigin - let rect: CGRect = text.boundingRect(with: size, options: option, - attributes: attributes, context: nil) - return rect.size - } - - static func stringFromDate(date: Date) -> String { - let fmt = DateFormatter() - if Calendar.current.isDateInToday(date) { - fmt.dateFormat = localizable("hm") - } else { - if let firstDayYear = firstDayInYear() { - let dur = date.timeIntervalSince(firstDayYear) - if dur > 0 { - fmt.dateFormat = localizable("mdhm") - } else { - fmt.dateFormat = localizable("ymdhm") - } - } else { - fmt.dateFormat = localizable("ymdhm") - } - } - return fmt.string(from: date) - } - - static func firstDayInYear() -> Date? { - let format = DateFormatter() - format.dateFormat = "yyyy-MM-dd" - let year = Calendar.current.component(.year, from: Date()) - return format.date(from: "\(year)-01-01") - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/CreateServerViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/CreateServerViewController.swift deleted file mode 100644 index dc0b4968..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/CreateServerViewController.swift +++ /dev/null @@ -1,86 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -public class CreateServerViewController: NEBaseViewController, UITableViewDelegate, - UITableViewDataSource { - public var serverViewModel = CreateServerViewModel() - - override public func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - setupSubviews() - } - - func initializeConfig() { - title = localizable("qchat_add_Server") - addLeftAction(localizable("close"), #selector(closeAction), self) - } - - func setupSubviews() { - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint( - equalTo: view.topAnchor, - constant: KStatusBarHeight + CGFloat(kNavigationHeight) + 52 - ), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - - private lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register( - NECreateServerCell.self, - forCellReuseIdentifier: "\(NSStringFromClass(NECreateServerCell.self))" - ) - tableView.rowHeight = 60 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - return tableView - }() - - @objc func closeAction(sender: UIButton) { - navigationController?.dismiss(animated: true, completion: nil) - } - - // MARK: UITableViewDelegate, UITableViewDataSource - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - serverViewModel.dataArray.count - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(NSStringFromClass(NECreateServerCell.self))", - for: indexPath - ) as! NECreateServerCell - let model = serverViewModel.dataArray[indexPath.row] - cell.model = model - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.row == 0 { - let mineCreateCtrl = MineCreateServerController() - navigationController?.pushViewController(mineCreateCtrl, animated: true) - } else if indexPath.row == 1 { - let otherCtrl = JoinOtherServiceController() - navigationController?.pushViewController(otherCtrl, animated: true) - } - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 76 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift deleted file mode 100644 index 5af2c620..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift +++ /dev/null @@ -1,234 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreKit -import NECoreIMKit -import NECommonKit -// import NEKeyboardManagerSwift - -public class JoinOtherServiceController: NEBaseViewController, UITableViewDelegate, - UITableViewDataSource { - private let tag = "JoinOtherServiceController" - public var serversArray = [QChatServer]() - public var serverViewModel = CreateServerViewModel() - public var channelViewModel = QChatChannelViewModel() - - override public func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - setupSubviews() - } - - func initializeConfig() { - title = localizable("qchat_join_otherServer") - NEKeyboardManager.shared.enableAutoToolbar = true - } - - func setupSubviews() { - view.addSubview(searchTextField) - view.addSubview(tableView) - NSLayoutConstraint.activate([ - searchTextField.topAnchor.constraint( - equalTo: view.topAnchor, - constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 20 - ), - searchTextField.leftAnchor.constraint( - equalTo: view.leftAnchor, - constant: kScreenInterval - ), - searchTextField.rightAnchor.constraint( - equalTo: view.rightAnchor, - constant: -kScreenInterval - ), - searchTextField.heightAnchor.constraint(equalToConstant: 32), - ]) - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: 20), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - - // MARK: lazyMethod - - private lazy var searchTextField: SearchTextField = { - let textField = SearchTextField() - - let image = UIImage(named: "otherService_search_icon", - in: Bundle(for: type(of: self)), - compatibleWith: nil) - let leftImageView = UIImageView(image: image) - textField.contentMode = .center - textField.leftView = leftImageView - textField.leftViewMode = .always - textField.placeholder = localizable("search_serverId") - textField.font = DefaultTextFont(14) - textField.textColor = TextNormalColor - textField.translatesAutoresizingMaskIntoConstraints = false - textField.layer.cornerRadius = 8 - textField.backgroundColor = HexRGB(0xEFF1F4) - textField.clearButtonMode = .whileEditing - textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingDidEnd) - textField.keyboardType = .numberPad - return textField - }() - - private lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register( - NESearchServerCell.self, - forCellReuseIdentifier: "\(NSStringFromClass(NESearchServerCell.self))" - ) - tableView.rowHeight = 60 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - return tableView - }() - - private lazy var emptyView: EmptyDataView = { - let view = EmptyDataView( - imageName: "searchServer_noMoreData", - content: localizable("no_serverId"), - frame: tableView.bounds - ) - return view - }() - - @objc func searchTextFieldChange(textfield: SearchTextField) { - // 选择高亮文本在进行搜索 - // let textRange = textfield.markedTextRange - // if textRange == nil || ((textRange?.isEmpty) == nil) { - // print("111") - // } - - if !NEChatDetectNetworkTool.shareInstance.isNetworkRecahability() { - showToast(localizable("network_error")) - return - } - - guard let content = textfield.text else { - return - } - // 空字符串判断 - if content.isBlank { - emptyView.removeFromSuperview() - return - } - - let param = QChatGetServersParam(serverIds: [NSNumber(value: UInt64(content)!)]) - serverViewModel.getServers(parameter: param) { error, serversArray in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK getServers " + (error?.localizedDescription ?? "no error") - ) - if error == nil { - self.serversArray = serversArray?.servers ?? Array() - if self.serversArray.isEmpty { - self.tableView.addSubview(self.emptyView) - return - } else { - self.emptyView.removeFromSuperview() - } - self.tableView.reloadData() - } else { - NELog.errorLog(ModuleName + " " + self.tag, desc: "❌getServers failed,error = \(error!)") - } - } - } - - // MARK: UITableViewDelegate UITableViewDataSource - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - serversArray.count - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(NSStringFromClass(NESearchServerCell.self))", - for: indexPath - ) as! NESearchServerCell - cell.serverModel = serversArray[indexPath.row] - weak var weakSelf = self - cell.joinServerCallBack = { - let successView = - InviteMemberView(frame: CGRect(x: (kScreenWidth - 176) / 2, y: KStatusBarHeight, - width: 176, height: 55)) - successView.showSuccessView() - } - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - guard let serverId = serversArray[indexPath.row].serverId else { return } - let param = QChatGetChannelsByPageParam(timeTag: 0, serverId: serverId) - weak var weakSelf = self - channelViewModel.getChannelsByPage(parameter: param) { error, result in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK getChannelsByPage " + (error?.localizedDescription ?? "no error") - ) - if error == nil { - guard let dataArray = result?.channels else { return } - let chatVC = QChatViewController(channel: dataArray.first) - weakSelf?.navigationController?.pushViewController(chatVC, animated: true) - } else { - print("getChannelsByPage failed,error = \(error!)") - } - } - } -} - -// MARK: private Method - -extension JoinOtherServiceController { - func showAlert() { - let alertCtrl = UIAlertController( - title: localizable("cant_join"), - message: localizable("blocked_from_server_cant_join"), - preferredStyle: .alert - ) - let okAction = UIAlertAction(title: localizable("know"), style: .default, handler: nil) - alertCtrl.addAction(okAction) - present(alertCtrl, animated: true, completion: nil) - } -} - -// MARK: SearchTextField - -// class SearchTextField:UITextField { -// -// override func leftViewRect(forBounds bounds: CGRect) -> CGRect { -// var rect = super.leftViewRect(forBounds: bounds) -// rect.origin.x += 10 -// return rect -// } -// -// override func placeholderRect(forBounds bounds: CGRect) -> CGRect { -// var rect = super.placeholderRect(forBounds: bounds) -// rect.origin.x += 1 -// return rect -// } -// -// override func editingRect(forBounds bounds: CGRect) -> CGRect { -// -// var rect = super.editingRect(forBounds: bounds) -// rect.origin.x += 5 -// return rect -// -// } -// -// override func textRect(forBounds bounds: CGRect) -> CGRect { -// var rect = super.textRect(forBounds: bounds) -// rect.origin.x += 5 -// return rect -// } -// } diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/MemberListViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/MemberListViewController.swift deleted file mode 100644 index fc8e2a06..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/MemberListViewController.swift +++ /dev/null @@ -1,154 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import NECoreKit -public class MemberListViewController: NEBaseViewController, UITableViewDelegate, - UITableViewDataSource { - public var serverViewModel = CreateServerViewModel() - public var memberViewModel = MemberListViewModel() - private let className = "MemberListViewController" - - var dataArray: [ServerMemeber]? - var serverId: UInt64? - - override public func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - requestData() - addSubviews() - // Do any additional setup after loading the view. - } - - func requestData() { - guard let id = serverId else { - print("serverId is nil") - return - } - let param = QChatGetServerMembersByPageParam(timeTag: 0, serverId: id) - weak var weakSelf = self - memberViewModel.requestServerMemebersByPage(param: param) { error, serverMemberArray in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK requestServerMemebersByPage " + - (error?.localizedDescription ?? "no error") - ) - if error == nil { - weakSelf?.dataArray = serverMemberArray - weakSelf?.tableView.reloadData() - } else {} - } - } - - func initializeConfig() { - title = localizable("qchat_member") - addRightAction(UIImage.ne_imageNamed(name: "sign_add"), #selector(addMemberClick), self) - } - - func addSubviews() { - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: view.topAnchor), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - - // MARK: lazy method - - private lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register( - NEGroupIdentityMemberCell.self, - forCellReuseIdentifier: "\(NSStringFromClass(NEGroupIdentityMemberCell.self))" - ) - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.estimatedRowHeight = 125 - return tableView - }() - - // MAKR: UITableViewDelegate, UITableViewDataSource - @objc func addMemberClick(sender: UIButton) { - Router.shared.register(ContactSelectedUsersRouter) { [weak self] param in - print("param\(param)") - if let userIds = param["accids"] as? [String] { - print("userIds:\(userIds)") - guard let serverId = self?.serverId else { return } - self?.serverViewModel - .inviteMembersToServer(serverId: serverId, accids: userIds) { error in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "MemberListViewController"), - desc: "CALLBACK inviteMembersToServer " + - (error?.localizedDescription ?? "no error") - ) - if error == nil { - self?.requestData() - } - } - } - } - - Router.shared - .use(ContactUserSelectRouter, - parameters: ["nav": navigationController]) { obj, routerState, str in - print("obj:\(obj) routerState:\(routerState) str:\(str)") - } - - // FIXME: router - // let contactCtrl = ContactsSelectedViewController() - // self.navigationController?.pushViewController(contactCtrl, animated: true) - // weak var weakSelf = self - // - // contactCtrl.CallBack = {(selectMemberarray)->Void in - // - // guard let serverId = weakSelf?.serverId else { return } - // var accidArray = [String]() - // selectMemberarray.forEach { memberInfo in - // accidArray.append(memberInfo.user?.userId ?? "") - // } - // weakSelf?.serverViewModel.inviteMembersToServer(serverId: serverId, accids: accidArray) { error in - // if error == nil{ - // weakSelf?.requestData() - // } - // } - // } - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - dataArray?.count ?? 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(NSStringFromClass(NEGroupIdentityMemberCell.self))", - for: indexPath - ) as! NEGroupIdentityMemberCell - cell.memberModel = dataArray?[indexPath.row] - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - // let user = viewModel.limitUsers[indexPath.row] - if let member = dataArray?[indexPath.row] { - let editMember = QChatEditMemberViewController() - editMember.deleteCompletion = { - self.requestData() - } - editMember.changeCompletion = { - self.requestData() - } - let user = UserInfo(member) - editMember.user = user - navigationController?.pushViewController(editMember, animated: true) - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/MineCreateServerController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/MineCreateServerController.swift deleted file mode 100644 index b74e4406..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/MineCreateServerController.swift +++ /dev/null @@ -1,239 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import NIMSDK -import NECommonKit - -public class MineCreateServerController: NEBaseViewController, UINavigationControllerDelegate, - UITextFieldDelegate { - private let tag = "MineCreateServerController" - public var serverViewModel = CreateServerViewModel() - var headImageUrl: String? - - override public func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - setupSubviews() - } - - func initializeConfig() { - title = localizable("qchat_mine_add") - } - - func setupSubviews() { - view.addSubview(uploadBgView) - uploadBgView.addSubview(cameraImageView) - uploadBgView.addSubview(uploadDesLabel) - view.addSubview(selectHeadImage) - view.addSubview(textField) - view.addSubview(bottomBtn) - - NSLayoutConstraint.activate([ - uploadBgView.centerXAnchor.constraint(equalTo: view.centerXAnchor), - uploadBgView.topAnchor.constraint( - equalTo: view.topAnchor, - constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 40 - ), - uploadBgView.widthAnchor.constraint(equalToConstant: 80), - uploadBgView.heightAnchor.constraint(equalToConstant: 80), - ]) - - NSLayoutConstraint.activate([ - selectHeadImage.centerXAnchor.constraint(equalTo: view.centerXAnchor), - selectHeadImage.topAnchor.constraint( - equalTo: view.topAnchor, - constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 40 - ), - selectHeadImage.widthAnchor.constraint(equalToConstant: 80), - selectHeadImage.heightAnchor.constraint(equalToConstant: 80), - ]) - NSLayoutConstraint.activate([ - cameraImageView.centerXAnchor.constraint(equalTo: uploadBgView.centerXAnchor), - cameraImageView.topAnchor.constraint(equalTo: uploadBgView.topAnchor, constant: 18), - ]) - - NSLayoutConstraint.activate([ - uploadDesLabel.centerXAnchor.constraint(equalTo: uploadBgView.centerXAnchor), - uploadDesLabel.topAnchor.constraint(equalTo: cameraImageView.bottomAnchor, constant: 9), - ]) - - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: kScreenInterval), - textField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -kScreenInterval), - textField.topAnchor.constraint(equalTo: uploadBgView.bottomAnchor, constant: 40), - textField.heightAnchor.constraint(equalToConstant: 40), - ]) - - NSLayoutConstraint.activate([ - bottomBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: kScreenInterval), - bottomBtn.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -kScreenInterval), - bottomBtn.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 40), - bottomBtn.heightAnchor.constraint(equalToConstant: 40), - ]) - } - - // MARK: lazyMethod - - private lazy var uploadBgView: UIButton = { - let button = UIButton() - button.setBackgroundImage(UIImage.ne_imageNamed(name: "uploadPic_bg_icon"), for: .normal) - button.setBackgroundImage( - UIImage.ne_imageNamed(name: "uploadPic_bg_icon"), - for: .highlighted - ) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(uploadBgViewClick), for: .touchUpInside) - return button - - }() - - private lazy var selectHeadImage: UIImageView = { - let imageView = UIImageView() - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.layer.cornerRadius = 40 - imageView.clipsToBounds = true - return imageView - }() - - private lazy var cameraImageView: UIImageView = { - let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "upload_camera")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - - private lazy var uploadDesLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("upload_headImage") - label.textColor = HexRGB(0x656A72) - label.font = DefaultTextFont(12) - return label - }() - - private lazy var textField: UITextField = { - let textField = UITextField() - textField.setValue(NSNumber(value: 10), forKey: "paddingLeft") - textField.placeholder = localizable("enter_serverName") - textField.font = DefaultTextFont(16) - textField.textColor = TextNormalColor - textField.translatesAutoresizingMaskIntoConstraints = false - textField.layer.cornerRadius = 8 - textField.backgroundColor = HexRGB(0xEFF1F4) - textField.delegate = self - textField.addTarget(self, action: #selector(textContentChanged), for: .editingChanged) - textField.clearButtonMode = .whileEditing - return textField - }() - - private lazy var bottomBtn: UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitle(localizable("create"), for: .normal) - button.setTitleColor(UIColor.white, for: .normal) - button.titleLabel?.font = DefaultTextFont(16) - button.backgroundColor = HexRGBAlpha(0x337EFF, 0.5) - button.layer.cornerRadius = 8 - button.addTarget(self, action: #selector(createServerBtnClick), for: .touchUpInside) - return button - }() - - @objc func createServerBtnClick(sender: UIButton) { - guard let serverName = textField.text, serverName.count > 0 else { return } - - if NEChatDetectNetworkTool.shareInstance.isNetworkRecahability() { - sender.isEnabled = false - } else { - showToast(localizable("network_error")) - return - } - - let param = CreateServerParam(name: textField.text!, icon: headImageUrl ?? "") - serverViewModel.createServer(parameter: param) { error, result in - if error != nil { - NELog.errorLog(ModuleName + " " + self.tag, desc: "❌createServer failed,error = \(error!)") - } else { - // 创建服务器成功后,默认创建好两个频道 - if let serverId = result?.server?.serverId { - NotificationCenter.default.post( - name: NotificationName.createServer, - object: serverId - ) - self.navigationController?.dismiss(animated: true, completion: nil) - } else { - print("serverId is nil") - return - } - } - } - // 应对wifi切换4G请求没有回调的处理结果 - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - sender.isEnabled = true - } - } - - // MARK: UITextFieldDelegate - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - let text = "\(textField.text ?? "")\(string)" - if text.count > 50 { - showToast(localizable("serverName_limit")) - return false - } - - return true - } - - // Upload the picture - @objc func uploadBgViewClick(sender: UIButton) { - showBottomAlert(self) - } - - @objc func textContentChanged() { - if textField.text?.count != 0 { - bottomBtn.isEnabled = true - bottomBtn.backgroundColor = HexRGB(0x337EFF) - } else { - bottomBtn.isEnabled = false - bottomBtn.backgroundColor = HexRGBAlpha(0x337EFF, 0.5) - } - } - - // MARK: UIImagePickerControllerDelegate - - func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [UIImagePickerController - .InfoKey: Any]) { - let image: UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage - uploadHeadImage(image: image) - dismiss(animated: true, completion: nil) - } - - public func uploadHeadImage(image: UIImage) { - view.makeToastActivity(.center) - if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { - let filePath = NSHomeDirectory().appending("/Documents/") - .appending(IMKitEngine.instance.imAccid) - let succcess = imageData.write(toFile: filePath, atomically: true) - - if succcess { - NIMSDK.shared().resourceManager - .upload(filePath, progress: nil) { urlString, error in - if error == nil { - // 显示设置的照片 - self.selectHeadImage.image = image - self.headImageUrl = urlString - print("upload image success") - } else { - print("upload image failed,error = \(error!)") - } - self.view.hideToastActivity() - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/QChatHomeViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/QChatHomeViewController.swift deleted file mode 100644 index 8da3e46f..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Controller/QChatHomeViewController.swift +++ /dev/null @@ -1,378 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import UIKit -import NECoreIMKit -import MJRefresh -import NIMSDK -import NEQChatKit -import NECommonUIKit -import NECommonKit - -public class QChatHomeViewController: UIViewController, ViewModelDelegate { - public var serverViewModel = CreateServerViewModel() - public var serverListArray = [QChatServer]() - fileprivate var selectIndex = 0 - private let className = "QChatHomeViewController" - - override public func viewWillAppear(_ animated: Bool) { - navigationController?.navigationBar.isHidden = true - } - - override public func viewWillDisappear(_ animated: Bool) { - navigationController?.navigationBar.isHidden = false - } - - override public func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - weak var weakSelf = self - NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in - if status == .notReachable, let networkView = weakSelf?.brokenNetworkView { - weakSelf?.qChatBgView.addSubview(networkView) - } else { - weakSelf?.brokenNetworkView.removeFromSuperview() - } - } - } - - override public func viewDidLoad() { - super.viewDidLoad() - serverViewModel.delegate = self - qChatBgView.viewmodel = serverViewModel - weak var weakSelf = self - serverViewModel.updateServerList = { - weakSelf?.tableView.reloadData() - } - initializeConfig() - addSubviews() - requestData(timeTag: 0) - addObserve() - } - - func initializeConfig() { - QChatSystemMessageProvider.shared.addDelegate(delegate: self) - } - - func addSubviews() { - view.addSubview(addServiceBtn) - view.addSubview(qChatBgView) - view.addSubview(tableView) - - NSLayoutConstraint.activate([ - addServiceBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 12), - addServiceBtn.widthAnchor.constraint(equalToConstant: 42), - addServiceBtn.heightAnchor.constraint(equalToConstant: 42), - addServiceBtn.topAnchor.constraint(equalTo: view.topAnchor, constant: 46), - ]) - NSLayoutConstraint.activate([ - qChatBgView.leftAnchor.constraint(equalTo: addServiceBtn.rightAnchor, constant: 12), - qChatBgView.topAnchor.constraint(equalTo: addServiceBtn.topAnchor), - qChatBgView.rightAnchor.constraint(equalTo: view.rightAnchor), - qChatBgView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: addServiceBtn.bottomAnchor, constant: 7), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: qChatBgView.leftAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - - func requestData(timeTag: TimeInterval) { - let param = GetServersByPageParam(timeTag: timeTag, limit: 20) - weak var weakSelf = self - serverViewModel.getServerList(parameter: param) { error, response in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK getServerList " + (error?.localizedDescription ?? "no error") - ) - if error == nil { - guard let dataArray = response?.servers else { return } - if timeTag == 0 { - self.serverListArray.removeAll() - self.serverListArray = dataArray - if let first = dataArray.first { - self.qChatBgView.qchatServerModel = first - self.qChatBgView.dismissEmptyView() - } else { - // 服务器列表为空 - self.qChatBgView.showEmptyServerView() - } - } else { - self.serverListArray += dataArray - } - - // 未读数入口 - weakSelf?.serverViewModel.getUnread(dataArray) - - self.tableView.reloadData() - } else { - print("getServerList failed,error = \(error!)") - } - } - } - - func addObserve() { - NotificationCenter.default.addObserver( - self, - selector: #selector(onCreateServer), - name: NotificationName.createServer, - object: nil - ) - NotificationCenter.default.addObserver( - self, - selector: #selector(onCreateChannel), - name: NotificationName.createChannel, - object: nil - ) - } - - // MARK: lazy method - - private lazy var addServiceBtn: UIButton = { - let btn = UIButton() - btn.setBackgroundImage(UIImage.ne_imageNamed(name: "addService_icon"), for: .normal) - btn.translatesAutoresizingMaskIntoConstraints = false - btn.addTarget(self, action: #selector(addServiceBtnClick), for: .touchUpInside) - return btn - }() - - private lazy var qChatBgView: NEHomeChannelView = { - let view = NEHomeChannelView() - view.translatesAutoresizingMaskIntoConstraints = false - weak var weakSelf = self - view.viewmodel = serverViewModel - view.setUpBlock = { () in - if weakSelf?.serverListArray.count == 0 { - return - } - if let index = weakSelf?.selectIndex, - let server = weakSelf?.serverListArray[index] { - let setting = QChatServerSettingViewController() - setting.server = server - setting.hidesBottomBarWhenPushed = true - weakSelf?.navigationController?.pushViewController(setting, animated: true) - } - } - - view.addChannelBlock = { [weak self] in - if self?.serverListArray.count ?? 0 > 0 { - let server = self?.serverListArray[self?.selectIndex ?? 0] - guard let serverId = server?.serverId, serverId > 0 else { - print("error: serverId:\(server?.serverId ?? 0)") - return - } - let nav = - QChatNavigationController( - rootViewController: QChatChannelViewController(serverId: serverId) - ) - nav.modalPresentationStyle = .fullScreen - weakSelf?.present(nav, animated: true, completion: nil) - } - } - - view.selectedChannelBlock = { [weak self] channel in - self?.enterChatVC(channel: channel) - } - return view - }() - - private lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.showsVerticalScrollIndicator = false - tableView.delegate = self - tableView.dataSource = self - tableView.register( - NEHomeServerCell.self, - forCellReuseIdentifier: "\(NSStringFromClass(NEHomeServerCell.self))" - ) - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.backgroundColor = HexRGB(0xE9EFF5) - let mjfooter = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) - mjfooter.stateLabel?.isHidden = true - tableView.mj_footer = mjfooter - return tableView - }() - - private lazy var brokenNetworkView: NEBrokenNetworkView = { - let view = - NEBrokenNetworkView(frame: CGRect(x: 0, y: 38, width: qChatBgView.width, height: 33)) - return view - }() -} - -extension QChatHomeViewController { - @objc func addServiceBtnClick(sender: UIButton) { - let nav = UINavigationController(rootViewController: CreateServerViewController()) - nav.modalPresentationStyle = .fullScreen - present(nav, animated: true, completion: nil) - } - - @objc func loadMoreData() { - if let time = serverListArray.last?.createTime { - requestData(timeTag: time) - } - tableView.mj_footer?.endRefreshing() - } -} - -// MARK: tableviewDelegate dataSource - -extension QChatHomeViewController: UITableViewDelegate, UITableViewDataSource { - public func dataDidChange() { - qChatBgView.tableView.reloadData() - } - - public func dataDidError(_ error: Error) {} - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - serverListArray.count - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(NSStringFromClass(NEHomeServerCell.self))", - for: indexPath - ) as! NEHomeServerCell - cell.showSelectState(isShow: indexPath.row == selectIndex ? true : false) - cell.serverModel = serverListArray[indexPath.row] - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let serverModel = serverListArray[indexPath.row] - qChatBgView.qchatServerModel = serverModel - serverViewModel.currentServerId = serverModel.serverId - selectIndex = indexPath.row - tableView.reloadData() - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 50 - } - -// MARK: action - - @objc func onCreateServer(noti: Notification) { - print("noti create server id:\(String(describing: noti.object))") - guard let serverId: UInt64 = noti.object as? UInt64 else { - return - } - - weak var weakSelf = self - let viewModel = QChatChannelViewModel(serverId: serverId) - viewModel.name = localizable("second_channel") - let className = className() - viewModel.createChannel { error, channel in - if error == nil { - NELog.infoLog(ModuleName + " " + className, desc: "✅CALLBACK second_channel create success") - viewModel.name = localizable("first_channel") - - viewModel.createChannel { error, channel in - if let err = error { - NELog.errorLog( - ModuleName + " " + className, - desc: "❌createChannel first_channel failed,error = \(err)" - ) - } else { - NELog.infoLog(ModuleName + " " + className, desc: "✅CALLBACK enter first channel success") - weakSelf?.enterChatVC(channel: channel) - } - } - } - } - } - - @objc func onCreateChannel(noti: Notification) { - // enter ChatVC - guard let channel = noti.object as? ChatChannel else { - return - } - enterChatVC(channel: channel) - } - - private func enterChatVC(channel: ChatChannel?) { - let chatVC = QChatViewController(channel: channel) - navigationController?.pushViewController(chatVC, animated: true) - } -} - -extension QChatHomeViewController: NIMQChatMessageManagerDelegate { - public func onRecvSystemNotification(_ result: NIMQChatReceiveSystemNotificationResult) { - result.systemNotifications?.forEach { systemNotification in - - switch systemNotification.type { - case .channelCreate, .channelRemove, .updateChannelCategoryBlackWhiteRole, - .channelUpdate: - self.channelChange(notificationInfo: systemNotification) - case .serverMemberKick, .serverMemberInviteDone: - - if systemNotification.fromAccount != IMKitEngine.instance.imAccid, - (systemNotification.toAccids?.contains(IMKitEngine.instance.imAccid)) != - nil { - self.requestData(timeTag: 0) - } - case .serverMemberApplyDone, .serverCreate, .serverRemove, .serverMemberLeave: - - if systemNotification.type == .serverRemove { - selectIndex = 0 - self.requestData(timeTag: 0) - } else { - if systemNotification.fromAccount == IMKitEngine.instance.imAccid { - selectIndex = 0 - self.requestData(timeTag: 0) - } - } - - case .serverUpdate: - // 刷新发生更新的cell - self.reloadUpdateCell(targetServerId: systemNotification.serverId) - default: - print("") - } - } - } - - private func reloadUpdateCell(targetServerId: UInt64) { - var targetIndex = 0 - for (index, serverModel) in serverListArray.enumerated() { - if targetServerId == serverModel.serverId { - targetIndex = index - break - } - } - - let indexPath = IndexPath(row: targetIndex, section: 0) - let param = QChatGetServersParam(serverIds: [NSNumber(value: targetServerId)]) - weak var weakSelf = self - serverViewModel.getServers(parameter: param) { error, result in - NELog.infoLog( - ModuleName + " " + self.className, - desc: "CALLBACK getServers " + (error?.localizedDescription ?? "no error") - ) - if let serverArray = result?.servers,!serverArray.isEmpty { - weakSelf?.serverListArray[targetIndex] = serverArray.first! - weakSelf?.tableView.reloadRows(at: [indexPath], with: .none) - - if targetIndex == weakSelf?.selectIndex { - weakSelf?.qChatBgView.qchatServerModel = serverArray.first! - } - } - } - } - - private func channelChange(notificationInfo: NIMQChatSystemNotification) { - qChatBgView.channelChange(noticeInfo: notificationInfo) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Model/AllChannelData.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Model/AllChannelData.swift deleted file mode 100644 index 4d1af5df..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Model/AllChannelData.swift +++ /dev/null @@ -1,57 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import NECoreIMKit - -protocol AllChannelDataDelegate: NSObjectProtocol { - func dataGetSuccess(_ serverId: UInt64, _ channels: [ChatChannel]) - func dataGetError(_ serverId: UInt64, _ error: Error) -} - -@objcMembers -public class AllChannelData: NSObject { - var repo = QChatRepo() - let limit = 200 - weak var delegate: AllChannelDataDelegate? - var serverId: UInt64 = 0 - var channelInfos = [ChatChannel]() - public var nextTimetag: TimeInterval = 0 - - init(sid: UInt64) { - super.init() - serverId = sid - getChannelData() - } - - func getChannelData() { - var param = QChatGetChannelsByPageParam(timeTag: nextTimetag, serverId: serverId) - param.limit = 200 - weak var weakSelf = self - repo.getChannelsByPage(param: param) { error, result in - if let err = error { - if let sid = weakSelf?.serverId { - weakSelf?.delegate?.dataGetError(sid, err) - } - } else { - if let datas = result?.channels { - weakSelf?.channelInfos.append(contentsOf: datas) - } - if let nextTimeTag = result?.nextTimetag { - weakSelf?.nextTimetag = nextTimeTag - } - if let hasMore = result?.hasMore, hasMore == true { - weakSelf?.getChannelData() - } else { - print("getChannelData finish : ", weakSelf?.serverId as Any) - if let sid = weakSelf?.serverId, let channels = weakSelf?.channelInfos { - weakSelf?.delegate?.dataGetSuccess(sid, channels) - } - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Model/ServerMemberModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Model/ServerMemberModel.swift deleted file mode 100644 index 9986b183..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/Model/ServerMemberModel.swift +++ /dev/null @@ -1,15 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -// 服务器下成员列表数据模型 -@objcMembers -public class ServerMemberModel: NSObject { - public var serverMemberModel: ServerMemeber? - public var imName: String? - public var idGroupData: [String]? -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/EmptyDataView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/EmptyDataView.swift deleted file mode 100644 index 2c00f3bd..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/EmptyDataView.swift +++ /dev/null @@ -1,69 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. -import UIKit - -class EmptyDataView: UIView { - private var imageName: String? - private var content: String? - - public init(imageName: String, content: String, frame: CGRect) { - self.imageName = imageName - self.content = content - super.init(frame: frame) - setupSubviews() - setupSubviewStyle() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - backgroundColor = .white - addSubview(emptyImageView) - addSubview(contentLabel) - - NSLayoutConstraint.activate([ - emptyImageView.topAnchor.constraint(equalTo: topAnchor, constant: 176), - emptyImageView.centerXAnchor.constraint(equalTo: centerXAnchor), - emptyImageView.widthAnchor.constraint(equalToConstant: 122), - emptyImageView.heightAnchor.constraint(equalToConstant: 91), - ]) - - NSLayoutConstraint.activate([ - contentLabel.topAnchor.constraint(equalTo: emptyImageView.bottomAnchor, constant: 8), - contentLabel.centerXAnchor.constraint(equalTo: centerXAnchor), - ]) - } - - func setupSubviewStyle() { - emptyImageView.image = UIImage.ne_imageNamed(name: imageName) - contentLabel.text = content - } - - private lazy var emptyImageView: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - return avatar - }() - - private lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_emptyTitleColor - label.font = DefaultTextFont(14) - label.numberOfLines = 0 - label.textAlignment = .center - return label - }() - - public func setttingContent(content: String) { - contentLabel.text = content - } - - public func setEmptyImage(name: String) { - emptyImageView.image = UIImage.ne_imageNamed(name: name) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/InviteMemberView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/InviteMemberView.swift deleted file mode 100644 index 9795bead..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/InviteMemberView.swift +++ /dev/null @@ -1,60 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class InviteMemberView: UIView { - override init(frame: CGRect) { - super.init(frame: frame) - addSubview(content) - addSubview(successImageView) - layer.cornerRadius = 26 - layer.borderWidth = 1 - layer.borderColor = HexRGB(0xE3E3E3).cgColor - layer.masksToBounds = true - backgroundColor = .white - - NSLayoutConstraint.activate([ - successImageView.leftAnchor.constraint(equalTo: leftAnchor, constant: kScreenInterval), - successImageView.centerYAnchor.constraint(equalTo: centerYAnchor), - successImageView.widthAnchor.constraint(equalToConstant: kScreenInterval), - successImageView.heightAnchor.constraint(equalToConstant: kScreenInterval), - ]) - - NSLayoutConstraint.activate([ - content.leftAnchor.constraint(equalTo: successImageView.rightAnchor, constant: 6), - content.centerYAnchor.constraint(equalTo: successImageView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func showSuccessView() { - let window = UIApplication.shared.keyWindow - window?.addSubview(self) - DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { - self.removeFromSuperview() - } - } - - // MARK: lazyMethod - - private lazy var content: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("request_sended") - label.font = DefaultTextFont(16) - label.textColor = UIColor.ne_darkText - return label - }() - - private lazy var successImageView: UIImageView = { - let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "invitemember_success")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NECreateServerCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NECreateServerCell.swift deleted file mode 100644 index bd667bd6..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NECreateServerCell.swift +++ /dev/null @@ -1,108 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class NECreateServerCell: UITableViewCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - setupSubviews() - } - - var model: (image: String, title: String)? { - didSet { - headImageView.image = UIImage.ne_imageNamed(name: model?.image) - content.text = model?.title - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - contentView.addSubview(serviceBgView) - serviceBgView.addSubview(headImageView) - serviceBgView.addSubview(content) - serviceBgView.addSubview(arrowImageView) - - NSLayoutConstraint.activate([ - serviceBgView.leftAnchor.constraint( - equalTo: contentView.leftAnchor, - constant: kScreenInterval - ), - serviceBgView.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -kScreenInterval - ), - serviceBgView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), - serviceBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8), - ]) - - NSLayoutConstraint.activate([ - headImageView.leftAnchor.constraint(equalTo: serviceBgView.leftAnchor, constant: 16), - headImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - headImageView.widthAnchor.constraint(equalToConstant: 36), - headImageView.heightAnchor.constraint(equalToConstant: 36), - ]) - - NSLayoutConstraint.activate([ - arrowImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - arrowImageView.rightAnchor.constraint( - equalTo: serviceBgView.rightAnchor, - constant: -kScreenInterval - ), - arrowImageView.widthAnchor.constraint(equalToConstant: 5), - ]) - - NSLayoutConstraint.activate([ - content.leftAnchor.constraint(equalTo: headImageView.rightAnchor, constant: 16), - content.centerYAnchor.constraint(equalTo: headImageView.centerYAnchor), - content.rightAnchor.constraint(equalTo: arrowImageView.leftAnchor, constant: -16), - ]) - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - // MARK: lazyMethod - - private lazy var serviceBgView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = HexRGB(0xEFF1F4) - view.layer.cornerRadius = 8 - return view - }() - - private lazy var headImageView: UIImageView = { - let imageView = UIImageView() - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - - private lazy var content: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(16) - label.textColor = TextNormalColor - return label - }() - - private lazy var arrowImageView: UIImageView = { - let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift deleted file mode 100644 index b61c0b9b..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift +++ /dev/null @@ -1,282 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import MapKit -import NECoreIMKit -class NEGroupIdentityMemberCell: UITableViewCell { - var dataArray = [String]() - - var maxWidth: CGFloat = kScreenWidth - 2 * kScreenInterval - var labelMargin: CGFloat = 6 - var labelHeight: CGFloat = 25 - var isFirstRow = true - var titleTopConstraint: NSLayoutConstraint? - - public var memberModel: ServerMemeber? { - didSet { - guard let model = memberModel else { return } - - if let imageName = model.avatar,!imageName.isEmpty { - avatarImage.sd_setImage(with: URL(string: imageName), completed: nil) - avatarImage.setTitle("") - } else { - if let name = model.nick,!name.isEmpty { - avatarImage.setTitle(name) - } else { - avatarImage.setTitle(model.accid ?? "") - } - avatarImage.backgroundColor = .colorWithString(string: memberModel?.accid) - } - var labelContentArray = [String]() - memberModel?.roles?.forEach { roleModel in - labelContentArray.append(roleModel.name ?? "") - } - self.dataArray = labelContentArray - setupSubviews() - - if let nick = model.nick,!nick.isEmpty { - titleLabel.text = nick - subTitleLabel.text = model.accid - titleTopConstraint?.constant = 14 - } else { - titleLabel.text = model.accid - subTitleLabel.text = "" - titleTopConstraint?.constant = 22 - } - } - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - } - - override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ rect: CGRect) { - avatarImage.addCorner(conrners: .allCorners, radius: 18) - } - - func setupSubviews() { - contentView.addSubview(avatarImage) - contentView.addSubview(titleLabel) - contentView.addSubview(subTitleLabel) - contentView.addSubview(arrowImageView) - contentView.addSubview(labelContainerView) - contentView.addSubview(lineView) - - NSLayoutConstraint.activate([ - avatarImage.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12), - avatarImage.leftAnchor.constraint( - equalTo: contentView.leftAnchor, - constant: kScreenInterval - ), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36), - ]) - - titleTopConstraint = titleLabel.topAnchor.constraint( - equalTo: contentView.topAnchor, - constant: 14 - ) - titleTopConstraint?.isActive = true - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 12), - ]) - - NSLayoutConstraint.activate([ - subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor), - subTitleLabel.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), - ]) - - NSLayoutConstraint.activate([ - arrowImageView.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), - arrowImageView.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -labelHeight - ), - ]) - - NSLayoutConstraint.activate([ - labelContainerView.topAnchor.constraint(equalTo: avatarImage.bottomAnchor, constant: 8), - labelContainerView.leftAnchor.constraint(equalTo: contentView.leftAnchor), - labelContainerView.rightAnchor.constraint(equalTo: contentView.rightAnchor), - labelContainerView.bottomAnchor.constraint( - equalTo: contentView.bottomAnchor, - constant: -10 - ), - ]) - - // 移除contentview上复用的label - labelContainerView.subviews.forEach { label in - label.removeFromSuperview() - } - var labelsWidth: CGFloat = 0 - for i in 0 ..< dataArray.count { - let label = IDGroupLabel(content: dataArray[i]) - label.textInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8) - label.translatesAutoresizingMaskIntoConstraints = false - labelContainerView.addSubview(label) - let labelSize = label.sizeThatFits(CGSize(width: maxWidth, height: labelHeight)) - - // 剩余宽度是否满足,下一个label的宽度,如不满足则换行 - if (maxWidth - labelsWidth) >= labelSize.width, isFirstRow { - NSLayoutConstraint.activate([ - i == 0 ? label.leftAnchor.constraint( - equalTo: labelContainerView.leftAnchor, - constant: kScreenInterval - ) : label.leftAnchor.constraint( - equalTo: labelContainerView.leftAnchor, - constant: kScreenInterval + labelsWidth - ), - label.topAnchor.constraint(equalTo: labelContainerView.topAnchor, constant: 8), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant: labelSize.height), - ]) - } else { - // 换行重置,labels总宽度 - if isFirstRow { - labelsWidth = kScreenInterval - } - isFirstRow = false - NSLayoutConstraint.activate([ - label.leftAnchor.constraint( - equalTo: labelContainerView.leftAnchor, - constant: labelsWidth - ), - label.topAnchor.constraint( - equalTo: labelContainerView.topAnchor, - constant: 8 + labelHeight + labelMargin - ), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant: labelSize.height), - ]) - } - - if i == dataArray.count - 1 { - NSLayoutConstraint.activate([ - label.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor), - ]) - } - labelsWidth += (labelSize.width + labelMargin) - } - - NSLayoutConstraint.activate([ - lineView.topAnchor.constraint(equalTo: labelContainerView.bottomAnchor, constant: 12), - lineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - lineView.rightAnchor.constraint(equalTo: contentView.rightAnchor), - lineView.heightAnchor.constraint(equalToConstant: 1), - lineView.leftAnchor.constraint( - equalTo: contentView.leftAnchor, - constant: kScreenInterval - ), - ]) - } - - lazy var avatarImage: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(14) - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var titleLabel: UILabel = { - let name = UILabel() - name.translatesAutoresizingMaskIntoConstraints = false - name.textColor = .ne_darkText - name.font = DefaultTextFont(14) - return name - }() - - private lazy var subTitleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = UIColor.ne_emptyTitleColor - return label - }() - - private lazy var labelContainerView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var lineView: UIView = { - let view = UIView() - view.backgroundColor = .ne_greyLine - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var arrowImageView: UIImageView = { - let arrow = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) - arrow.translatesAutoresizingMaskIntoConstraints = false - return arrow - }() -} - -class IDGroupLabel: UILabel { - private var content: String? - - init(content: String) { - super.init(frame: CGRect.zero) - self.content = content - setupStyle() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ rect: CGRect) { - super.draw(rect) - addCorner(conrners: .allCorners, radius: 4) - } - - func setupStyle() { - font = DefaultTextFont(12) - textColor = HexRGB(0x656A72) - backgroundColor = HexRGB(0xF2F4F5) - text = content - } - - // 定义一个接受间距的属性 - var textInsets = UIEdgeInsets.zero - - // 返回 label 重新计算过 text 的 rectangle - override func textRect(forBounds bounds: CGRect, - limitedToNumberOfLines numberOfLines: Int) -> CGRect { - guard text != nil else { - return super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines) - } - - let insetRect = bounds.inset(by: textInsets) - let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) - let invertedInsets = UIEdgeInsets(top: -textInsets.top, - left: -textInsets.left, - bottom: -textInsets.bottom, - right: -textInsets.right) - return textRect.inset(by: invertedInsets) - } - - // 3. 绘制文本时,对当前 rectangle 添加间距 - override func drawText(in rect: CGRect) { - super.drawText(in: rect.inset(by: textInsets)) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeChannelCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeChannelCell.swift deleted file mode 100644 index 9747d56f..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeChannelCell.swift +++ /dev/null @@ -1,92 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -class NEHomeChannelCell: UITableViewCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - public var channelModel: ChatChannel? { - didSet { - guard var name = channelModel?.name else { return } - name = "# \(name)" - let attrStr = NSMutableAttributedString(string: name) - attrStr.addAttribute( - NSAttributedString.Key.foregroundColor, - value: PlaceholderTextColor, - range: NSRange(location: 0, length: 1) - ) - attrStr.addAttribute( - NSAttributedString.Key.foregroundColor, - value: TextNormalColor, - range: NSRange(location: 1, length: name.count - 1) - ) - channelNameLabel.attributedText = attrStr - } - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - contentView.addSubview(channelNameLabel) - contentView.addSubview(redAngleView) - - NSLayoutConstraint.activate([ - channelNameLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 18), - channelNameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - channelNameLabel.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -50 - ), - - ]) - - NSLayoutConstraint.activate([ - redAngleView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -18), - redAngleView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - redAngleView.heightAnchor.constraint(equalToConstant: 18), - ]) - } - - private lazy var channelNameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(16) - label.textColor = TextNormalColor - return label - }() - - lazy var redAngleView: RedAngleLabel = { - let label = RedAngleLabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = .white - label.text = "99+" - label.backgroundColor = HexRGB(0xF24957) - label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) - label.layer.cornerRadius = 9 - label.clipsToBounds = true - label.isHidden = true - return label - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeChannelView.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeChannelView.swift deleted file mode 100644 index 5376a6e8..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeChannelView.swift +++ /dev/null @@ -1,319 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import MJRefresh -import NIMSDK - -class NEHomeChannelView: UIView { - private let className = "NEHomeChannelView" - typealias CallBack = () -> Void - typealias SelectedChannelBlock = (_ channel: ChatChannel?) -> Void - public var channelViewModel = QChatChannelViewModel() - public var channelArray = [ChatChannel]() - - public var setUpBlock: CallBack? - public var addChannelBlock: CallBack? - public var selectedChannelBlock: SelectedChannelBlock? - public var hasMore = true - public var nextTimeTag: TimeInterval = 0 - - public var viewmodel: CreateServerViewModel? - - public var qchatServerModel: QChatServer? { - didSet { - hasMore = true - nextTimeTag = 0 - self.titleLabel.text = qchatServerModel?.name - channelArray.removeAll() - requestData(timeTag: 0) - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ rect: CGRect) { - addCorner(conrners: [.topLeft, .topRight], radius: 8) - } - - func setupSubviews() { - backgroundColor = .white - - addSubview(titleLabel) - addSubview(setUpBtn) - addSubview(divideLineView) - addSubview(addChannelBtn) - addSubview(subTitleLable) - addSubview(tableView) - addSubview(emptyView) - - NSLayoutConstraint.activate([ - titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 16), - titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 12), - titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -30), - - ]) - - NSLayoutConstraint.activate([ - setUpBtn.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor), - setUpBtn.rightAnchor.constraint(equalTo: rightAnchor, constant: -16), - ]) - - NSLayoutConstraint.activate([ - divideLineView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 16), - divideLineView.leftAnchor.constraint(equalTo: leftAnchor, constant: 12), - divideLineView.rightAnchor.constraint(equalTo: rightAnchor, constant: -12), - divideLineView.heightAnchor.constraint(equalToConstant: 1), - ]) - - NSLayoutConstraint.activate([ - subTitleLable.topAnchor.constraint(equalTo: divideLineView.bottomAnchor, constant: 16), - subTitleLable.leftAnchor.constraint(equalTo: leftAnchor, constant: 18), - ]) - - NSLayoutConstraint.activate([ - addChannelBtn.centerYAnchor.constraint(equalTo: subTitleLable.centerYAnchor), - addChannelBtn.rightAnchor.constraint(equalTo: rightAnchor, constant: -15), - ]) - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: subTitleLable.bottomAnchor, constant: 8), - tableView.leftAnchor.constraint(equalTo: leftAnchor), - tableView.rightAnchor.constraint(equalTo: rightAnchor), - tableView.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - - NSLayoutConstraint.activate([ - emptyView.topAnchor.constraint(equalTo: subTitleLable.bottomAnchor, constant: 8), - emptyView.leftAnchor.constraint(equalTo: leftAnchor), - emptyView.rightAnchor.constraint(equalTo: rightAnchor), - emptyView.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - } - - @objc func updateChannelList() { - requestData(timeTag: 0) - } - - public func channelChange(noticeInfo: NIMQChatSystemNotification) { - switch noticeInfo.type { - case .channelRemove, .channelCreate, .channelUpdate: - if noticeInfo.serverId == qchatServerModel?.serverId { - requestData(timeTag: 0) - } - case .updateChannelCategoryBlackWhiteRole: - if noticeInfo.serverId == qchatServerModel?.serverId, - (noticeInfo.toAccids?.contains(IMKitEngine.instance.imAccid)) != nil { - requestData(timeTag: 0) - } - - default: - print("") - } - } - - // MARK: lazy method - - private lazy var titleLabel: UILabel = { - let title = UILabel() - title.translatesAutoresizingMaskIntoConstraints = false - title.textColor = UIColor.ne_darkText - title.font = UIFont.systemFont(ofSize: 16.0, weight: .medium) - return title - }() - - private lazy var setUpBtn: ExpandButton = { - let button = ExpandButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(UIImage.ne_imageNamed(name: "home_setupServer"), for: .normal) - button.setImage(UIImage.ne_imageNamed(name: "home_setupServer"), for: .highlighted) - button.addTarget(self, action: #selector(setupBtnClick), for: .touchUpInside) - return button - }() - - private lazy var divideLineView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = UIColor.ne_greyLine - return view - }() - - private lazy var subTitleLable: UILabel = { - let title = UILabel() - title.translatesAutoresizingMaskIntoConstraints = false - title.text = localizable("message_channel") - title.textColor = PlaceholderTextColor - title.font = DefaultTextFont(14) - return title - }() - - private lazy var addChannelBtn: UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(UIImage.ne_imageNamed(name: "home_addChannel"), for: .normal) - button.setImage(UIImage.ne_imageNamed(name: "home_addChannel"), for: .highlighted) - button.addTarget(self, action: #selector(addChannelBtnClick), for: .touchUpInside) - return button - }() - - lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register( - NEHomeChannelCell.self, - forCellReuseIdentifier: "\(NSStringFromClass(NEHomeChannelCell.self))" - ) - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - let mjfooter = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) - mjfooter.stateLabel?.isHidden = true - tableView.mj_footer = mjfooter - return tableView - }() - - private lazy var emptyView: EmptyDataView = { - let view = EmptyDataView( - imageName: "channel_noMoreData", - content: localizable("server_nochannel"), - frame: tableView.bounds - ) - view.translatesAutoresizingMaskIntoConstraints = false - view.isHidden = true - return view - }() -} - -extension NEHomeChannelView { - @objc func setupBtnClick(sender: UIButton) { - if setUpBlock != nil { - setUpBlock!() - } - } - - @objc func addChannelBtnClick(sender: UIButton) { - if addChannelBlock != nil { - addChannelBlock!() - } - } - - @objc func loadMoreData() { - requestData(timeTag: nextTimeTag) - tableView.mj_footer?.endRefreshing() - } - - public func requestData(timeTag: TimeInterval) { - if timeTag != 0, !hasMore { - // 上拉加载无多余数据,无需请求 - return - } - - guard let serverId = qchatServerModel?.serverId else { return } - let param = QChatGetChannelsByPageParam(timeTag: timeTag, serverId: serverId) - channelViewModel.getChannelsByPage(parameter: param) { [self] error, result in - if error == nil { - NELog.infoLog(self.className, desc: "✅CALLBACK getChannelsByPage SUCCESS") - guard let dataArray = result?.channels else { return } - if timeTag == 0 { - self.channelArray.removeAll() - self.channelArray = dataArray - if dataArray.isEmpty { - emptyView.setttingContent(content: localizable("server_nochannel")) - emptyView.setEmptyImage(name: "channel_noMoreData") - emptyView.isHidden = false - } else { - emptyView.isHidden = true - } - - } else { - self.channelArray += dataArray - } - self.hasMore = result?.hasMore ?? false - self.nextTimeTag = result?.nextTimetag ?? 0 - tableView.reloadData() - } else { - NELog.errorLog(self.className, desc: "❌CALLBACK getChannelsByPage failed,error = \(error!)") - } - } - } - - public func showEmptyServerView() { - titleLabel.isHidden = true - setUpBtn.isHidden = true - divideLineView.isHidden = true - subTitleLable.isHidden = true - addChannelBtn.isHidden = true - emptyView.isHidden = false - emptyView.setttingContent(content: localizable("add_favorite_service")) - emptyView.setEmptyImage(name: "servers_noMore") - } - - public func dismissEmptyView() { - titleLabel.isHidden = false - setUpBtn.isHidden = false - divideLineView.isHidden = false - subTitleLable.isHidden = false - addChannelBtn.isHidden = false - emptyView.isHidden = true - } -} - -extension NEHomeChannelView: UITableViewDataSource, UITableViewDelegate { - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - channelArray.count - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell( - withIdentifier: "\(NSStringFromClass(NEHomeChannelCell.self))", - for: indexPath - ) as! NEHomeChannelCell - if indexPath.row < channelArray.count { - let channel = channelArray[indexPath.row] - cell.channelModel = channel - if let sid = qchatServerModel?.serverId, let cid = channel.channelId, - let unreadCount = viewmodel?.getChannelUnreadCount( - sid, - cid - ) { - cell.redAngleView.isHidden = false - if unreadCount <= 0 { - cell.redAngleView.isHidden = true - } else if unreadCount <= 99 { - cell.redAngleView.text = "\(unreadCount)" - } else { - cell.redAngleView.text = "99+" - } - } else { - cell.redAngleView.isHidden = true - } - } - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let block = selectedChannelBlock, channelArray.count > 0 { - block(channelArray[indexPath.row]) - } - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 36 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeServerCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeServerCell.swift deleted file mode 100644 index cdcdd667..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEHomeServerCell.swift +++ /dev/null @@ -1,120 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit -import NECoreKit -class NEHomeServerCell: UITableViewCell { - lazy var redDot: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = .ne_redColor - view.clipsToBounds = true - view.layer.cornerRadius = 4.0 - view.layer.borderColor = UIColor.white.cgColor - view.layer.borderWidth = 1 - view.isHidden = true - return view - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - public var serverModel: QChatServer? { - didSet { - if let imageUrl = serverModel?.icon { - headView.sd_setImage(with: URL(string: imageUrl), completed: nil) - headView.setTitle("") - } else { - if let name = serverModel?.name { - headView.setTitle(name) - } - headView.sd_setImage(with: URL(string: ""), completed: nil) - headView.backgroundColor = .colorWithNumber(number: serverModel?.serverId) - } - - if let hasUnread = serverModel?.hasUnread { - redDot.isHidden = !hasUnread - } - } - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - contentView.backgroundColor = HexRGB(0xE9EFF5) - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - contentView.addSubview(leftSelectView) - contentView.addSubview(headView) - - NSLayoutConstraint.activate([ - headView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 12), - headView.topAnchor.constraint(equalTo: contentView.topAnchor), - headView.widthAnchor.constraint(equalToConstant: 42), - headView.heightAnchor.constraint(equalToConstant: 42), - ]) - - NSLayoutConstraint.activate([ - leftSelectView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: -4), - leftSelectView.topAnchor.constraint(equalTo: contentView.topAnchor), - leftSelectView.widthAnchor.constraint(equalToConstant: 8), - leftSelectView.heightAnchor.constraint(equalToConstant: 36), - ]) - - contentView.addSubview(redDot) - let factor = cos(45 * Double.pi / 180) - let x = 12 + 21 * factor + 21 - let y = 21 - 21 * factor - NSLayoutConstraint.activate([ - redDot.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: x), - redDot.topAnchor.constraint(equalTo: contentView.topAnchor, constant: y), - redDot.widthAnchor.constraint(equalToConstant: 8), - redDot.heightAnchor.constraint(equalToConstant: 8), - ]) - } - - override func draw(_ rect: CGRect) { - super.draw(rect) - headView.addCorner(conrners: .allCorners, radius: 21) - } - - // MARK: lazy method - - private lazy var leftSelectView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = HexRGB(0x337EFF) - view.layer.cornerRadius = 4 - view.isHidden = true - return view - }() - - lazy var headView: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(14) - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - public func showSelectState(isShow: Bool) { - leftSelectView.isHidden = isShow ? false : true - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEMemberListCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEMemberListCell.swift deleted file mode 100644 index d0b6cfdf..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NEMemberListCell.swift +++ /dev/null @@ -1,87 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class NEMemberListCell: UITableViewCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - contentView.addSubview(avatarImage) - contentView.addSubview(contentLabel) - contentView.addSubview(arrowImage) - contentView.addSubview(lineView) - - NSLayoutConstraint.activate([ - avatarImage.leftAnchor.constraint( - equalTo: contentView.leftAnchor, - constant: kScreenInterval - ), - avatarImage.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36), - ]) - - NSLayoutConstraint.activate([ - lineView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - lineView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - lineView.heightAnchor.constraint(equalToConstant: 1.0), - lineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) - - NSLayoutConstraint.activate([ - arrowImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -32), - arrowImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } - - private lazy var avatarImage: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.backgroundColor = .ne_defautAvatarColor - return avatar - }() - - private lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = TextNormalColor - label.font = DefaultTextFont(14) - return label - }() - - private lazy var lineView: UIView = { - let line = UIView() - line.translatesAutoresizingMaskIntoConstraints = false - line.backgroundColor = .ne_greyLine - return line - }() - - private lazy var arrowImage: UIImageView = { - let arrow = UIImageView() - arrow.translatesAutoresizingMaskIntoConstraints = false - arrow.image = UIImage.ne_imageNamed(name: "") - return arrow - }() -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NESearchServerCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NESearchServerCell.swift deleted file mode 100644 index 23e57c0d..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/View/NESearchServerCell.swift +++ /dev/null @@ -1,236 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -class NESearchServerCell: UITableViewCell { - typealias CallBack = (() -> Void)? - @objc var joinServerCallBack: CallBack = nil - public var serverViewModel = CreateServerViewModel() - private let className = "NESearchServerCell" - - public var serverModel: QChatServer? { - didSet { - if let imageUrl = serverModel?.icon { - headImageView.sd_setImage(with: URL(string: imageUrl), completed: nil) - headImageView.setTitle("") - } else { - if let name = serverModel?.name { - headImageView.setTitle(name) - } - headImageView.sd_setImage(with: URL(string: ""), completed: nil) - headImageView.backgroundColor = .colorWithNumber(number: serverModel?.serverId) - } - - self.content.text = serverModel?.name - - guard let serverId = serverModel?.serverId else { - return - } - self.subContent.text = "\(serverId)" - - let item = QChatGetServerMemberItem( - serverId: serverId, - accid: IMKitEngine.instance.imAccid - ) - let param = QChatGetServerMembersParam(serverAccIds: [item]) - - serverViewModel.getServerMemberList(parameter: param) { error, membersResult in - NELog.infoLog( - self.className, - desc: "CALLBACK getServerMemberList " + (error?.localizedDescription ?? "no error") - ) - if error == nil { - guard let dataArray = membersResult?.memberArray else { return } - if dataArray.isEmpty { - self.rightContent.isHidden = true - self.joinBtn.isHidden = false - } else { - self.rightContent.isHidden = false - self.joinBtn.isHidden = true - } - } else { - print("getServerMemberList failed,error = \(error!)") - } - } - } - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ rect: CGRect) { - serviceBgView.addCorner(conrners: .allCorners, radius: 8) - headImageView.addCorner(conrners: .allCorners, radius: 18) - } - - func setupSubviews() { - contentView.addSubview(serviceBgView) - serviceBgView.addSubview(headImageView) - serviceBgView.addSubview(content) - serviceBgView.addSubview(subContent) - serviceBgView.addSubview(rightContent) - serviceBgView.addSubview(rightContentImageView) - serviceBgView.addSubview(joinBtn) - - NSLayoutConstraint.activate([ - serviceBgView.leftAnchor.constraint( - equalTo: contentView.leftAnchor, - constant: kScreenInterval - ), - serviceBgView.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -kScreenInterval - ), - serviceBgView.topAnchor.constraint(equalTo: contentView.topAnchor), - serviceBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -6), - ]) - - NSLayoutConstraint.activate([ - headImageView.leftAnchor.constraint(equalTo: serviceBgView.leftAnchor, constant: 16), - headImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - headImageView.widthAnchor.constraint(equalToConstant: 36), - headImageView.heightAnchor.constraint(equalToConstant: 36), - ]) - - NSLayoutConstraint.activate([ - subContent.leftAnchor.constraint(equalTo: content.leftAnchor), - subContent.bottomAnchor.constraint(equalTo: headImageView.bottomAnchor), - ]) - - NSLayoutConstraint.activate([ - rightContent.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - rightContent.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor, constant: -16), - ]) - - NSLayoutConstraint.activate([ - rightContentImageView.centerYAnchor.constraint(equalTo: rightContent.centerYAnchor), - rightContentImageView.rightAnchor.constraint( - equalTo: serviceBgView.rightAnchor, - constant: 16 - ), - ]) - - NSLayoutConstraint.activate([ - joinBtn.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - joinBtn.widthAnchor.constraint(equalToConstant: 56), - joinBtn.heightAnchor.constraint(equalToConstant: 24), - joinBtn.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor, constant: -16), - ]) - - NSLayoutConstraint.activate([ - content.topAnchor.constraint(equalTo: headImageView.topAnchor), - content.leftAnchor.constraint(equalTo: headImageView.rightAnchor, constant: 12), - content.rightAnchor.constraint(equalTo: joinBtn.leftAnchor), - ]) - } - - // MARK: lazyMethod - - private lazy var serviceBgView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = HexRGB(0xEFF1F4) - return view - }() - - lazy var headImageView: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(14) - view.translatesAutoresizingMaskIntoConstraints = false -// view.clipsToBounds = true - return view - }() - - private lazy var content: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(14) - label.textColor = TextNormalColor - return label - }() - - private lazy var subContent: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = .ne_blueText - return label - }() - - private lazy var rightContent: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("applied") - label.font = DefaultTextFont(12) - label.textColor = UIColor.ne_emptyTitleColor - label.isHidden = true - return label - }() - - private lazy var rightContentImageView: UIImageView = { - let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "addOther_icon")) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.isHidden = true - return imageView - }() - - private lazy var joinBtn: UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitle(localizable("join"), for: .normal) - button.setTitleColor(UIColor.white, for: .normal) - button.titleLabel?.font = DefaultTextFont(12) - button.backgroundColor = HexRGB(0x337EFF) - button.layer.cornerRadius = 4 - button.addTarget(self, action: #selector(bottomBtnClick), for: .touchUpInside) - button.isHidden = true - return button - }() -} - -extension NESearchServerCell { - @objc func bottomBtnClick(sender: UIButton) { - guard let serverId = serverModel?.serverId else { - return - } - let param = QChatApplyServerJoinParam(serverId: serverId) - - serverViewModel.applyServerJoin(parameter: param) { [self] error in - NELog.infoLog( - self.className, - desc: "CALLBACK applyServerJoin " + (error?.localizedDescription ?? "no error") - ) - if error == nil { - self.joinBtn.isHidden = true - self.rightContent.isHidden = false - if self.joinServerCallBack != nil { - joinServerCallBack!() - } - } else { - print("applyServerJoin failed,error = \(error!)") - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift deleted file mode 100644 index fe593914..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit -import UIKit -import NEQChatKit -import NIMSDK -import NECoreKit -import SDWebImageWebPCoder -import SDWebImageSVGKitPlugin - -@objcMembers -public class CreateServerViewModel: NSObject, QChatRepoMessageDelegate, AllChannelDataDelegate { - typealias ServerListRefresh = () -> Void - - var dataDic = WeakDictionary() - - var channelUnreadCountDic = [UInt64: Int]() - - var requestFlag = [UInt64: AllChannelData]() - - var channelDataDic = [UInt64: [UInt64: UInt]]() - - let repo = QChatRepo() - - var currentServerId: UInt64? - - var delegate: ViewModelDelegate? - - var updateServerList: ServerListRefresh? - - private let className = "CreateServerViewModel" - - override public init() { - super.init() - NELog.infoLog(ModuleName + " " + className, desc: #function) - repo.delegate = self - let webpCoder = SDImageWebPCoder() - SDImageCodersManager.shared.addCoder(webpCoder) - let svgCoder = SDImageSVGKCoder.shared - SDImageCodersManager.shared.addCoder(svgCoder) - } - - public func onUnReadChange(_ unreads: [NIMQChatUnreadInfo]?, - _ lastUnreads: [NIMQChatUnreadInfo]?) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", unreads.count:\(unreads?.count ?? 0)") - print("onUnReadChange: ", unreads as Any) - weak var weakSelf = self - var set = Set() - - unreads?.forEach { unread in - set.insert(unread.serverId) - if weakSelf?.channelDataDic[unread.serverId] != nil { - weakSelf?.channelDataDic[unread.serverId]?[unread.channelId] = unread.unreadCount - } else { - var channelDic = [UInt64: UInt]() - channelDic[unread.channelId] = unread.unreadCount - weakSelf?.channelDataDic[unread.serverId] = channelDic - } - } - - set.forEach { sid in - let hasUnread = checkServerExistUnread(sid) - print("hasUnread : ", hasUnread) - let model = weakSelf?.dataDic[sid] - print("server model : ", model?.name as Any) - model?.hasUnread = hasUnread - if let cSid = weakSelf?.currentServerId, cSid == sid { - weakSelf?.delegate?.dataDidChange() - } - } - - if let block = updateServerList { - block() - } - } - - func checkServerExistUnread(_ serverId: UInt64) -> Bool { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId)") - if let channelDic = channelDataDic[serverId] { - for key in channelDic.keys { - if let unreadCount = channelDic[key], unreadCount > 0 { - return true - } - } - } - return false - } - - public lazy var dataArray: [(String, String)] = { - let array = [ - ("mine_create", localizable("qchat_mine_add")), - ("addOther_icon", localizable("qchat_join_otherServer")), - ] - return array - }() - - public func createServer(parameter: CreateServerParam, - _ completion: @escaping (NSError?, CreateServerResult?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", name:\(parameter.name ?? "nil")") - QChatServerProvider.shared.createServer(param: parameter) { error, serverResult in - completion(error, serverResult) - } - } - - public func getServers(parameter: QChatGetServersParam, - _ completion: @escaping (NSError?, QChatGetServersResult?) -> Void) { - NELog.infoLog( - ModuleName + " " + className, - desc: #function + ", serverIds.count:\(parameter.serverIds?.count ?? 0)" - ) - repo.getServers(parameter) { error, serverResult in - completion(error, serverResult) - } - } - - public func getServerList(parameter: GetServersByPageParam, - _ completion: @escaping (NSError?, GetServersByPageResult?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function) - QChatServerProvider.shared.getServerCount(param: parameter) { error, result in - completion(error, result) - } - } - - public func getServerMemberList(parameter: QChatGetServerMembersParam, - _ completion: @escaping (NSError?, - QChatGetServerMembersResult?) -> Void) { - NELog.infoLog( - ModuleName + " " + className, - desc: #function + ", serverAccIds.count:\(parameter.serverAccIds?.count ?? 0)" - ) - QChatServerProvider.shared.getServerMembers(param: parameter) { error, result in - completion(error, result) - } - } - - public func getServerMembersByPage(parameter: QChatGetServerMembersByPageParam, - _ completion: @escaping (NSError?, - QChatGetServerMembersResult?) - -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(parameter.serverId ?? 0)") - QChatServerProvider.shared.getServerMembersByPage(param: parameter) { error, result in - completion(error, result) - } -// repo.getServerMembersByPage(parameter, completion) - } - - public func applyServerJoin(parameter: QChatApplyServerJoinParam, - _ completion: @escaping (NSError?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(parameter.serverId)") - QChatServerProvider.shared.applyServerJoin(param: parameter) { error in - completion(error) - } - } - - public func inviteMembersToServer(serverId: UInt64, accids: [String], - _ completion: @escaping (NSError?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId)") - let param = QChatInviteServerMembersParam(serverId: serverId, accids: accids) - repo.inviteMembersToServer(param) { error in - completion(error) - } - } - - public func getUnread(_ servers: [QChatServer]) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", servers.count:\(servers.count)") -// print("server model get unread servers : ", servers.count) - - if currentServerId == nil { - currentServerId = servers.first?.serverId - } - weak var weakSelf = self - servers.forEach { server in - if let sid = server.serverId { - weakSelf?.dataDic[sid] = server - } - weakSelf?.getAllChannel(server) - } - } - - func getAllChannel(_ server: QChatServer) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(server.serverId ?? 0)") - if let sid = server.serverId, requestFlag[sid] == nil { - let allChannelData = AllChannelData(sid: sid) - allChannelData.delegate = self - requestFlag[sid] = allChannelData - } - } - - func getChannelUnread(_ serverId: UInt64, _ channels: [ChatChannel]) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId), channels.count:\(channels.count)") -// print("getChannelUnread channel count : ", channels.count) - var param = GetChannelUnreadInfosParam() - var targets = [ChannelIdInfo]() - - channels.forEach { channel in - var channelIdInfo = ChannelIdInfo() - channelIdInfo.serverId = serverId - channelIdInfo.channelId = channel.channelId - targets.append(channelIdInfo) - } - param.targets = targets -// weak var weakSelf = self - repo.getChannelUnReadInfo(param) { error, infos in - - print("get channel unread info : ", error as Any) - /* - infos?.forEach({ info in - if weakSelf?.channelDataDic[info.serverId] != nil { - weakSelf?.channelDataDic[info.serverId]?[info.channelId] = info.unreadCount - }else { - var channelDic = [UInt64: UInt]() - channelDic[info.channelId] = info.unreadCount - weakSelf?.channelDataDic[info.serverId] = channelDic - } - }) - if let last = infos?.last, let sid = weakSelf?.currentServerId { - if last.serverId == sid { - weakSelf?.delegate?.dataDidChange() - } - } - if let server = weakSelf?.dataDic[serverId], let block = weakSelf?.updateServerList, let hasUnread = weakSelf?.checkServerExistUnread(serverId){ - server.hasUnread = hasUnread - block() - if let cSid = weakSelf?.currentServerId, cSid == serverId { - weakSelf?.delegate?.dataDidChange() - } - }*/ - } - } - - func dataGetSuccess(_ serverId: UInt64, _ channels: [ChatChannel]) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId)") - print("get unread channel success : ", channels.count) - requestFlag.removeValue(forKey: serverId) - getChannelUnread(serverId, channels) - } - - func dataGetError(_ serverId: UInt64, _ error: Error) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId)") - requestFlag.removeValue(forKey: serverId) - print("get all channels error : ", error) - } - - func getChannelUnreadCount(_ serverId: UInt64, _ channelId: UInt64) -> UInt { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId)") - if let channelDic = channelDataDic[serverId], let count = channelDic[channelId] { - return count - } - return 0 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift deleted file mode 100644 index c423a8d9..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import NECoreIMKit - -@objcMembers -public class MemberListViewModel: NSObject { - let repo = QChatRepo() - public var memberInfomationArray: [QChatMember]? - weak var delegate: ViewModelDelegate? - private let className = "MemberListViewModel" - - override init() {} - - func requestServerMemebersByPage(param: QChatGetServerMembersByPageParam, - _ completion: @escaping (NSError?, [ServerMemeber]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(param.serverId ?? 0)") - repo.getServerMembersByPage(param) { error, memberResult in - - if error == nil { - guard let memberArr = memberResult?.memberArray else { return } - var accidList = [String]() - var dic = [String: ServerMemeber]() - - for memberModel in memberArr { - accidList.append(memberModel.accid ?? "") - if let accid = memberModel.accid { - dic[accid] = memberModel - } - } - - let roleParam = QChatGetExistingAccidsInServerRoleParam( - serverId: param.serverId!, - accids: accidList - ) - self.repo.getExistingServerRolesByAccids(roleParam) { error, serverRolesDict in - serverRolesDict?.forEach { key, roleArray in - dic[key]?.roles = roleArray - } - var tempServerArray = [ServerMemeber]() - for var memberModel in memberArr { - if let accid = memberModel.accid, let dicMember = dic[accid] { - memberModel.roles = dicMember.roles - memberModel.imName = dicMember.imName - tempServerArray.append(memberModel) - } - } - completion(nil, tempServerArray) - } - - } else { - completion(error, nil) - print("getServerMembersByPage failed,error = \(error!)") - NELog.infoLog(ModuleName + " " + self.className, desc: #function + ", ❌CALLBACK FAILED, error:" + error!.localizedDescription) - } - } - } - - func getRoles() {} -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/IdGroupModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/IdGroupModel.swift deleted file mode 100644 index a0e3e62e..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/IdGroupModel.swift +++ /dev/null @@ -1,30 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -@objcMembers -public class IdGroupModel: NSObject { - var idName: String? - var subTitle: String? - var uid: Int? - var isSelect = false - var cornerType: CornerType = .none - var role: ServerRole? - var hasPermission = false - - override public init() {} - - public init(_ serverRole: ServerRole) { - role = serverRole - idName = serverRole.name - if let type = serverRole.type, type == .everyone { - subTitle = localizable("qchat_group_default_permission") - } else if let type = serverRole.type, type == .custom { - subTitle = "\(serverRole.memberCount ?? 0)人" - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/PermissionCellModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/PermissionCellModel.swift deleted file mode 100644 index 58c12a14..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/PermissionCellModel.swift +++ /dev/null @@ -1,15 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation - -@objcMembers -public class PermissionCellModel: NSObject { - weak var permission: PermissionModel? - var permissionKey: String? - var showName: String? - var cornerType = CornerType.none - var hasPermission = false -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/PermissionModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/PermissionModel.swift deleted file mode 100644 index fc9ca6f3..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/PermissionModel.swift +++ /dev/null @@ -1,108 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -@objcMembers -public class PermissionModel: NSObject { - let commonPermission = [ - #keyPath(PermissionModel.managerServer), - #keyPath(PermissionModel.allChannelProperty), - #keyPath(PermissionModel.role), - ] - - let commonPermissionDic = [ - #keyPath(PermissionModel.managerServer): localizable("qchat_manager_server"), - #keyPath(PermissionModel.allChannelProperty): localizable("qchat_manager_channel"), - #keyPath(PermissionModel.role): localizable("qchat_manager_role"), - ] - - var allChannelProperty = ChatPermissionType.manageChannel.rawValue - - var role = ChatPermissionType.manageRole.rawValue - - var managerServer = ChatPermissionType.manageServer.rawValue - - let messagePermission = [#keyPath(PermissionModel.sendMessage)] - - let messagePermissionDic = - [#keyPath(PermissionModel.sendMessage): localizable("qchat_send_message")] - - var sendMessage = ChatPermissionType.sendMsg.rawValue - -// @objc var deleteOtherMemberMessage = ChatPermissionType.deleteOtherMsg.rawValue -// -// @objc var recallMessage = ChatPermissionType.revokeMsg.rawValue -// -// @objc var atAnyMember = ChatPermissionType.remindOther.rawValue -// -// @objc var atAllMember = ChatPermissionType.remindAll.rawValue - - /* - let messagePermission = [#keyPath(PermissionModel.sendMessage), - #keyPath(PermissionModel.deleteOtherMemberMessage), - #keyPath(PermissionModel.recallMessage), - #keyPath(PermissionModel.atAnyMember), - #keyPath(PermissionModel.atAllMember)] - - let messagePermissionDic = [#keyPath(PermissionModel.sendMessage):localizable("qchat_send_message"), - #keyPath(PermissionModel.deleteOtherMemberMessage):localizable("qchat_delete_message"), - #keyPath(PermissionModel.recallMessage):localizable("qchat_recall_message"), - #keyPath(PermissionModel.atAnyMember):localizable("qchat_at_any"), - #keyPath(PermissionModel.atAllMember):localizable("qchat_at_all")] - - @objc var sendMessage = ChatPermissionType.sendMsg.rawValue - - @objc var deleteOtherMemberMessage = ChatPermissionType.deleteOtherMsg.rawValue - - @objc var recallMessage = ChatPermissionType.revokeMsg.rawValue - - @objc var atAnyMember = ChatPermissionType.remindOther.rawValue - - @objc var atAllMember = ChatPermissionType.remindAll.rawValue - */ - - let memberPermission = [#keyPath(PermissionModel.modifyOwnServer), - #keyPath(PermissionModel.modifyOthersServer), - #keyPath(PermissionModel.inviteMember), - #keyPath(PermissionModel.kickout), - #keyPath(PermissionModel.managerBlackAndWhite)] - - let memberPermissionDic = [ - #keyPath(PermissionModel.modifyOwnServer): localizable("qchat_modify_own_server"), - #keyPath(PermissionModel.modifyOthersServer): localizable("qchat_modify_other_server"), - #keyPath(PermissionModel.inviteMember): localizable("qchat_invite_member"), - #keyPath(PermissionModel.kickout): localizable("qchat_kick_out"), - #keyPath(PermissionModel.managerBlackAndWhite): localizable("qchat_manager_channel_list"), - ] - - var modifyOwnServer = ChatPermissionType.manageServer.rawValue - - var modifyOthersServer = ChatPermissionType.modifyOthersInfoInServer.rawValue - - var inviteMember = ChatPermissionType.inviteToServer.rawValue - - var kickout = ChatPermissionType.kickOthersInServer.rawValue - - var managerBlackAndWhite = ChatPermissionType.manageBlackWhiteList.rawValue - - var changeMap = [String: Bool]() - - override init() { - super.init() - } - - func getChangePermission() -> [ChatPermissionType: Bool] { - var permissions = [ChatPermissionType: Bool]() - changeMap.forEach { (key: String, v: Bool) in - if let permissionKey = value(forKey: key) as? String, - let type = ChatPermissionType(rawValue: permissionKey) { - permissions[type] = v - } - } - return permissions - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/SettingModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/SettingModel.swift deleted file mode 100644 index 60193a48..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/SettingModel.swift +++ /dev/null @@ -1,13 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation - -@objcMembers -public class SettingModel: NSObject { - var title: String? - var cornerType: CornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/UserInfo.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/UserInfo.swift deleted file mode 100644 index 7a319b6f..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/Model/UserInfo.swift +++ /dev/null @@ -1,50 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit - -@objcMembers -class UserInfo: NSObject { - var nickName: String? - var cornerType: CornerType = .none - var color = UIColor.colorWithNumber(number: 0) - var select = false - var accid: String? - var serverId: UInt64? - var createTime: Double? - - var serverMember: ServerMemeber? - - var roleMember: RoleMember? - - override init() {} - - init(_ member: ServerMemeber) { - serverMember = member - if let n = member.nick, n.count > 0 { - nickName = n - } else { - nickName = member.accid - } - accid = member.accid - serverId = member.serverId - createTime = member.createTime - color = UIColor.colorWithString(string: accid) - } - - init(_ member: RoleMember) { - roleMember = member - if let n = member.nick, n.count > 0 { - nickName = n - } else { - nickName = member.accid - } - accid = member.accid - serverId = member.serverId - createTime = member.createTime - color = UIColor.colorWithString(string: accid) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatDestructiveCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatDestructiveCell.swift deleted file mode 100644 index 38a54c94..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatDestructiveCell.swift +++ /dev/null @@ -1,46 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatDestructiveCell: QChatCornerCell { - lazy var redTextLabel: UILabel = { - let label = UILabel() - label.textColor = .ne_redText - label.font = DefaultTextFont(16) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.backgroundColor = .clear - backgroundColor = .clear - contentView.addSubview(redTextLabel) - NSLayoutConstraint.activate([ - redTextLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - redTextLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } - - func changeDisableTextColor() { - redTextLabel.textColor = .ne_disableRedText - } - - func changeEnableTextColor() { - redTextLabel.textColor = .ne_redText - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatHeaderCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatHeaderCell.swift deleted file mode 100644 index 61ea3353..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatHeaderCell.swift +++ /dev/null @@ -1,69 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatHeaderCell: QChatCornerCell { - var user: UserInfo? { - didSet { - if let name = user?.nickName { - headerView.setTitle(name) - nameLabel.text = name - } else if let aid = user?.accid { - headerView.setTitle(aid) - nameLabel.text = aid - } - headerView.backgroundColor = user?.color - } - } - - let headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.titleLabel.font = DefaultTextFont(20) - header.titleLabel.textColor = UIColor.white - header.layer.cornerRadius = 30 - header.translatesAutoresizingMaskIntoConstraints = false -// header.backgroundColor = UIColor.randomColor() - - return header - }() - - let nameLabel: UILabel = { - let label = UILabel() - label.textColor = .ne_darkText - label.font = DefaultTextFont(16) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headerView.widthAnchor.constraint(equalToConstant: 60), - headerView.heightAnchor.constraint(equalToConstant: 60), - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 16), - nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupCell.swift deleted file mode 100644 index e0415913..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupCell.swift +++ /dev/null @@ -1,138 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatIdGroupCell: QChatBaseCell { - lazy var headImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "id_group_header") - return image - }() - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_darkText - label.font = DefaultTextFont(14) - label.textAlignment = .left - return label - }() - - lazy var subTitleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_greyText - label.font = DefaultTextFont(12) - label.textAlignment = .left - return label - }() - - lazy var countHeadImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "count_header") - return image - }() - - lazy var tailImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.highlightedImage = UIImage.ne_imageNamed(name: "lock") - image.image = UIImage.ne_imageNamed(name: "arrowRight") - return image - }() - - lazy var dividerLine: UIView = { - let line = UIView() - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - return line - }() - - var leftSpace: NSLayoutConstraint? - - var titleLeftSpace: NSLayoutConstraint? - - var countHeadWidth: NSLayoutConstraint? - - var headWidth: NSLayoutConstraint? - - var headHeight: NSLayoutConstraint? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.addSubview(headImage) - leftSpace = headImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 24) - leftSpace?.isActive = true - - headWidth = headImage.widthAnchor.constraint(equalToConstant: 29) - headWidth?.isActive = true - headHeight = headImage.heightAnchor.constraint(equalToConstant: 33) - headHeight?.isActive = true - - NSLayoutConstraint.activate([ - headImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - - contentView.addSubview(tailImage) - NSLayoutConstraint.activate([ - tailImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - tailImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - ]) - - contentView.addSubview(titleLabel) - titleLeftSpace = titleLabel.leftAnchor.constraint( - equalTo: headImage.rightAnchor, - constant: 15.5 - ) - titleLeftSpace?.isActive = true - NSLayoutConstraint.activate([ - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 13.0), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36.0), - ]) - - contentView.addSubview(countHeadImage) - countHeadWidth = countHeadImage.widthAnchor.constraint(equalToConstant: 10) - countHeadWidth?.isActive = true - NSLayoutConstraint.activate([ - countHeadImage.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), - countHeadImage.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 6), - countHeadImage.heightAnchor.constraint(equalToConstant: 10), - ]) - - contentView.addSubview(subTitleLabel) - NSLayoutConstraint.activate([ - subTitleLabel.leftAnchor.constraint(equalTo: countHeadImage.rightAnchor, constant: 6), - subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4), - subTitleLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), - ]) - - contentView.addSubview(dividerLine) - NSLayoutConstraint.activate([ - dividerLine.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - dividerLine.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - dividerLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - dividerLine.heightAnchor.constraint(equalToConstant: 1), - ]) - } - - func configure(_ model: IdGroupModel) { - titleLabel.text = model.idName - subTitleLabel.text = model.subTitle - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupMemberCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupMemberCell.swift deleted file mode 100644 index dce6e98d..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupMemberCell.swift +++ /dev/null @@ -1,98 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatIdGroupMemberCell: QChatCornerCell { - lazy var headView: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(11) - view.translatesAutoresizingMaskIntoConstraints = false - view.clipsToBounds = true - view.layer.cornerRadius = 16.0 - return view - }() - - lazy var tailorImage: UIImageView = { - let image = UIImageView() - image.image = UIImage.ne_imageNamed(name: "delete") - image.translatesAutoresizingMaskIntoConstraints = false - return image - }() - - lazy var nameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_darkText - label.font = DefaultTextFont(14) - return label - }() - - var user: UserInfo? { - didSet { - if let name = user?.nickName { - headView.setTitle(name) - } - headView.backgroundColor = user?.color - nameLabel.text = user?.nickName - } - } - - var leftSpace: NSLayoutConstraint? - - var rightSpace: NSLayoutConstraint? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI() { - contentView.addSubview(headView) - - leftSpace = headView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36) - leftSpace?.isActive = true - NSLayoutConstraint.activate([ - headView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headView.widthAnchor.constraint(equalToConstant: 32), - headView.heightAnchor.constraint(equalToConstant: 32), - ]) - - contentView.addSubview(tailorImage) - rightSpace = tailorImage.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -36 - ) - rightSpace?.isActive = true - NSLayoutConstraint.activate([ - tailorImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - tailorImage.widthAnchor.constraint(equalToConstant: 16.0), - tailorImage.heightAnchor.constraint(equalToConstant: 16.0), - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: headView.rightAnchor, constant: 12), - nameLabel.rightAnchor.constraint(equalTo: tailorImage.leftAnchor, constant: -10), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupSelectCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupSelectCell.swift deleted file mode 100644 index 86514861..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupSelectCell.swift +++ /dev/null @@ -1,67 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatIdGroupSelectCell: QChatCornerCell { - var group: IdGroupModel? { - didSet { - if let select = group?.isSelect { - tailImage.isHighlighted = select - } - nameLabel.text = group?.idName - if let type = group?.cornerType { - cornerType = type - } - } - } - - let tailImage: UIImageView = { - let image = UIImageView() - image.image = UIImage.ne_imageNamed(name: "unselect") - image.highlightedImage = UIImage.ne_imageNamed(name: "select") - image.translatesAutoresizingMaskIntoConstraints = false - image.isHidden = true - return image - }() - - let nameLabel: UILabel = { - let label = UILabel() - label.textColor = .ne_darkText - label.font = DefaultTextFont(14) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.addSubview(tailImage) - NSLayoutConstraint.activate([ - tailImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - tailImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - nameLabel.rightAnchor.constraint( - equalTo: contentView.rightAnchor, - constant: -(36 + 23) - ), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupSortButtonCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupSortButtonCell.swift deleted file mode 100644 index 7629ddc4..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupSortButtonCell.swift +++ /dev/null @@ -1,78 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatIdGroupSortButtonCell: QChatBaseCell { - lazy var titleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_greyText - label.font = DefaultTextFont(12) - return label - }() - - lazy var sortImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "id_group_sort") - return image - }() - - lazy var sortBtn: ExpandButton = { - let btn = ExpandButton() - btn.translatesAutoresizingMaskIntoConstraints = false - return btn - }() - - lazy var sortLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = .ne_blueText - label.text = localizable("qchat_sort") - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - ]) - - contentView.addSubview(sortLabel) - NSLayoutConstraint.activate([ - sortLabel.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor), - sortLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - ]) - - contentView.addSubview(sortImage) - NSLayoutConstraint.activate([ - sortImage.centerYAnchor.constraint(equalTo: sortLabel.centerYAnchor), - sortImage.rightAnchor.constraint(equalTo: sortLabel.leftAnchor, constant: -6), - ]) - - contentView.addSubview(sortBtn) - NSLayoutConstraint.activate([ - sortBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor), - sortBtn.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - sortBtn.topAnchor.constraint(equalTo: contentView.topAnchor), - sortBtn.leftAnchor.constraint(equalTo: sortImage.leftAnchor, constant: -10), - ]) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupTopCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupTopCell.swift deleted file mode 100644 index 3e0c3bb2..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatIdGroupTopCell.swift +++ /dev/null @@ -1,30 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatIdGroupTopCell: QChatIdGroupCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override func setupUI() { - super.setupUI() - leftSpace?.constant = 20.0 - headImage.image = UIImage.ne_imageNamed(name: "member_header") - titleLeftSpace?.constant = 12.0 - countHeadWidth?.constant = 0 - countHeadImage.isHidden = true - headWidth?.constant = 36.0 - headHeight?.constant = 36.0 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatMemberManagerCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatMemberManagerCell.swift deleted file mode 100644 index ec712139..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatMemberManagerCell.swift +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatMemberManagerCell: QChatIdGroupMemberCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override func setupUI() { - super.setupUI() - contentView.backgroundColor = .white - leftSpace?.constant = 20 - rightSpace?.constant = -20 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatPlainTextArrowCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatPlainTextArrowCell.swift deleted file mode 100644 index c5cd2e17..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatPlainTextArrowCell.swift +++ /dev/null @@ -1,27 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatPlainTextArrowCell: QChatTextArrowCell { - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.backgroundColor = .white - titleLeftMargin?.constant = 20 - detailRightMargin?.constant = -42 - rightImageMargin?.constant = -20 - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSelectedCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSelectedCell.swift deleted file mode 100644 index 434af2e1..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSelectedCell.swift +++ /dev/null @@ -1,92 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatSelectedCell: QChatBaseCell { - var user: UserInfo? { - didSet { - if let name = user?.nickName { - headerView.setTitle(name) - } - titleLabel.text = user?.nickName - headerView.backgroundColor = user?.color - if let value = user?.select { - checkBox.isHighlighted = value - } - } - } - - public lazy var titleLabel: UILabel = { - let label = UILabel() - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 14.0) - label.textColor = .ne_darkText - return label - }() - - let headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.titleLabel.font = DefaultTextFont(14) - header.titleLabel.textColor = UIColor.white - header.layer.cornerRadius = 18 - header.translatesAutoresizingMaskIntoConstraints = false - return header - }() - - let checkBox: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "unselect") - image.highlightedImage = UIImage.ne_imageNamed(name: "select") - return image - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.addSubview(checkBox) - NSLayoutConstraint.activate([ - checkBox.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - checkBox.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headerView.leftAnchor.constraint(equalTo: checkBox.rightAnchor, constant: 12), - headerView.widthAnchor.constraint(equalToConstant: 36), - headerView.heightAnchor.constraint(equalToConstant: 36), - ]) - - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 98), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } - - func setSelect() { - user?.select = true - checkBox.isHighlighted = true - } - - func setUnselect() { - user?.select = false - checkBox.isHighlighted = false - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSortCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSortCell.swift deleted file mode 100644 index 5b7d7fd5..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSortCell.swift +++ /dev/null @@ -1,39 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatSortCell: QChatIdGroupCell { - lazy var dotImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "dot_image") - image.highlightedImage = UIImage.ne_imageNamed(name: "dot_image_disable") - return image - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override func setupUI() { - super.setupUI() -// self.leftSpace?.constant = 72 - tailImage.image = UIImage.ne_imageNamed(name: "delete") - tailImage.highlightedImage = UIImage.ne_imageNamed(name: "lock") -// contentView.addSubview(dotImage) -// NSLayoutConstraint.activate([ -// dotImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 31), -// dotImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) -// ]) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSwitchCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSwitchCell.swift deleted file mode 100644 index c639e2dc..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatSwitchCell.swift +++ /dev/null @@ -1,88 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -protocol QChatSwitchCellDelegate: AnyObject { - func didChangeSwitchValue(_ cell: QChatSwitchCell) -} - -class QChatSwitchCell: QChatCornerCell { - weak var delegate: QChatSwitchCellDelegate? - - var qSwitch: UISwitch = { - let q = UISwitch() - q.translatesAutoresizingMaskIntoConstraints = false - q.onTintColor = .ne_blueText - return q - }() - - var permissionLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_darkText - label.font = DefaultTextFont(16) - return label - }() - - var model: PermissionCellModel? { - didSet { - permissionLabel.text = model?.showName - - if let type = model?.cornerType { - cornerType = type - } - if let value = model?.hasPermission { - qSwitch.isOn = value - } - } - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI() { - contentView.addSubview(qSwitch) - NSLayoutConstraint.activate([ - qSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - qSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - ]) - qSwitch.addTarget(self, action: #selector(valueChange(_:)), for: .valueChanged) - - contentView.addSubview(permissionLabel) - NSLayoutConstraint.activate([ - permissionLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - permissionLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -95), - permissionLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - } - - @objc func valueChange(_ s: UISwitch) { - model?.hasPermission = s.isOn - delegate?.didChangeSwitchValue(self) - /* - if s.isOn == true { - if let key = model?.permissionKey { - print("add key : ", key) - model?.permission?.changeMap[key] = true - } - }else { - if let key = model?.permissionKey { - print("rm key : ", key) - model?.permission?.changeMap[key] = false - } - }*/ - print("change maps : ", model?.permission?.changeMap as Any) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatUserUnCheckCell.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatUserUnCheckCell.swift deleted file mode 100644 index 223f91c0..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/View/QChatUserUnCheckCell.swift +++ /dev/null @@ -1,57 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit - -class QChatUserUnCheckCell: QChatBaseCollectionViewCell { - public var avatarImage = UIView() - public var nameTailLabel = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI() { - contentView.addSubview(avatarImage) - avatarImage.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - avatarImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36), - ]) - avatarImage.layer.cornerRadius = 18.0 - avatarImage.clipsToBounds = true - - avatarImage.addSubview(nameTailLabel) - nameTailLabel.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - nameTailLabel.centerXAnchor.constraint(equalTo: avatarImage.centerXAnchor), - nameTailLabel.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), - nameTailLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor, constant: 1), - nameTailLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: -1), - ]) - nameTailLabel.font = UIFont.systemFont(ofSize: 16.0) - nameTailLabel.textAlignment = .center - nameTailLabel.textColor = .white - - contentView.backgroundColor = .clear - } - - func configure(_ model: UserInfo) { - avatarImage.backgroundColor = model.color - // title - guard let name = model.nickName else { - return - } - nameTailLabel.text = name - .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatCreateGroupViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatCreateGroupViewController.swift deleted file mode 100644 index 3718b993..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatCreateGroupViewController.swift +++ /dev/null @@ -1,273 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -typealias CreateCompletion = () -> Void - -public class QChatCreateGroupViewController: NEBaseTableViewController, - QChatMemberSelectControllerDelegate, UITableViewDataSource, UITableViewDelegate, - ViewModelDelegate, - QChatTextEditCellDelegate { - let viewModel = CreateGroupViewModel() - - var serverId: UInt64? - - var serverName = "" - - var completion: CreateCompletion? - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - viewModel.delegate = self - setupUI() - } - - func setupUI() { - addRightAction(localizable("create"), #selector(createClick), self) - title = localizable("qchat_create_new_id_group") - setupTable() - tableView.delegate = self - tableView.backgroundColor = .ne_backcolor - - tableView.dataSource = self - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - tableView.register( - QChatTextEditCell.self, - forCellReuseIdentifier: "\(QChatTextEditCell.self)" - ) - tableView.register(QChatUnfoldCell.self, forCellReuseIdentifier: "\(QChatUnfoldCell.self)") - tableView.register( - QChatIdGroupMemberCell.self, - forCellReuseIdentifier: "\(QChatIdGroupMemberCell.self)" - ) - } - - // MAKR: objc 方法 - @objc func createClick() { - if serverName.count <= 0 { - view.makeToast(localizable("qchat_please_input_role_name")) - return - } - var param = ServerRoleParam() - param.serverId = serverId - param.type = .custom - param.name = serverName - weak var weakSelf = self - print("create role param : ", param) - - viewModel.repo.createRole(param) { error, role in - print("create role : ", error as Any, role) - if let err = error { - weakSelf?.dataDidError(err) - } else { - if let rid = role.roleId, let addMemebers = weakSelf?.viewModel.allUsers, - addMemebers.count > 0 { - weakSelf?.addMember(rid) - } else { - if let block = weakSelf?.completion { - block() - } - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - } - - func addMember(_ roleId: UInt64) { - weak var weakSelf = self - if viewModel.allUsers.count > 0 { - var accids = [String]() - viewModel.allUsers.forEach { user in - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - var param = AddServerRoleMemberParam() - param.accountArray = accids - param.serverId = serverId - param.roleId = roleId - viewModel.repo.addRoleMember(param) { error, sAccids, fAccids in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } - if let block = weakSelf?.completion { - block() - } - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - - // MARK: - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { - var dic = [String: String]() - viewModel.allUsers.forEach { user in - if let aid = user.accid { - dic[aid] = aid - } - } - var retArray = [String]() - accid?.forEach { aid in - if dic[aid] != nil { - retArray.append(aid) - } - } - filterMembers(retArray) - - // filterMembers(accid) - } - - func textDidChange(_ textField: UITextField) { - if let text = textField.text { - serverName = text - } - print("text change: ", textField.text as Any) - } - - public func dataDidError(_ error: Error) { - UIApplication.shared.keyWindow?.endEditing(true) - view.makeToast(error.localizedDescription) - } - - public func dataDidChange() { - tableView.reloadData() - } - - public func numberOfSections(in tableView: UITableView) -> Int { - let count = 3 - // if viewModel.limitUsers.count < viewModel.allUsers.count { - // count = count + 1 - // } - return count - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 || section == 1 { - return 1 - } else if section == 2 { - return viewModel.allUsers.count - } else if section == 3 { - return 0 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell: QChatTextEditCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - cell.textFied.placeholder = localizable("qchat_please_input_role_name") - cell.delegate = self - cell.limit = 20 - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) - return cell - } else if indexPath.section == 1 { - let cell: QChatTextArrowCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - cell.titleLabel.text = localizable("add_member") - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) - return cell - } else if indexPath.section == 2 { - let cell: QChatIdGroupMemberCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatIdGroupMemberCell.self)", - for: indexPath - ) as! QChatIdGroupMemberCell - let user = viewModel.allUsers[indexPath.row] - cell.cornerType = user.cornerType - cell.user = user - return cell - } else if indexPath.section == 3 { - let cell: QChatUnfoldCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatUnfoldCell.self)", - for: indexPath - ) as! QChatUnfoldCell - cell.contentLabel.text = "更多(共\(viewModel.allUsers.count))人" - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - return cell - } - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 1 { - let memberSelect = QChatMemberSelectController() - memberSelect.serverId = serverId - memberSelect.delegate = self - // memberSelect.selectType = .ServerMember - weak var weakSelf = self - memberSelect.completion = { datas in - if datas.count > 0 { - weakSelf?.viewModel.addMembers(datas) - } - } - navigationController?.pushViewController(memberSelect, animated: true) - - } else if indexPath.section == 2 { - // 编辑成员临时入口 - - // let user = viewModel.limitUsers[indexPath.row] - // let editMember = QChatEditMemberViewController() - // editMember.user = user - // navigationController?.pushViewController(editMember, animated: true) - - viewModel.removeData(indexPath.row) - } else if indexPath.section == 3 { - viewModel.loadAllData() - tableView.reloadData() - } - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 50 - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - if section == 0 || section == 1 { - return 40.0 - } else if section == 2 { - return 16 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - viewForHeaderInSection section: Int) -> UIView? { - let header = QChatHeaderView() - if section == 0 { - header.titleLabel.text = localizable("qchat_group_name") - return header - } - - if section == 1 { - header.titleLabel.text = localizable("qchat_manager_member") - return header - } - - if section == 2 { - let space = UIView() - space.backgroundColor = .clear - return space - } - - return nil - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatEditMemberViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatEditMemberViewController.swift deleted file mode 100644 index 88b64cec..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatEditMemberViewController.swift +++ /dev/null @@ -1,398 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreKit -import NECoreIMKit - -// typealias EditMemberCompletion = (_ member: ServerMemeber) -> Void - -typealias EditMemberChange = () -> Void - -typealias EditMemberDelete = () -> Void - -public class QChatEditMemberViewController: NEBaseTableViewController, UITableViewDataSource, - UITableViewDelegate, ViewModelDelegate, QChatTextEditCellDelegate { - var user: UserInfo? - var editAble = false - var showAll = false - let viewModel = EditMemberViewModel() - private let tag = "QChatEditMemberViewController" - -// var completion: EditMemberCompletion? - var changeCompletion: EditMemberChange? - var deleteCompletion: EditMemberDelete? - var nickName = "" - - var didChange = false - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - if let nick = user?.nickName { - nickName = nick - } -// else if let acid = user?.accid { -// nickName = acid -// } - viewModel.delegate = self - viewModel.getData(user?.serverId, user?.accid) - setupUI() - } - - func setupUI() { - setupTable() - if let name = user?.nickName { - title = name - } - addRightAction(localizable("qchat_edit"), #selector(rightBtnClick(_:)), self) - tableView.register( - QChatTextEditCell.self, - forCellReuseIdentifier: "\(QChatTextEditCell.self)" - ) - tableView.register(QChatHeaderCell.self, forCellReuseIdentifier: "\(QChatHeaderCell.self)") - tableView.register( - QChatDestructiveCell.self, - forCellReuseIdentifier: "\(QChatDestructiveCell.self)" - ) - tableView.register( - QChatIdGroupSelectCell.self, - forCellReuseIdentifier: "\(QChatIdGroupSelectCell.self)" - ) - tableView.register(QChatUnfoldCell.self, forCellReuseIdentifier: "\(QChatUnfoldCell.self)") - tableView.dataSource = self - tableView.delegate = self - tableView.backgroundColor = .ne_backcolor - -// let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) -// self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(back)) - addLeftAction(UIImage.ne_imageNamed(name: "backArrow"), #selector(back), self) - } - - @objc func back() { - didChangeRole() - navigationController?.popViewController(animated: true) - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - - // MARK: objc 方法 - - @objc func rightBtnClick(_ btn: ExpandButton) { - if btn.isSelected == true { - print("to save") - if nickName.count <= 0 { - showToast(localizable("nickName_not_empty")) - return - } - - guard let accid = user?.accid else { - showToast(localizable("accid_not_empty")) - return - } - - weak var weakSelf = self - - if IMKitEngine.instance.isMySelf(accid) == true { - viewModel.updateMyMember(user?.serverMember?.serverId, nickName) { error, member in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK updateMyMember " + (error?.localizedDescription ?? "no error") - ) - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } else { - weakSelf?.navigationController?.popViewController(animated: true) - if let block = weakSelf?.changeCompletion { - block() - } - } - } - } else { - viewModel - .updateMember(user?.serverMember?.serverId, nickName, - user?.accid) { error, member in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK updateMember " + (error?.localizedDescription ?? "no error") - ) - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } else { - weakSelf?.navigationController?.popViewController(animated: true) - if let block = weakSelf?.changeCompletion { - block() - } - } - } - } - - } else { - btn.isSelected = true - editAble = true - btn.setTitle(localizable("qchat_save"), for: .normal) - viewModel.showServerData() - } - } - - // MARK: UITableViewDataSource, UITableViewDelegate,ViewModelDelegate, QChatTextEditCellDelegate - - func textDidChange(_ textField: UITextField) { - print("edit mebmer name change : ", textField.text as Any) - if let text = textField.text { - nickName = text - } - } - - public func dataDidChange() { - tableView.reloadData() - } - - public func dataDidError(_ error: Error) { - showToast(error.localizedDescription) - } - - public func numberOfSections(in tableView: UITableView) -> Int { - 5 - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 || section == 1 { - return 1 - } else if section == 2 { - return showAll ? viewModel.allIdGroups.count : viewModel.limitIdGroups.count - } else if section == 3 { - if viewModel.limitIdGroups.count < viewModel.allIdGroups.count { - return 1 - } - } else if section == 4 { - return 1 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell: QChatHeaderCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatHeaderCell.self)", - for: indexPath - ) as! QChatHeaderCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.user = user - return cell - } else if indexPath.section == 1 { - let cell: QChatTextEditCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.delegate = self - cell.editTotast = localizable("modify_nickname") - cell.canEdit = editAble - if nickName.count > 0 { - cell.textFied.text = nickName - } else { - cell.textFied.text = nil - } - cell.textFied.placeholder = localizable("qcaht_edit_nickname") - return cell - } else if indexPath.section == 2 { - let cell: QChatIdGroupSelectCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatIdGroupSelectCell.self)", - for: indexPath - ) as! QChatIdGroupSelectCell - let group = showAll ? viewModel.allIdGroups[indexPath.row] : viewModel - .limitIdGroups[indexPath.row] - cell.tailImage.isHidden = !editAble - if let type = group.role?.type, type == .everyone { - cell.tailImage.isHidden = true - } - let exist = viewModel.checkoutCurrentUserRole(group.role?.roleId) - print("checkoutCurrentUserRole name : \(group.idName ?? "") exist : \(exist)") - group.isSelect = exist - cell.group = group - return cell - } else if indexPath.section == 3 { - let cell: QChatUnfoldCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatUnfoldCell.self)", - for: indexPath - ) as! QChatUnfoldCell - cell.contentLabel - .text = showAll ? "收起(共\(viewModel.allIdGroups.count)个)" : - "更多(共\(viewModel.allIdGroups.count)个)" - if showAll { - cell.changeToArrowUp() - } else { - cell.changeToArrowDown() - } - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - return cell - } else if indexPath.section == 4 { - let cell: QChatDestructiveCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatDestructiveCell.self)", - for: indexPath - ) as! QChatDestructiveCell - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.redTextLabel.text = "\(localizable("qchat_kick_out")) \(user?.nickName ?? "")" - if getKickDisable() { - cell.changeDisableTextColor() - } - } else if indexPath.row == 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - cell.redTextLabel.text = "\(localizable("qchat_prohibit")) \(user?.nickName ?? "")" - cell.changeEnableTextColor() - } - return cell - } - - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 92 - } - return 50 - } - - public func tableView(_ tableView: UITableView, - viewForHeaderInSection section: Int) -> UIView? { - let header = QChatHeaderView() - if section == 1 { - header.titleLabel.text = localizable("qchat_nickname") - return header - } - - if section == 2, viewModel.allIdGroups.count > 0 { - header.titleLabel.text = localizable("qchat_id_group") - return header - } - return nil - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - if section == 0 { - return 22 - } - - if section == 1 { - return 38 - } - - if section == 2, viewModel.allIdGroups.count > 0 { - return 38 - } - - if section == 4 { - return 20 - } - return 0 - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 1 { - // showToast("请点击编辑后修改昵称") - } else if indexPath.section == 2 { - if editAble == false { - return - } - - let group = showAll == true ? viewModel.allIdGroups[indexPath.row] : viewModel - .limitIdGroups[indexPath.row] - - if let type = group.role?.type, type == .everyone { - return - } - let select = viewModel.checkoutCurrentUserRole(group.role?.roleId) - weak var weakSelf = self - if select == false { - view.makeToastActivity(.center) - viewModel.addMembers(user?.accid, user?.serverId, group.role?.roleId) { - NELog.infoLog(ModuleName + " " + self.className(), desc: #function + ", accid:\(self.user?.accid ?? "nil")") - weakSelf?.view.hideToastActivity() - weakSelf?.didChange = true - } - } else { - view.makeToastActivity(.center) - viewModel.remove(user?.accid, user?.serverId, group.role?.roleId) { - NELog.infoLog(ModuleName + " " + self.className(), desc: #function + ", accid:\(self.user?.accid ?? "nil")") - weakSelf?.view.hideToastActivity() - weakSelf?.didChange = true - } - } - } else if indexPath.section == 3 { - showAll = !showAll - tableView.reloadData() - } else if indexPath.section == 4 { - weak var weakSelf = self - if getKickDisable() == true { - return - } - showAlert(message: localizable("kick_currentMember")) { - weakSelf?.kickOutMember() - } - } - } - - func didChangeRole() { - if didChange == true { - if let block = changeCompletion { - block() - } - } - } - - func getKickDisable() -> Bool { - if let accid = user?.serverMember?.accid { - // if CoreKitEngine.instance.imAccid == accid { - // return true - // } - - if IMKitEngine.instance.imAccid == accid { - return true - } - if let type = user?.serverMember?.type, type == .owner { - return true - } - } - return false - } - - func kickOutMember() { - view.makeToastActivity(.center) - weak var weakSelf = self - viewModel.kickoutMember(user?.serverId, user?.accid) { error in - NELog.infoLog( - ModuleName + " " + self.tag, - desc: "CALLBACK kickoutMember " + (error?.localizedDescription ?? "no error") - ) - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } else { - if let block = weakSelf?.deleteCompletion { - block() - } - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatIdGroupSortController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatIdGroupSortController.swift deleted file mode 100644 index a982fbb2..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatIdGroupSortController.swift +++ /dev/null @@ -1,210 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -// typealias SortCompletion = (_ array: NSMutableArray) -> Void - -typealias SortChange = () -> Void - -public class QChatIdGroupSortController: NEBaseTableViewController, UITableViewDelegate, - UITableViewDataSource, ViewModelDelegate { - var serverId: UInt64? - - var isOwer = false - - let viewmodel = IdGroupSortViewModel() - -// let dataArray = NSMutableArray() - - var didDelete = false - - var completion: SortChange? - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - navigationItem.leftBarButtonItem = UIBarButtonItem( - image: image, - style: .plain, - target: self, - action: #selector(back) - ) - viewmodel.isOwner = isOwer - viewmodel.delegate = self - viewmodel.getData(serverId) - setupUI() - } - - func setupUI() { - setupTable() - title = localizable("qchat_id_group_sort") - addRightAction(localizable("qchat_save"), #selector(saveSort), self) - tableView.backgroundColor = .white - tableView.delegate = self - tableView.dataSource = self - tableView.register(QChatSortCell.self, forCellReuseIdentifier: "\(QChatSortCell.self)") - tableView.isEditing = true - tableView.allowsSelectionDuringEditing = true - } - - @objc func saveSort() { - view.makeToastActivity(.center) - weak var weakSelf = self - viewmodel.saveSort(serverId) { - NELog.infoLog(ModuleName + " " + self.className(), desc: #function + ", serverId:\(self.serverId ?? 0)") - weakSelf?.view.hideToastActivity() - if let block = weakSelf?.completion { - block() - } - print("save success") - weakSelf?.navigationController?.popViewController(animated: true) - } - } - - @objc func back() { - if didDelete == true, let block = completion { - block() - } - navigationController?.popViewController(animated: true) - } - - // MARK: UITableViewDelegate, UITableViewDataSource, ViewModelDelegate - - public func dataDidChange() { - tableView.reloadData() - } - - public func dataDidError(_ error: Error) { - view.hideToastActivity() - showToast(error.localizedDescription) - } - - public func numberOfSections(in tableView: UITableView) -> Int { - 1 - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - // if section == 0 { - // return viewmodel.lockData.count - // }else if section == 1 { - // return viewmodel.datas.count - // } - viewmodel.datas.count - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: QChatSortCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatSortCell.self)", - for: indexPath - ) as! QChatSortCell - // if indexPath.section == 0 { - // let model = viewmodel.lockData[indexPath.row] - // cell.configure(model) - // cell.tailImage.isHighlighted = true - // }else if indexPath.section == 1 { - // if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - // cell.configure(model) - // cell.tailImage.isHighlighted = !model.hasPermission - // } - // } - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - cell.configure(model) - cell.tailImage.isHighlighted = !model.hasPermission - } - - return cell - } - - public func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, - to destinationIndexPath: IndexPath) { - print("source :", sourceIndexPath.row, " destionation :", destinationIndexPath.row) - - if sourceIndexPath.row > destinationIndexPath.row { - let src_model = viewmodel.datas.object(at: sourceIndexPath.row) - viewmodel.datas.remove(src_model) - viewmodel.datas.insert(src_model, at: destinationIndexPath.row) - } else { - let src_model = viewmodel.datas.object(at: sourceIndexPath.row) - viewmodel.datas.insert(src_model, at: destinationIndexPath.row + 1) - viewmodel.datas.removeObject(at: sourceIndexPath.row) - } - - viewmodel.datas.forEach { user in - if let u = user as? IdGroupModel { - print("change name : ", u.idName as Any) - print("change p: ", u.role?.priority as Any) - } - } - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 60 - } - - public func tableView(_ tableView: UITableView, - shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool { - false - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - weak var weakSelf = self - if model.hasPermission == true { - showAlert( - message: "\(localizable("sure_delete"))\(model.idName ?? localizable("current_identity"))?" - ) { - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.removeRole(weakSelf?.serverId, model.role?.roleId, model) { - NELog.infoLog(ModuleName + " " + self.className(), desc: #function + ", serverId:\(weakSelf?.serverId ?? 0)") - weakSelf?.didDelete = true - weakSelf?.view.hideToastActivity() - } - } - } - } - } - - public func tableView(_ tableView: UITableView, - targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, - toProposedIndexPath proposedDestinationIndexPath: IndexPath) - -> IndexPath { - if isOwer == true { - return proposedDestinationIndexPath - } else { - if let model = viewmodel.datas[proposedDestinationIndexPath.row] as? IdGroupModel { - if model.hasPermission == true { - return proposedDestinationIndexPath - } - } - } - return sourceIndexPath - } - - public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - return model.hasPermission - } - return true - } - - public func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - return model.hasPermission - } - return true - } - - public func tableView(_ tableView: UITableView, - editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell - .EditingStyle { - UITableViewCell.EditingStyle.none - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatIdGroupViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatIdGroupViewController.swift deleted file mode 100644 index 9ff02440..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatIdGroupViewController.swift +++ /dev/null @@ -1,246 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import MJRefresh - -public class QChatIdGroupViewController: NEBaseTableViewController, UITableViewDelegate, - UITableViewDataSource, ViewModelDelegate { - let viewModel = IdGroupViewModel() - var isOwner = false - var serverid: UInt64? - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - viewModel.delegate = self - loadMoreData() - setupUI() - } - - func setupUI() { - NELog.infoLog(ModuleName + " " + className(), desc: "serverid : \(serverid ?? 0)") - title = localizable("qchat_id_group") - addRightAction(UIImage.ne_imageNamed(name: "sign_add"), #selector(addClick), self) - setupTable() - tableView.delegate = self - tableView.dataSource = self - tableView.register( - QChatIdGroupCell.self, - forCellReuseIdentifier: "\(QChatIdGroupCell.self)" - ) - tableView.register( - QChatIdGroupTopCell.self, - forCellReuseIdentifier: "\(QChatIdGroupTopCell.self)" - ) - tableView.register( - QChatIdGroupSortButtonCell.self, - forCellReuseIdentifier: "\(QChatIdGroupSortButtonCell.self)" - ) - let mjFooter = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) - mjFooter.stateLabel?.isHidden = true - tableView.mj_footer = mjFooter - } - - @objc func loadMoreData() { - if let sid = serverid { - viewModel.getRoles(sid, false, nil) - } else { - fatalError("serverid must not be nil") - } - } - - @objc func refreshData() { - weak var weakSelf = self - view.makeToastActivity(.center) - print("refresh data") - viewModel.getRoles(weakSelf?.serverid, true) { - weakSelf?.view.hideToastActivity() - weakSelf?.tableView.mj_footer?.state = .idle - weakSelf?.tableView.mj_footer?.isHidden = false - } - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - - // MARK: UITableViewDelegate, UITableViewDataSource,ViewModelDelegate - - public func dataDidError(_ error: Error) { -// print("get roles error : ", error) - NELog.errorLog(ModuleName + " " + className(), desc: "error : \(error)") - view.makeToast(error.localizedDescription) - } - - public func dataDidChange() { - tableView.mj_footer?.endRefreshing() - tableView.reloadData() - } - - public func dataNoMore() { - tableView.mj_footer?.endRefreshingWithNoMoreData() - tableView.mj_footer?.isHidden = true - } - - public func numberOfSections(in tableView: UITableView) -> Int { - 3 - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return viewModel.topDatas.count - } else if section == 1 { - if viewModel.datas.count > 0 { - return viewModel.sortBtnCellDatas.count - } - } else if section == 2 { - return viewModel.datas.count - } - return 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let model = viewModel.topDatas[indexPath.row] - let cell: QChatIdGroupTopCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatIdGroupTopCell.self)", - for: indexPath - ) as! QChatIdGroupTopCell - cell.configure(model) - return cell - } else if indexPath.section == 1 { - let model = viewModel.sortBtnCellDatas[indexPath.row] - let cell: QChatIdGroupSortButtonCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatIdGroupSortButtonCell.self)", - for: indexPath - ) as! QChatIdGroupSortButtonCell - cell.titleLabel.text = model.idName - cell.sortBtn.addTarget(self, action: #selector(toSort), for: .touchUpInside) - return cell - } else if indexPath.section == 2 { - let model = viewModel.datas[indexPath.row] - let cell: QChatIdGroupCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatIdGroupCell.self)", - for: indexPath - ) as! QChatIdGroupCell - cell.configure(model) - return cell - } - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 68 - } else if indexPath.section == 1 { - return 30 - } else if indexPath.section == 2 { - return 60 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - if section == 1 { - return 6 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - viewForHeaderInSection section: Int) -> UIView? { - if section == 1 { - let view = UIView(frame: CGRect.zero) - view.backgroundColor = UIColor(hexString: "EFF1F4") - return view - } - return nil - } - - public func tableView(_ tableView: UITableView, - heightForFooterInSection section: Int) -> CGFloat { - 0 - } - - public func tableView(_ tableView: UITableView, - viewForFooterInSection section: Int) -> UIView? { - nil - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 1 { - return - } - - if indexPath.section == 0 { - let model = viewModel.topDatas[indexPath.row] - toPermission(model) - } else if indexPath.section == 2 { - let model = viewModel.datas[indexPath.row] - toPermission(model) - } - } - - // MARK: objc 方法 - - @objc func addClick() { - let create = QChatCreateGroupViewController() - create.serverId = serverid - weak var weakSelf = self - create.completion = { - weakSelf?.refreshData() - } - navigationController?.pushViewController(create, animated: true) - } - - @objc func toSort() { - let sort = QChatIdGroupSortController() - sort.serverId = serverid - sort.isOwer = isOwner - weak var weakSelf = self - sort.completion = { - weakSelf?.refreshData() - // weakSelf?.viewModel.datas.removeAll() - // for index in 0.. Void - -public class QChatMemberManagerController: NEBaseTableViewController, UITableViewDelegate, - UITableViewDataSource, ViewModelDelegate, QChatMemberSelectControllerDelegate { - let viewmodel = MemberManagerViewModel() - - var memberCount = 0 - - var serverId: UInt64? - - var roleId: UInt64? - - var countChangeBlock: MemberCountChange? - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - viewmodel.delegate = self - loadMoreData() - setupUI() - } - - func setupUI() { - title = localizable("qchat_manager_member") - view.backgroundColor = .white - setupTable() - tableView.delegate = self - tableView.dataSource = self - tableView.register( - QChatMemberManagerCell.self, - forCellReuseIdentifier: "\(QChatMemberManagerCell.self)" - ) - tableView.register( - QChatPlainTextArrowCell.self, - forCellReuseIdentifier: "\(QChatPlainTextArrowCell.self)" - ) - - let mjfooter = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) - mjfooter.stateLabel?.isHidden = true - tableView.mj_footer = mjfooter - } - - @objc func loadMoreData() { - if let rid = roleId, let sid = serverId { - viewmodel.getData(sid, rid) - } else { - fatalError("serverId or roleId is nil") - } - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - - // MARK: UITableViewDelegate, UITableViewDataSource,ViewModelDelegate,QChatMemberSelectControllerDelegate - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { - var param = GetExistingServerRoleMembersByAccidsParam() - param.serverId = serverId - param.accids = accid - param.roleId = roleId - print("param existing accid : ", accid as Any) - viewmodel.repo.getExistingServerRoleMembersByAccids(param) { error, accids in - NELog.infoLog(ModuleName + " " + self.className(), desc: #function + ", accids:\(accids)") -// print("getExistingServerRoleMembersByAccids : ", accids) - var dic = [String: String]() - var retAccids = [String]() - accids.forEach { aid in - dic[aid] = aid - } - accid?.forEach { aid in - if dic[aid] != nil { - retAccids.append(aid) - } - } - print("filter members : ", retAccids) - filterMembers(retAccids) - } - } - - public func dataDidChange() { - view.hideToastActivity() - tableView.mj_footer?.endRefreshing() - tableView.reloadData() - } - - public func dataNoMore() { - view.hideToastActivity() - tableView.mj_footer?.endRefreshingWithNoMoreData() - tableView.mj_footer?.isHidden = true - } - - public func dataDidError(_ error: Error) { - showToast(error.localizedDescription) - } - - public func numberOfSections(in tableView: UITableView) -> Int { - 2 - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 1 - } - if section == 1 { - return viewmodel.datas.count - } - return 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell: QChatPlainTextArrowCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatPlainTextArrowCell.self)", - for: indexPath - ) as! QChatPlainTextArrowCell - cell.titleLabel.text = localizable("add_member") - cell.detailLabel.text = "\(memberCount)" - return cell - } - - if indexPath.section == 1 { - let cell: QChatMemberManagerCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatMemberManagerCell.self)", - for: indexPath - ) as! QChatMemberManagerCell - let user = viewmodel.datas[indexPath.row] - cell.user = user - return cell - } - - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 50 - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - 0 - } - - public func tableView(_ tableView: UITableView, - heightForFooterInSection section: Int) -> CGFloat { - 0 - } - - public func tableView(_ tableView: UITableView, - viewForHeaderInSection section: Int) -> UIView? { - nil - } - - public func tableView(_ tableView: UITableView, - viewForFooterInSection section: Int) -> UIView? { - nil - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - weak var weakSelf = self - if indexPath.section == 0 { - let memberSelect = QChatMemberSelectController() - memberSelect.delegate = self - memberSelect.serverId = serverId - memberSelect.completion = { users in - print("member manager select: ", users) - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel - .addMembers(users, weakSelf?.serverId, weakSelf?.roleId) { successCount in - NELog.infoLog(ModuleName + " " + (weakSelf?.className() ?? "QChatMemberManagerController"), desc: "✅ CALLBACK SUCCESS") - // weakSelf?.view.hideToastActivity() - weakSelf?.showToast(localizable("qchat_add_success")) - if let block = weakSelf?.countChangeBlock, var count = weakSelf?.memberCount { - count += successCount - weakSelf?.memberCount = count - block(count) - } - } - } - navigationController?.pushViewController(memberSelect, animated: true) - } else { - let user = viewmodel.datas[indexPath.row] - showAlert(message: localizable("qchat_sure_delete_user")) { - if let rid = weakSelf?.roleId, let sid = weakSelf?.serverId { - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.remove(user, sid, rid) { - NELog.infoLog(ModuleName + " " + self.className(), desc: #function + ", serverId:\(sid)") - weakSelf?.view.hideToastActivity() - weakSelf?.viewmodel.datas.remove(at: indexPath.row) - weakSelf?.tableView.reloadData() - if var count = weakSelf?.memberCount, - let block = weakSelf?.countChangeBlock { - count -= 1 - weakSelf?.memberCount = count - block(count) - } - } - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatMemberSelectController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatMemberSelectController.swift deleted file mode 100644 index 03ec8558..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatMemberSelectController.swift +++ /dev/null @@ -1,288 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import MJRefresh - -typealias SelectMemeberCompletion = ([UserInfo]) -> Void -typealias FilterMembersBlock = ([UserInfo]) -> [UserInfo]? - -public protocol QChatMemberSelectControllerDelegate: NSObjectProtocol { - func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) -} - -// enum SelectType { -// case ServerMember -// case ChannelMember -// } - -public class QChatMemberSelectController: NEBaseTableViewController, MemberSelectViewModelDelegate, - UICollectionViewDelegate, UICollectionViewDataSource, - UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource, - ViewModelDelegate { - let viewmodel = MemberSelectViewModel() - var filterBlock: FilterMembersBlock? - var completion: SelectMemeberCompletion? - -// var selectType = SelectType.ServerMember - - var serverId: UInt64? - - var limit = 10 - - private let tag = "QChatMemberSelectController" - - public weak var delegate: QChatMemberSelectControllerDelegate? - - lazy var collection: UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .horizontal - layout.minimumLineSpacing = 0 - layout.minimumInteritemSpacing = 0 - let collect = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) - collect.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) - return collect - }() - - var collectionHeight: NSLayoutConstraint? - - var selectArray = [UserInfo]() - - override public func viewDidLoad() { - super.viewDidLoad() - viewmodel.delegate = self - loadData() - setupUI() - } - - func setupUI() { - edgesForExtendedLayout = [] - addRightAction(localizable("qchat_sure"), #selector(sureClick), self) - title = localizable("qchat_select") - view.addSubview(collection) - collection.delegate = self - collection.dataSource = self - collection.allowsMultipleSelection = false - collection.translatesAutoresizingMaskIntoConstraints = false - collectionHeight = collection.heightAnchor.constraint(equalToConstant: 0) - collectionHeight?.isActive = true - collection.backgroundColor = UIColor(hexString: "F2F4F5") - NSLayoutConstraint.activate([ - collection.topAnchor.constraint(equalTo: view.topAnchor), - collection.leftAnchor.constraint(equalTo: view.leftAnchor), - collection.rightAnchor.constraint(equalTo: view.rightAnchor), - ]) - - collection.register( - QChatUserUnCheckCell.self, - forCellWithReuseIdentifier: "\(NSStringFromClass(QChatUserUnCheckCell.self))" - ) - - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - tableView.topAnchor.constraint(equalTo: collection.bottomAnchor), - ]) - if #available(iOS 13.0, *) { - tableView.automaticallyAdjustsScrollIndicatorInsets = false - } else { - // Fallback on earlier versions - } - tableView.delegate = self - tableView.dataSource = self - tableView.register( - QChatSelectedCell.self, - forCellReuseIdentifier: "\(QChatSelectedCell.self)" - ) - - if #available(iOS 11.0,*) { - tableView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior - .never - } else { - automaticallyAdjustsScrollViewInsets = false - } - tableView.mj_footer = MJRefreshBackNormalFooter( - refreshingTarget: self, - refreshingAction: #selector(loadMoreData) - ) -// tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadData)) - } - - @objc func sureClick() { - if selectArray.count <= 0 { - view.makeToast(localizable("qchat_not_empty_select_memeber")) - return - } - if let block = completion { - block(selectArray) - } - navigationController?.popViewController(animated: true) - } - - @objc func loadData() { - viewmodel.loadFirst(serverId: serverId) { [weak self] error, users in - NELog.infoLog( - ModuleName + " " + (self?.tag ?? "QChatMemberSelectController"), - desc: "CALLBACK loadFirst " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - self?.tableView.reloadData() - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - } - } - } - - @objc func loadMoreData() { - viewmodel.loadMore(serverId: serverId) { [weak self] error, users in - NELog.infoLog( - ModuleName + " " + (self?.tag ?? "QChatMemberSelectController"), - desc: "CALLBACK loadMore " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } else { - if users?.count ?? 0 > 0 { - self?.tableView.reloadData() - self?.tableView.mj_footer?.endRefreshing() - } else { - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() - } - } - } - } - - // MARK: - - public func dataDidError(_ error: Error) { - view.makeToast(error.localizedDescription) - } - - public func dataDidChange() { - tableView.reloadData() - } - - public func collectionView(_ collectionView: UICollectionView, - numberOfItemsInSection section: Int) -> Int { - selectArray.count - } - - public func collectionView(_ collectionView: UICollectionView, - cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let user = selectArray[indexPath.row] - let cell = collectionView.dequeueReusableCell( - withReuseIdentifier: "\(NSStringFromClass(QChatUserUnCheckCell.self))", - for: indexPath - ) as? QChatUserUnCheckCell - cell?.configure(user) - return cell ?? UICollectionViewCell() - } - - public func collectionView(_ collectionView: UICollectionView, - didSelectItemAt indexPath: IndexPath) { - let user = selectArray[indexPath.row] - didUnselectContact(user) - } - - public func collectionView(_ collectionView: UICollectionView, - layout collectionViewLayout: UICollectionViewLayout, - sizeForItemAt indexPath: IndexPath) -> CGSize { - CGSize(width: 46, height: 52) - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - viewmodel.datas.count - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: QChatSelectedCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatSelectedCell.self)", - for: indexPath - ) as! QChatSelectedCell - let user = viewmodel.datas[indexPath.row] - cell.user = user - return cell - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 62 - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let user = viewmodel.datas[indexPath.row] - let cell = tableView.cellForRow(at: indexPath) as? QChatSelectedCell - - if user.select == true { - cell?.setUnselect() - didUnselectContact(user) - } else { - if selectArray.count >= limit { - // view.makeToast("超出\(limit)人限制") - showToast( - "\(localizable("exceed"))\(limit)\(localizable("person"))\(localizable("limit"))" - ) - return - } - cell?.setSelect() - didSelectContact(user) - } - // tableView.reloadRows(at: [indexPath], with: .none) - } - - func didSelectContact(_ user: UserInfo) { - user.select = true - if selectArray.contains(where: { c in - user === c - }) == false { - selectArray.append(user) - if let height = collectionHeight?.constant, height <= 0 { - collectionHeight?.constant = 52 - } - } - collection.reloadData() - tableView.reloadData() - refreshSelectCount() - } - - func didUnselectContact(_ user: UserInfo) { - user.select = false - selectArray.removeAll { c in - user === c - } - if selectArray.count <= 0 { - collection.reloadData() - collectionHeight?.constant = 0 - } - collection.reloadData() - tableView.reloadData() - refreshSelectCount() - } - - func refreshSelectCount() { - if selectArray.count > 0 { - rightNavBtn.setTitle("\(localizable("qchat_sure"))(\(selectArray.count))", for: .normal) - } else { - rightNavBtn.setTitle(localizable("qchat_sure"), for: .normal) - } - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - 0 - } - - // MARK: MemberSelectViewModelDelegate - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { - // 查询需要筛选的用户 - delegate?.filterMembers(accid: accid, filterMembers) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatPermissionViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatPermissionViewController.swift deleted file mode 100644 index 9c4dd2f1..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatPermissionViewController.swift +++ /dev/null @@ -1,308 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreIMKit - -typealias RoleUpdateCompletion = (_ role: ServerRole) -> Void -public class QChatPermissionViewController: NEBaseTableViewController, UITableViewDelegate, - UITableViewDataSource, QChatTextEditCellDelegate, ViewModelDelegate, QChatSwitchCellDelegate { - var idGroup: IdGroupModel? - - let viewmodel = PermissionViewModel() - - var serverName = "" - - var completion: RoleUpdateCompletion? - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - viewmodel.delegate = self - if let name = idGroup?.role?.name { - serverName = name - } - if let serverRole = idGroup?.role { - viewmodel.getData(serverRole) - } else { - fatalError("permission server role is nil ") - } - setupUI() - } - - func setupUI() { - if let type = idGroup?.role?.type, type != .everyone { - addRightAction(localizable("qchat_save"), #selector(savePermission), self) - } - - setupTable() - title = idGroup?.idName - tableView.backgroundColor = .ne_backcolor - tableView.delegate = self - tableView.dataSource = self - tableView.register( - QChatTextEditCell.self, - forCellReuseIdentifier: "\(QChatTextEditCell.self)" - ) - tableView.register(QChatSwitchCell.self, forCellReuseIdentifier: "\(QChatSwitchCell.self)") - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - - // MARK: UITableViewDelegate, UITableViewDataSource, QChatTextEditCellDelegate, ViewModelDelegate, QChatSwitchCellDelegate - - func didChangeSwitchValue(_ cell: QChatSwitchCell) { - print("did change switch value : ", cell) - if let key = cell.model?.permissionKey, - let value = cell.model?.permission?.value(forKey: key) as? String, - let type = ChatPermissionType(rawValue: value) { - updatePermission(type, cell.qSwitch.isOn) { success in - if success == false { - cell.qSwitch.isOn = !cell.qSwitch.isOn - } - } - } - } - - public func dataDidChange() { - tableView.reloadData() - } - - public func dataDidError(_ error: Error) { - showToast(error.localizedDescription) - } - - func textDidChange(_ textField: UITextField) { - if let text = textField.text { - serverName = text - } - } - - public func numberOfSections(in tableView: UITableView) -> Int { - 5 - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 1 - } - if section == 1 { - if let type = idGroup?.role?.type, type == .everyone { - return 0 - } - return 1 - } - if section == 2 { - return viewmodel.commons.count - } - if section == 3 { - return viewmodel.messages.count - } - if section == 4 { - return viewmodel.members.count - } - return 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell: QChatTextEditCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextEditCell.self)", - for: indexPath - ) as! QChatTextEditCell - if serverName.count > 0 { - cell.textFied.text = serverName - } else { - cell.textFied.text = nil - } - cell.textFied.placeholder = localizable("qchat_please_input_role_name") - cell.delegate = self - cell.limit = 20 - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - return cell - } - - if indexPath.section == 1 { - let cell: QChatTextArrowCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - cell.titleLabel.text = localizable("qchat_member") - cell.detailLabel.text = "\(idGroup?.role?.memberCount ?? 0)" - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - .union(CornerType.bottomLeft).union(CornerType.bottomRight) - return cell - } - - if indexPath.section == 2 || indexPath.section == 3 || indexPath.section == 4 { - let cell: QChatSwitchCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatSwitchCell.self)", - for: indexPath - ) as! QChatSwitchCell - var model: PermissionCellModel? - if indexPath.section == 2 { - model = viewmodel.commons[indexPath.row] - } else if indexPath.section == 3 { - model = viewmodel.messages[indexPath.row] - } else if indexPath.section == 4 { - model = viewmodel.members[indexPath.row] - } - cell.delegate = self - cell.model = model - return cell - } - - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - 50 - } - - public func tableView(_ tableView: UITableView, - viewForHeaderInSection section: Int) -> UIView? { - let header = QChatHeaderView() - switch section { - case 0: - header.titleLabel.text = localizable("qchat_group_name") - case 1: - if let type = idGroup?.role?.type, type == .everyone { - return nil - } - header.titleLabel.text = localizable("qchat_manager_member") - case 2: - header.titleLabel.text = localizable("qchat_common_permission") - case 3: - header.titleLabel.text = localizable("qchat_message_permission") - case 4: - header.titleLabel.text = localizable("qchat_member_permission") - default: - break - } - return header - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - if let type = idGroup?.role?.type, type == .everyone, section == 1 { - return 0 - } - return 40 - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 1 { - let memberManager = QChatMemberManagerController() - memberManager.serverId = idGroup?.role?.serverId - memberManager.roleId = idGroup?.role?.roleId - memberManager.memberCount = idGroup?.role?.memberCount ?? 0 - weak var weakSelf = self - memberManager.countChangeBlock = { count in - weakSelf?.idGroup?.role?.memberCount = count - if let role = weakSelf?.idGroup?.role, let block = weakSelf?.completion { - block(role) - } - tableView.reloadData() - } - navigationController?.pushViewController(memberManager, animated: true) - } - } - - // MAKR: objc 方法 - @objc func savePermission() { - if serverName.count <= 0 { - showToast(localizable("qchat_please_input_role_name")) - return - } - var param = UpdateServerRoleParam() - param.serverId = idGroup?.role?.serverId - if let rid = idGroup?.role?.roleId { - param.roleId = UInt64(rid) - } - param.name = serverName - - /* 批量逻辑,暂时不用 - let permissions = viewmodel.permission.getChangePermission() - var commonds = [StatusInfo]() - - permissions.forEach { (type: ChatPermissionType, value: Bool) in - var info = StatusInfo() - info.permissionType = type - if value == true { - info.status = .Allow - }else { - info.status = .Deny - } - commonds.append(info) - } - if commonds.count > 0 { - print("commonds : ", commonds) - print("commonds count :", commonds.count) - param.commands = commonds - } */ - - weak var weakSelf = self - viewmodel.repo.updateRole(param) { error, role in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } else { - if let block = weakSelf?.completion { - block(role) - } - weakSelf?.showToastInWindow(localizable("update_channel_suscess")) - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } -} - -extension QChatPermissionViewController { - func updatePermission(_ type: ChatPermissionType, _ open: Bool, - _ completion: @escaping (Bool) -> Void) { - var param = UpdateServerRoleParam() - param.serverId = idGroup?.role?.serverId - if let rid = idGroup?.role?.roleId { - param.roleId = UInt64(rid) - } - - var commonds = [StatusInfo]() - var info = StatusInfo() - info.permissionType = type - info.status = open == true ? .Allow : .Deny - commonds.append(info) - param.commands = commonds - - weak var weakSelf = self - view.makeToastActivity(.center) - viewmodel.repo.updateRole(param) { error, role in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - completion(false) - } else { - if let block = weakSelf?.completion { - completion(true) - block(role) - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatServerSettingViewController.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatServerSettingViewController.swift deleted file mode 100644 index f65228bf..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewController/QChatServerSettingViewController.swift +++ /dev/null @@ -1,494 +0,0 @@ - -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import UIKit -import NECoreKit -import NECoreIMKit -import NIMSDK - -typealias SaveSuccessBlock = (_ server: QChatServer?) -> Void - -public class QChatServerSettingViewController: NEBaseTableViewController, UITableViewDelegate, - UITableViewDataSource, UITextFieldDelegate, UINavigationControllerDelegate { - let viewModel = SettingViewModel() - var server: QChatServer? - - var headerImageUrl: String? - - var headerImage: NEUserHeaderView? - - lazy var serverNameInput: UITextField = getInput() - - lazy var serverThemeInput: UITextField = getInput() - - var topicInput: UITextField? - - private let className = "QChatServerSettingViewController" - - lazy var serverName: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 16.0) - label.textColor = .ne_darkText - return label - }() - - override public func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.navigationBar.isHidden = false - } - - override public func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - - NELog.infoLog(ModuleName + " " + className, desc: "server id : \(server?.serverId ?? 0)") - - setupUI() - addRightAction(localizable("save"), #selector(saveClick), self) - } - - func setupUI() { - title = localizable("qchat_setting") - view.backgroundColor = .ne_backcolor - setupTable() - tableView.bounces = false - tableView.tableHeaderView = headerView() - tableView.register( - QChatTextArrowCell.self, - forCellReuseIdentifier: "\(QChatTextArrowCell.self)" - ) - tableView.register( - QChatDestructiveCell.self, - forCellReuseIdentifier: "\(QChatDestructiveCell.self)" - ) - tableView.delegate = self - tableView.dataSource = self - } - - func headerView() -> UIView { - let headerBack = UIView() - headerBack.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 334) - headerBack.backgroundColor = .clear - - let cornerView = UIView() - cornerView.translatesAutoresizingMaskIntoConstraints = false - headerBack.addSubview(cornerView) - NSLayoutConstraint.activate([ - cornerView.topAnchor.constraint(equalTo: headerBack.topAnchor, constant: 22), - cornerView.leftAnchor.constraint(equalTo: headerBack.leftAnchor, constant: 20), - cornerView.rightAnchor.constraint(equalTo: headerBack.rightAnchor, constant: -20), - cornerView.heightAnchor.constraint(equalToConstant: 98), - ]) - cornerView.clipsToBounds = true - cornerView.layer.cornerRadius = 8 - cornerView.backgroundColor = .white - - let header = NEUserHeaderView(frame: .zero) - header.translatesAutoresizingMaskIntoConstraints = false - cornerView.addSubview(header) - NSLayoutConstraint.activate([ - header.widthAnchor.constraint(equalToConstant: 60), - header.heightAnchor.constraint(equalToConstant: 60), - header.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16), - header.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 16), - ]) - header.isUserInteractionEnabled = true - header.clipsToBounds = true - header.backgroundColor = UIColor.colorWithNumber(number: server?.serverId) - header.layer.cornerRadius = 30 - headerImage = header - if let icon = server?.icon { - header.sd_setImage(with: URL(string: icon), completed: nil) - } else { - if let name = server?.name { - header.setTitle(name) - } - } - - let cameraBtn = ExpandButton() - cornerView.addSubview(cameraBtn) - cameraBtn.translatesAutoresizingMaskIntoConstraints = false - cameraBtn.backgroundColor = .ne_backcolor - NSLayoutConstraint.activate([ - cameraBtn.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 58), - cameraBtn.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 58), - cameraBtn.widthAnchor.constraint(equalToConstant: 26), - cameraBtn.heightAnchor.constraint(equalToConstant: 26), - ]) - cameraBtn.layer.cornerRadius = 12 - cameraBtn.clipsToBounds = true - cameraBtn.layer.borderColor = UIColor.white.cgColor - cameraBtn.layer.borderWidth = 2 - cameraBtn.addTarget(self, action: #selector(cameraClick), for: .touchUpInside) - - let camera = UIImageView() - camera.translatesAutoresizingMaskIntoConstraints = false - cornerView.addSubview(camera) - camera.backgroundColor = .clear - camera.image = coreLoader.loadImage("camera") - NSLayoutConstraint.activate([ - camera.centerXAnchor.constraint(equalTo: cameraBtn.centerXAnchor), - camera.centerYAnchor.constraint(equalTo: cameraBtn.centerYAnchor, constant: -2), - ]) - - cornerView.addSubview(serverName) - NSLayoutConstraint.activate([ - serverName.leftAnchor.constraint(equalTo: header.rightAnchor, constant: 16), - serverName.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -16), - serverName.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 30), - ]) - serverName.text = server?.name - - let account = UILabel() - account.translatesAutoresizingMaskIntoConstraints = false - account.textColor = UIColor.ne_emptyTitleColor - account.font = UIFont.systemFont(ofSize: 12) - cornerView.addSubview(account) - NSLayoutConstraint.activate([ - account.leftAnchor.constraint(equalTo: serverName.leftAnchor), - account.rightAnchor.constraint(equalTo: serverName.rightAnchor), - account.topAnchor.constraint(equalTo: serverName.bottomAnchor, constant: 6), - ]) - account.text = "ID: \(server?.serverId ?? 0)" - - addInputView(headerBack, cornerView) - - return headerBack - } - - func addInputView(_ back: UIView, _ topView: UIView) { - let serverNameLabel = getTagLabel() - back.addSubview(serverNameLabel) - NSLayoutConstraint.activate([ - serverNameLabel.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 33), - serverNameLabel.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 16.0), - ]) - serverNameLabel.text = localizable("qchat_server_name") - - back.addSubview(serverNameInput) - NSLayoutConstraint.activate([ - serverNameInput.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), - serverNameInput.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), - serverNameInput.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 38), - serverNameInput.heightAnchor.constraint(equalToConstant: 50), - ]) - serverNameInput.placeholder = localizable("enter_name") - serverNameInput.tag = 50 - if let name = server?.name { - serverNameInput.text = name - } - - let serverThemeLabel = getTagLabel() - back.addSubview(serverThemeLabel) - NSLayoutConstraint.activate([ - serverThemeLabel.leftAnchor.constraint(equalTo: serverNameLabel.leftAnchor), - serverThemeLabel.topAnchor.constraint( - equalTo: serverNameInput.bottomAnchor, - constant: 16 - ), - ]) - serverThemeLabel.text = localizable("qchat_server_theme") - - back.addSubview(serverThemeInput) - NSLayoutConstraint.activate([ - serverThemeInput.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), - serverThemeInput.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), - serverThemeInput.topAnchor.constraint( - equalTo: serverNameInput.bottomAnchor, - constant: 38 - ), - serverThemeInput.heightAnchor.constraint(equalToConstant: 50), - ]) - serverThemeInput.placeholder = localizable("qchat_please_input_topic") - if let custom = server?.custom, let dic = getDictionaryFromJSONString(custom), - let topic = dic["topic"] as? String { - serverThemeInput.text = topic - } - serverThemeInput.tag = 64 - - let permissionLabel = getTagLabel() - back.addSubview(permissionLabel) - NSLayoutConstraint.activate([ - permissionLabel.leftAnchor.constraint(equalTo: serverThemeLabel.leftAnchor), - permissionLabel.topAnchor.constraint( - equalTo: serverThemeInput.bottomAnchor, - constant: 16 - ), - ]) - permissionLabel.text = localizable("qchat_permisssion") - } - - func getTagLabel() -> UILabel { - let label = UILabel() - label.textColor = UIColor(hexString: "666666") - label.font = UIFont.systemFont(ofSize: 12.0) - label.translatesAutoresizingMaskIntoConstraints = false - label.textAlignment = .left - return label - } - - func getInput() -> UITextField { - let textField = UITextField() - textField.backgroundColor = .white - textField.clipsToBounds = true - textField.layer.cornerRadius = 8 - textField.font = UIFont.systemFont(ofSize: 16.0) - textField.translatesAutoresizingMaskIntoConstraints = false - let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 0)) - textField.leftView = leftSpace - textField.leftViewMode = .always - textField.delegate = self - return textField - } - - // MARK: action - - @objc func cameraClick() { - // print("camera click") - showBottomAlert(self) - } - - @objc func saveClick() { - print("save click") - - var name = "" - - if let currentName = serverNameInput.text, currentName.count > 0 { - name = currentName - } else if let originServerName = server?.name, originServerName.count > 0 { - name = originServerName - } - - if name.count <= 0 { - showToast(localizable("qchat_not_empty_servername")) - return - } - - if let icon = headerImageUrl { - server?.icon = icon - } - - var serverParam = UpdateServerParam(name: name, icon: headerImageUrl) - - guard let sid = server?.serverId else { - showToast(localizable("serverId_notbe_empty")) - return - } - serverParam.serverId = sid - - if let topic = serverThemeInput.text, topic.count > 0 { - serverParam.custom = getJSONStringFromDictionary(["topic": topic]) - } - weak var weakSelf = self - - view.makeToastActivity(.center) - print("update param : ", serverParam) - QChatServerProvider.shared.updateServer(serverParam) { error in - print("update finish : ", error as Any) - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - - func leaveServer() { - if let serverid = server?.serverId { - weak var weakSelf = self - view.makeToastActivity(.center) - viewModel.repo.leaveServer(serverid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - NELog.errorLog(ModuleName + " " + self.className, desc: "leave server error : \(err)") - weakSelf?.view.makeToast(err.localizedDescription) - } else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - } - - func deleteServer() { - if let serverid = server?.serverId { - weak var weakSelf = self - view.makeToastActivity(.center) - QChatServerProvider.shared.deleteServer(serverid) { error in - print("delete result : ", error as Any) - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.view.makeToast(err.localizedDescription) - } else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - } - - // MARK: UITableViewDelegate, UITableViewDataSource,UITextFieldDelegate - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - let l = textField.tag - let text = "\(textField.text ?? "")\(string)" - print("count : ", text.count) - if text.count > l { - return false - } - return true - } - - public func numberOfSections(in tableView: UITableView) -> Int { - 2 - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - print("count section : ", section) - if section == 0 { - return viewModel.permissions.count - } else if section == 1 { - return 1 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let textCell: QChatTextArrowCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatTextArrowCell.self)", - for: indexPath - ) as! QChatTextArrowCell - let model = viewModel.permissions[indexPath.row] - textCell.titleLabel.text = model.title - textCell.backgroundColor = .clear - textCell.cornerType = model.cornerType - return textCell - } else if indexPath.section == 1 { - let destructiveCell: QChatDestructiveCell = tableView.dequeueReusableCell( - withIdentifier: "\(QChatDestructiveCell.self)", - for: indexPath - ) as! QChatDestructiveCell - - destructiveCell.redTextLabel - .text = isMyServer() ? localizable("qchat_delete_server") : - localizable("qchat_leave_server") - destructiveCell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - .union(CornerType.topLeft).union(CornerType.topRight) - return destructiveCell - } - - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 0 { - if indexPath.row == 1 { - let idGroupController = QChatIdGroupViewController() - idGroupController.serverid = server?.serverId - if let owner = server?.owner, owner == IMKitEngine.instance.imAccid { - idGroupController.isOwner = true - } - navigationController?.pushViewController(idGroupController, animated: true) - - } else if indexPath.row == 0 { - let memberCtrl = MemberListViewController() - memberCtrl.serverId = server?.serverId - navigationController?.pushViewController(memberCtrl, animated: true) - } - - } else if indexPath.section == 1 { - print("click delete") - weak var weakSelf = self - if isMyServer() == true { - showAlert(message: localizable("sure_delete_server")) { - weakSelf?.deleteServer() - } - } else { - showAlert(message: localizable("sure_exit_server")) { - weakSelf?.leaveServer() - } - } - } - } - - public func tableView(_ tableView: UITableView, - heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 48 - } else if indexPath.section == 1 { - return 40 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - viewForHeaderInSection section: Int) -> UIView? { - if section == 1 { - return UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 24)) - } - return nil - } - - public func tableView(_ tableView: UITableView, - heightForHeaderInSection section: Int) -> CGFloat { - if section == 1 { - return 24 - } - return 0 - } - - public func tableView(_ tableView: UITableView, - heightForFooterInSection section: Int) -> CGFloat { - 0 - } - - func isMyServer() -> Bool { - if let owner = server?.owner { - let accid = IMKitEngine.instance.imAccid - if owner == accid { - return true - } - } - return false - } - - // UINavigationControllerDelegate - func imagePickerController(_ picker: UIImagePickerController, - didFinishPickingMediaWithInfo info: [UIImagePickerController - .InfoKey: Any]) { - let image: UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage - uploadHeadImage(image: image) - picker.dismiss(animated: true, completion: nil) - } - - public func uploadHeadImage(image: UIImage) { - view.makeToastActivity(.center) - if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { - let filePath = NSHomeDirectory().appending("/Documents/") - .appending(IMKitEngine.instance.imAccid) - let succcess = imageData.write(toFile: filePath, atomically: true) - weak var weakSelf = self - if succcess { - NIMSDK.shared().resourceManager - .upload(filePath, progress: nil) { urlString, error in - if error == nil { - // 显示设置的照片 - weakSelf?.headerImage?.image = image - weakSelf?.headerImageUrl = urlString - weakSelf?.headerImage?.titleLabel.isHidden = true - print("upload image success") - } else { - print("upload image failed,error = \(error!)") - } - weakSelf?.view.hideToastActivity() - } - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/CreateGroupViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/CreateGroupViewModel.swift deleted file mode 100644 index f3e82131..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/CreateGroupViewModel.swift +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import NECoreIMKit - -@objcMembers -public class CreateGroupViewModel: NSObject { -// var limit = 7 - -// var limitUsers = [UserInfo]() - var allUsers = [UserInfo]() - let repo = QChatRepo() - private let className = "CreateGroupViewModel" - - weak var delegate: ViewModelDelegate? - - override init() {} - - func loadAllData() { - NELog.infoLog(ModuleName + " " + className, desc: #function) -// limitUsers.removeAll() -// limitUsers.append(contentsOf: allUsers) - } - - private func addUser(_ user: UserInfo) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(user.serverId ?? 0)") - allUsers.append(user) -// if limitUsers.count <= limit { -// limitUsers.append(user) -// } - } - - func addNewUser(_ user: UserInfo) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(user.serverId ?? 0)") - addUser(user) - filterData() - } - - func filterData() { - NELog.infoLog(ModuleName + " " + className, desc: #function) - allUsers.forEach { user in - user.cornerType = .none - } - if allUsers.count == 1, let first = allUsers.first { - first.cornerType = CornerType.topLeft.union(CornerType.topRight).union(.bottomLeft) - .union(.bottomRight) - } - - if allUsers.count > 1, let first = allUsers.first, let last = allUsers.last { - first.cornerType = .topLeft.union(.topRight) - last.cornerType = .bottomLeft.union(.bottomRight) - } - - /* - if limitUsers.count < limit { - if let last = limitUsers.last { - if limitUsers.count == 1 { - last.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - }else { - last.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - } - }else { - if let last = limitUsers.last { - last.cornerType = .none - } - } */ - - delegate?.dataDidChange() - } - - func removeData(_ index: Int) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", index:\(index)") - allUsers.remove(at: index) - filterData() - delegate?.dataDidChange() - } - - func addMembers(_ members: [UserInfo]) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", members.count:\(members.count)") - members.forEach { user in - if allUsers.contains(where: { lUser in - if let cid = lUser.serverMember?.accid, let mid = user.serverMember?.accid { - if cid == mid { - return true - } - } - return false - }) == false { - addUser(user) - } - } - filterData() - } - - func removeMember(_ member: UserInfo) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(member.serverId ?? 0)") - delegate?.dataDidChange() - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/EditMemberViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/EditMemberViewModel.swift deleted file mode 100644 index 706199b7..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/EditMemberViewModel.swift +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit -import NEQChatKit - -@objcMembers -public class EditMemberViewModel: NSObject { - var limitIdGroups = [IdGroupModel]() - var allIdGroups = [IdGroupModel]() - - var serverRoles = [ServerRole]() - var userRoles = [ServerRole]() - - var userDic = [UInt64: IdGroupModel]() - var serverDic = [UInt64: IdGroupModel]() - - var delegate: ViewModelDelegate? - - let repo = QChatRepo() - - var limit = 5 - - private let className = "EditMemberViewModel" - - override init() {} - - func checkoutCurrentUserRole(_ roleId: UInt64?) -> Bool { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", roleId:\(roleId ?? 0)") - if let rid = roleId { - if userDic[rid] != nil { - return true - } - } - return false - } - - func showServerData() { - NELog.infoLog(ModuleName + " " + className, desc: #function) - limitIdGroups.removeAll() - allIdGroups.removeAll() - serverRoles.forEach { role in - if let roleId = role.roleId { - if let model = self.serverDic[roleId] { - self.allIdGroups.append(model) - } - } - } - allIdGroups.first?.cornerType = .topLeft.union(.topRight) - if allIdGroups.count > limit { - limitIdGroups.append(contentsOf: allIdGroups.prefix(limit)) - } else { - limitIdGroups.append(contentsOf: allIdGroups) - if let last = limitIdGroups.last { - last.cornerType = last.cornerType.union(.bottomLeft).union(.bottomRight) - } - } - delegate?.dataDidChange() - } - - func filterAllRoles() { - NELog.infoLog(ModuleName + " " + className, desc: #function) - let serverModels = getRoleModel(serverRoles, nil) - serverModels.forEach { idModel in - if let roleId = idModel.role?.roleId { - self.serverDic[roleId] = idModel - } - } - } - - func filterUserRoles() { - NELog.infoLog(ModuleName + " " + className, desc: #function) - allIdGroups.append(contentsOf: getRoleModel(userRoles, true)) - allIdGroups.first?.cornerType = .topLeft.union(.topRight) - if allIdGroups.count > limit { - limitIdGroups.append(contentsOf: allIdGroups.prefix(limit)) - } else { - limitIdGroups.append(contentsOf: allIdGroups) - if let last = limitIdGroups.last { - last.cornerType = last.cornerType.union(.bottomLeft).union(.bottomRight) - } - } - allIdGroups.forEach { idModel in - if let roleId = idModel.role?.roleId { - self.userDic[roleId] = idModel - } - } - delegate?.dataDidChange() - } - - func getData(_ serverId: UInt64?, _ accid: String?) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - weak var weakSelf = self - - var accidParam = GetServerRolesByAccIdParam(serverId: serverId, accid: accid) - accidParam.limit = 200 - accidParam.timeTag = 0 - repo.getServerRolesByAccId(param: accidParam) { error, roles in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - print("edit member member role : ", roles as Any) - if let datas = roles { - weakSelf?.userRoles.append(contentsOf: datas) - weakSelf?.delegate?.dataDidChange() - weakSelf?.filterUserRoles() - } - } - } - - var param = GetServerRoleParam() - param.limit = 200 - param.serverId = serverId - - repo.getRoles(param) { error, roles, sets in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - print("edit member server roles : ", roles as Any) - if let datas = roles { - weakSelf?.serverRoles.append(contentsOf: datas) - weakSelf?.filterAllRoles() - } - } - } - } - - func getRoleModel(_ roles: [ServerRole]?, _ select: Bool?) -> [IdGroupModel] { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", roles.count:\(roles?.count ?? 0)") - var models = [IdGroupModel]() - roles?.forEach { role in - let model = IdGroupModel(role) - if let s = select { - model.isSelect = s - } - models.append(model) - } - return models - } - - func updateMyMember(_ serverId: UInt64?, _ nick: String?, - _ completion: @escaping (Error?, ServerMemeber) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = UpdateMyMemberInfoParam() - param.serverId = serverId - param.nick = nick - repo.updateMyServerMember(param, completion) - } - - func updateMember(_ serverId: UInt64?, _ nick: String?, _ accid: String?, - _ completion: @escaping (Error?, ServerMemeber) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = UpdateServerMemberInfoParam() - param.serverId = serverId - param.nick = nick - param.accid = accid - repo.updateServerMember(param, completion) - } - - func kickoutMember(_ serverId: UInt64?, _ accid: String?, - _ completion: @escaping (Error?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = KickServerMembersParam() - param.serverId = serverId - var accids = [String]() - if let acc = accid { - accids.append(acc) - param.accounts = accids - } - repo.kickoutServerMembers(param) { error in - completion(error) - } - } - - func addMembers(_ accid: String?, _ serverId: UInt64?, _ roleId: UInt64?, - _ completion: @escaping () -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", accid:\(accid ?? "nil")") - var param = AddServerRoleMemberParam() - param.serverId = serverId - param.roleId = roleId - var accids = [String]() - if let aid = accid { - accids.append(aid) - } - param.accountArray = accids - weak var weakSelf = self - - repo.addRoleMember(param) { error, successAccids, failedAccids in - print("add role member result : ", error as Any) - completion() - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - print("add members success accids : ", successAccids) - - if let rid = roleId, let model = weakSelf?.serverDic[rid] { - weakSelf?.userDic[rid] = model - } - weakSelf?.delegate?.dataDidChange() - } - } - } - - func remove(_ accid: String?, _ serverId: UInt64?, _ rid: UInt64?, - _ completion: @escaping () -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", accid:\(accid ?? "nil")") - var param = RemoveServerRoleMemberParam() - param.serverId = serverId - param.roleId = rid - weak var weakSelf = self - if let accid = accid { - param.accountArray = [accid] - repo.deleateRoleMember(param) { error, successAccids, failedAccids in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - if let roleId = rid { - print("add role id : ", roleId) - weakSelf?.userDic.removeValue(forKey: roleId) - } - weakSelf?.delegate?.dataDidChange() - } - completion() - } - } else { - completion() - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/IdGroupSortViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/IdGroupSortViewModel.swift deleted file mode 100644 index 6e85e372..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/IdGroupSortViewModel.swift +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import NECoreIMKit -import AVFoundation - -@objcMembers -public class IdGroupSortViewModel: NSObject { - let repo = QChatRepo() - - var datas = NSMutableArray() - -// var lockData = [IdGroupModel]() - - weak var delegate: ViewModelDelegate? - - var isOwner = false - - private let className = "IdGroupSortViewModel" - - func getData(_ serverId: UInt64?) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = GetServerRoleParam() - param.limit = 200 - param.serverId = serverId - weak var weakSelf = self - - repo.getRoles(param) { error, roles, sets in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - weakSelf?.filterData(roles, sets) - } - } - } - - func filterData(_ roles: [ServerRole]?, _ sets: Set?) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", roles.count:\(roles?.count ?? 0)") - weak var weakSelf = self - roles?.forEach { role in - if role.type == .everyone { - return - } - let model = IdGroupModel(role) - model.hasPermission = isOwner - if let rid = role.roleId, let s = sets, s.contains(NSNumber(value: rid)) == true { - isOwner = true - } - weakSelf?.datas.add(model) -// if model.hasPermission == true { -// weakSelf?.datas.add(model) -// }else { -// weakSelf?.lockData.append(model) -// } - } - weakSelf?.delegate?.dataDidChange() - } - - func removeRole(_ serverId: UInt64?, _ roleId: UInt64?, _ model: IdGroupModel, - _ completion: @escaping () -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = DeleteServerRoleParam() - param.serverId = serverId - param.roleId = roleId - weak var weakSelf = self - repo.deleteRoles(param) { error in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - weakSelf?.datas.remove(model) - weakSelf?.delegate?.dataDidChange() - completion() - } - } - } - - func saveSort(_ serverId: UInt64?, _ completion: @escaping () -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var startIndex = 0 - - var startSort = false - var last: IdGroupModel? - var items = [UpdateServerRolePriorityItem]() - - var min: Int? - - datas.forEach { data in - - if let model = data as? IdGroupModel, model.hasPermission == true { - print("model p : ", model.role?.priority as Any) - if let m = min, let p = model.role?.priority { - if m > p { - min = p - } - } else { - min = model.role?.priority - } - } - } - - print("print min : ", min as Any) - - for index in 0 ..< datas.count { - if let m = datas[index] as? IdGroupModel, let r = m.role { - if startSort == false, m.hasPermission == true { - startSort = true - if let m = min { - startIndex = m - } - } - if startSort == false { - } else { - let item = UpdateServerRolePriorityItem(r, startIndex) - items.append(item) - startIndex += 1 - print("item priority : ", startIndex) - } - last = m - print("item name : ", m.idName as Any) - } - } - - var param = UpdateServerRolePrioritiesParam() - param.updateItems = items - param.serverId = serverId - weak var weakSelf = self - - if items.count <= 1 { - completion() - return - } - - repo.updateServerRolePriorities(param) { error in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - completion() - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/IdGroupViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/IdGroupViewModel.swift deleted file mode 100644 index 6f8715fa..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/IdGroupViewModel.swift +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import NECoreIMKit - -typealias IdGroupViewModelBlock = () -> Void - -@objcMembers -public class IdGroupViewModel: NSObject { - let repo = QChatRepo() - var topDatas = [IdGroupModel]() - var datas = [IdGroupModel]() - var sortBtnCellDatas = [IdGroupModel]() // only one - weak var delegate: ViewModelDelegate? - - var limitCount = 20 - - private let className = "IdGroupViewModelBlock" - - override init() {} - - func getRoles(_ serverId: UInt64?, _ refresh: Bool = false, _ block: IdGroupViewModelBlock?) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = GetServerRoleParam() - param.serverId = serverId - param.limit = limitCount - if let last = datas.last, let pri = last.role?.priority, refresh == false { - param.priority = pri - } - weak var weakSelf = self - print("param : ", param) - - repo.getRoles(param) { error, roles, sets in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else if let rs = roles { - print("get roles success : ", rs.count) - weakSelf?.parseData(rs, refresh) - } - if let completion = block { - completion() - } - } - } - - func parseData(_ roles: [ServerRole], _ refresh: Bool) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", roles.count:\(roles.count)") - var models = [IdGroupModel]() - roles.forEach { role in - print("get data proprity : ", role.priority as Any) - let model = IdGroupModel(role) - models.append(model) - } - filterData(models, refresh) - if roles.count < limitCount { - delegate?.dataNoMore?() - } - } - - func filterData(_ models: [IdGroupModel], _ refresh: Bool) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", models.count:\(models.count)") - if refresh == true { - topDatas.removeAll() - datas.removeAll() - sortBtnCellDatas.removeAll() - } - - if let first = models.first { - topDatas.append(first) - } - if models.count >= 2 { - datas.append(contentsOf: models.suffix(models.count - 1)) - } - - if datas.count > 0 { - if let first = sortBtnCellDatas.first { - first.idName = "身份组(\(datas.count))" - } else { - let data = IdGroupModel() - data.idName = "身份组(\(datas.count))" - sortBtnCellDatas.append(data) - } - } - delegate?.dataDidChange() - } - - func addRole(_ role: ServerRole) { - var models = [IdGroupModel]() - models.append(contentsOf: topDatas) - models.append(contentsOf: datas) - models.append(IdGroupModel(role)) - topDatas.removeAll() - datas.removeAll() - filterData(models, false) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/MemberManagerViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/MemberManagerViewModel.swift deleted file mode 100644 index df6ffcb0..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/MemberManagerViewModel.swift +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NECoreIMKit -import NEQChatKit -import CoreMedia - -@objcMembers -public class MemberManagerViewModel: NSObject { - var datas = [UserInfo]() - - var delegate: ViewModelDelegate? - - let repo = QChatRepo() - - let limit = 20 - - private let className = "MemberManagerViewModel" - - override init() {} - - func getData(_ sid: UInt64?, _ rid: UInt64?, _ refresh: Bool = false) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", sid:\(sid ?? 0)") - var param = GetServerRoleMembersParam() - param.limit = limit - param.serverId = sid - param.roleId = rid - if let last = datas.last, let accid = last.accid, let createTime = last.createTime, - refresh == false { - param.accid = accid - param.timeTag = createTime - print("load more : ", param) - } else { - param.accid = "" - param.timeTag = 0 - print("first refresh : ", param) - } - weak var weakSelf = self - repo.getServerRoleMembers(param) { error, members in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - if refresh == true { - weakSelf?.datas.removeAll() - } - members.forEach { member in - let user = UserInfo(member) - weakSelf?.datas.append(user) - } - weakSelf?.delegate?.dataDidChange() - if let count = weakSelf?.limit, members.count < count { - weakSelf?.delegate?.dataNoMore?() - } - } - } - } - - func addMembers(_ users: [UserInfo], _ serverId: UInt64?, _ roleId: UInt64?, - _ completion: @escaping (Int) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", users.count:\(users.count)") - var param = AddServerRoleMemberParam() - param.serverId = serverId - param.roleId = roleId - var accids = [String]() - users.forEach { user in - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - param.accountArray = accids - weak var weakSelf = self - - repo.addRoleMember(param) { error, successAccids, failedAccids in - print("add role member result : ", error as Any) - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - weakSelf?.getData(serverId, roleId, true) - -// print("add members success accids : ", successAccids) -// var dic = [String: UserInfo]() -// users.forEach { user in -// print("for each role member : ", user.serverMember as Any) -// if let accid = user.serverMember?.accid { -// dic[accid] = user -// } -// } -// successAccids.forEach { accid in -// if let user = dic[accid] { -// print("add data user ", user) -// weakSelf?.datas.append(user) -// } -// } -// weakSelf?.delegate?.dataDidChange() - completion(successAccids.count) - } - } - } - - func remove(_ user: UserInfo, _ serverId: UInt64?, _ rid: UInt64?, - _ completion: @escaping () -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(user.serverId ?? 0)") - var param = RemoveServerRoleMemberParam() - param.serverId = serverId - param.roleId = rid - weak var weakSelf = self - if let accid = user.accid { - param.accountArray = [accid] - repo.deleateRoleMember(param) { error, successAccids, failedAccids in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - } else { - completion() - } - } - } else {} - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/MemberSelectViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/MemberSelectViewModel.swift deleted file mode 100644 index 35667f5c..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/MemberSelectViewModel.swift +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import NECoreIMKit - -@objc -public protocol MemberSelectViewModelDelegate: NSObjectProtocol { - func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) -} - -@objcMembers -public class MemberSelectViewModel: NSObject { - let repo = QChatRepo() - - var datas = [UserInfo]() - - weak var delegate: MemberSelectViewModelDelegate? - - var lastTimeTag: TimeInterval = 0 - - let pageSize = 50 - - private let className = "MemberSelectViewModel" - - override init() {} - - func loadFirst(serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - lastTimeTag = 0 - datas.removeAll() - print("self?.datas:\(datas.count)") - getServerMebers(serverId) { [weak self] error, userInfos in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "MemberSelectViewModel"), - desc: "CALLBACK getServerMebers " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - completion(error as NSError?, userInfos) - } else { - if let userArray = userInfos, !userArray.isEmpty { -// 判断有没设置delegate - if let del = self?.delegate { - self?.lastTimeTag = userArray.last?.serverMember?.createTime ?? 0 - var accids = [String]() - for user in userArray { - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - del.filterMembers(accid: accids) { filterAccids in - if let filterIds = filterAccids { - var tmp = [UserInfo]() - for user in userArray { - if filterIds.contains(user.serverMember?.accid ?? "") { - } else { - tmp.append(user) - self?.datas.append(user) - } - } - completion(error as NSError?, tmp) - } else { - self?.datas = userArray - completion(error as NSError?, userArray) - } - } - } else { - // 未设置 - self?.datas = userArray - completion(error as NSError?, userArray) - } - - } else { - // 结果为空 - completion(error as NSError?, userInfos) - } - } - } - } - - func loadMore(serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - getServerMebers(serverId) { [weak self] error, userInfos in - NELog.infoLog( - ModuleName + " " + (self?.className ?? "MemberSelectViewModel"), - desc: "CALLBACK getServerMebers " + (error?.localizedDescription ?? "no error") - ) - if error != nil { - completion(error as NSError?, userInfos) - } else { - if var userArray = userInfos, userArray.count > 0 { - if let del = self?.delegate { - self?.lastTimeTag = userArray.last?.serverMember?.createTime ?? 0 - var accids = [String]() - for user in userArray { - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - - del.filterMembers(accid: accids) { filterAccids in - var tmp = [UserInfo]() - for user in userArray { - if accids.contains(user.serverMember?.accid ?? "") { - } else { - tmp.append(user) - self?.datas.append(user) - } - } - completion(error as NSError?, tmp) - } - } else { - for u in userArray { - self?.datas.append(u) - } - completion(error as NSError?, userArray) - } - - } else { - // 结果为空 - completion(error as NSError?, userInfos) - } - } - } - } - - func getServerMebers(_ serverId: UInt64?, - completion: @escaping (NSError?, [UserInfo]?) -> Void) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverId ?? 0)") - var param = GetServerMembersByPageParam() - param.serverId = serverId - param.timeTag = lastTimeTag - param.limit = pageSize - repo.getServerMembers(param) { error, members in - var memberArray = [UserInfo]() - members.forEach { member in - memberArray.append(UserInfo(member)) - } - completion(error as NSError?, memberArray) - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/PermissionViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/PermissionViewModel.swift deleted file mode 100644 index cae71969..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/PermissionViewModel.swift +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit -import UIKit -import NECoreIMKit - -@objcMembers -public class PermissionViewModel: NSObject { - let permission = PermissionModel() - - var commons = [PermissionCellModel]() - - var messages = [PermissionCellModel]() - - var members = [PermissionCellModel]() - - let repo = QChatRepo() - - var delegate: ViewModelDelegate? - - var hasPermissionKey = [String: String]() - - private let className = "PermissionViewModel" - - override init() {} - - func getData(_ serverRole: ServerRole) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", serverId:\(serverRole.serverId ?? 0)") - weak var weakSelf = self -// print("get data authors : ", serverRole.auths as Any) - serverRole.auths?.forEach { info in - if info.status == .Allow { - if let key = info.permissionType?.rawValue { - weakSelf?.hasPermissionKey[key] = key - } - } - } - loadData(permission.commonPermission, permission.commonPermissionDic, &commons) - loadData(permission.messagePermission, permission.messagePermissionDic, &messages) - loadData(permission.memberPermission, permission.memberPermissionDic, &members) - -// delegate?.dataDidChange() - } - - func loadData(_ keys: [String], _ keyValues: [String: String], - _ datas: inout [PermissionCellModel]) { - NELog.infoLog(ModuleName + " " + className, desc: #function + ", keys.count:\(keys.count)") - for index in 0 ..< keys.count { - let model = PermissionCellModel() - model.permission = permission - let key = keys[index] - let name = keyValues[key] - model.showName = name - model.permissionKey = key - if let value = permission.value(forKey: key) as? String { - if hasPermissionKey[value] != nil { - model.hasPermission = true - } - } - datas.append(model) - if index == 0 { - model.cornerType = CornerType.topLeft.union(CornerType.topRight) - } - if index == keys.count - 1 { - model.cornerType = model.cornerType.union(.bottomLeft).union(.bottomRight) - } - } - } -} diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/SettingViewModel.swift b/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/SettingViewModel.swift deleted file mode 100644 index 62e919a3..00000000 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Server/ViewModel/SettingViewModel.swift +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -import Foundation -import NEQChatKit - -@objcMembers -public class SettingViewModel: NSObject { - let repo = QChatRepo() - var permissions = [SettingModel]() - override init() { - super.init() - NELog.infoLog(ModuleName + " " + className(), desc: #function) - let member = SettingModel() - member.title = localizable("qchat_member") - member.cornerType = CornerType.topLeft.union(CornerType.topRight) - permissions.append(member) - let idGroup = SettingModel() - idGroup.title = localizable("qchat_id_group") - idGroup.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - permissions.append(idGroup) - } -} diff --git a/NEQChatUIKit/NEQChatUIKit.podspec b/NERtcCallUIKit/NERtcCallUIKit.podspec similarity index 54% rename from NEQChatUIKit/NEQChatUIKit.podspec rename to NERtcCallUIKit/NERtcCallUIKit.podspec index 8d6d7fd2..419b1958 100644 --- a/NEQChatUIKit/NEQChatUIKit.podspec +++ b/NERtcCallUIKit/NERtcCallUIKit.podspec @@ -1,5 +1,5 @@ # -# Be sure to run `pod lib lint NEQChatUIKit.podspec' to ensure this is a +# Be sure to run `pod lib lint NERtcCallUIKit.podspec' to ensure this is a # valid spec before submitting. # # Any lines starting with a # are optional, but their use is encouraged @@ -7,8 +7,8 @@ # Pod::Spec.new do |s| - s.name = 'NEQChatUIKit' - s.version = '9.3.0' + s.name = 'NERtcCallUIKit' + s.version = '1.8.2' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -20,30 +20,25 @@ Pod::Spec.new do |s| s.description = <<-DESC TODO: Add long description of the pod here. DESC + s.homepage = 'http://netease.im' - s.license = { :'type' => 'Copyright', :'text' => ' Copyright 2022 Netease '} - s.author = 'yunxin engineering department' + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' + s.license = { :'type' => 'Copyright', :'text' => ' Copyright 2022 Netease ' } + s.author = "yunxin engineering department" s.source = { :git => 'ssh://git@g.hz.netease.com:22222/yunxin-app/xkit-ios.git', :tag => s.version.to_s } - s.pod_target_xcconfig = { - 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' - } - s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } - + # s.social_media_url = 'https://twitter.com/' + s.ios.deployment_target = '9.0' - s.swift_version = '5.0' - s.source_files = 'NEQChatUIKit/Classes/**/*' + s.source_files = 'NERtcCallUIKit/Classes/**/*' + s.resource = 'NERtcCallUIKit/Assets/**/*' -# s.resource_bundles = { -# 'NEQChatUIKit' => ['NEQChatUIKit/Assets/*.png'] -# } - s.resource = 'NEQChatUIKit/Assets/**/*' - s.dependency 'NECommonUIKit' - s.dependency 'NEQChatKit' - s.dependency 'SDWebImageWebPCoder' - s.dependency 'SDWebImageSVGKitPlugin' - s.dependency 'MJRefresh' - s.dependency 'NIMSDK_LITE' - s.dependency 'YXAlog_iOS' + s.dependency 'NERtcCallKit' + s.dependency 'NERtcSDK' + s.dependency 'AFNetworking' + s.dependency 'SDWebImage' + s.dependency 'Toast' + s.dependency 'NECoreKit' + s.dependency 'NECommonKit' end diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/.gitkeep b/NERtcCallUIKit/NERtcCallUIKit/Assets/.gitkeep similarity index 100% rename from NEQChatUIKit/NEQChatUIKit/Assets/.gitkeep rename to NERtcCallUIKit/NERtcCallUIKit/Assets/.gitkeep diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/Contents.json similarity index 100% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/Contents.json diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/Contents.json similarity index 79% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/Contents.json index 5c4d3b18..5ab63d7f 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/delete.imageset/Contents.json +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "avatar@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "avatar@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/avatar@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/avatar@2x.png new file mode 100644 index 00000000..e685ba2a Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/avatar@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/avatar@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/avatar@3x.png new file mode 100644 index 00000000..5bd90639 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/avator.imageset/avatar@3x.png differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/Contents.json similarity index 79% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/Contents.json index 5c4d3b18..ec2cf21c 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Commom/search.imageset/Contents.json +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x.png", + "filename" : "接听@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x.png", + "filename" : "接听@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/\346\216\245\345\220\254@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/\346\216\245\345\220\254@2x.png" new file mode 100644 index 00000000..64ac2161 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/\346\216\245\345\220\254@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/\346\216\245\345\220\254@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/\346\216\245\345\220\254@3x.png" new file mode 100644 index 00000000..3bfdc584 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_accept.imageset/\346\216\245\345\220\254@3x.png" differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/Contents.json new file mode 100644 index 00000000..fdc2dc0c --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "yx-tv-video-off-white@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "yx-tv-video-off-white@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/yx-tv-video-off-white@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/yx-tv-video-off-white@2x.png new file mode 100644 index 00000000..d91357f9 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/yx-tv-video-off-white@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/yx-tv-video-off-white@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/yx-tv-video-off-white@3x.png new file mode 100644 index 00000000..843db22b Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_off.imageset/yx-tv-video-off-white@3x.png differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/Contents.json similarity index 78% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/Contents.json index 53a2c560..211a7bbc 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/add.imageset/Contents.json +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x-4.png", + "filename" : "shooting@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x-4.png", + "filename" : "shooting@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/shooting@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/shooting@2x.png new file mode 100644 index 00000000..010147ad Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/shooting@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/shooting@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/shooting@3x.png new file mode 100644 index 00000000..cdd7488e Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_camera_on.imageset/shooting@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/Contents.json new file mode 100644 index 00000000..0b27130f --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "拒绝@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "拒绝@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/\346\213\222\347\273\235@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/\346\213\222\347\273\235@2x.png" new file mode 100644 index 00000000..b8c6562b Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/\346\213\222\347\273\235@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/\346\213\222\347\273\235@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/\346\213\222\347\273\235@3x.png" new file mode 100644 index 00000000..9b2be01a Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_cancel.imageset/\346\213\222\347\273\235@3x.png" differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/Contents.json new file mode 100644 index 00000000..afd788a4 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "关闭扬声器@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "关闭扬声器@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/\345\205\263\351\227\255\346\211\254\345\243\260\345\231\250@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/\345\205\263\351\227\255\346\211\254\345\243\260\345\231\250@2x.png" new file mode 100644 index 00000000..ddb16f10 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/\345\205\263\351\227\255\346\211\254\345\243\260\345\231\250@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/\345\205\263\351\227\255\346\211\254\345\243\260\345\231\250@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/\345\205\263\351\227\255\346\211\254\345\243\260\345\231\250@3x.png" new file mode 100644 index 00000000..6cdf7de0 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_off.imageset/\345\205\263\351\227\255\346\211\254\345\243\260\345\231\250@3x.png" differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Contents.json similarity index 77% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Contents.json index 535209c9..5e0bc1c1 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/photo.imageset/Contents.json +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x-2.png", + "filename" : "Group 361@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x-2.png", + "filename" : "Group 361@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Group 361@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Group 361@2x.png new file mode 100644 index 00000000..307c90f7 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Group 361@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Group 361@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Group 361@3x.png new file mode 100644 index 00000000..c390f5ff Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_speaker_on.imageset/Group 361@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/Contents.json new file mode 100644 index 00000000..8127486a --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "切换语音2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "切换语音2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/\345\210\207\346\215\242\350\257\255\351\237\2632@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/\345\210\207\346\215\242\350\257\255\351\237\2632@2x.png" new file mode 100644 index 00000000..af1e5bfe Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/\345\210\207\346\215\242\350\257\255\351\237\2632@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/\345\210\207\346\215\242\350\257\255\351\237\2632@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/\345\210\207\346\215\242\350\257\255\351\237\2632@3x.png" new file mode 100644 index 00000000..73cd43d0 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_audio.imageset/\345\210\207\346\215\242\350\257\255\351\237\2632@3x.png" differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/Contents.json new file mode 100644 index 00000000..89ecb081 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "翻转@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "翻转@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/\347\277\273\350\275\254@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/\347\277\273\350\275\254@2x.png" new file mode 100644 index 00000000..9e037707 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/\347\277\273\350\275\254@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/\347\277\273\350\275\254@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/\347\277\273\350\275\254@3x.png" new file mode 100644 index 00000000..1517a5f1 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_camera.imageset/\347\277\273\350\275\254@3x.png" differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/Contents.json new file mode 100644 index 00000000..12fa3918 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "切换视频2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "切换视频2@3x-1.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/\345\210\207\346\215\242\350\247\206\351\242\2212@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/\345\210\207\346\215\242\350\247\206\351\242\2212@2x.png" new file mode 100644 index 00000000..a218297e Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/\345\210\207\346\215\242\350\247\206\351\242\2212@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/\345\210\207\346\215\242\350\247\206\351\242\2212@3x-1.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/\345\210\207\346\215\242\350\247\206\351\242\2212@3x-1.png" new file mode 100644 index 00000000..3aa2a56b Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_switch_video.imageset/\345\210\207\346\215\242\350\247\206\351\242\2212@3x-1.png" differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/Contents.json new file mode 100644 index 00000000..f4e93508 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "话筒-关@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "话筒-关@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/\350\257\235\347\255\222-\345\205\263@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/\350\257\235\347\255\222-\345\205\263@2x.png" new file mode 100644 index 00000000..70dc6fbe Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/\350\257\235\347\255\222-\345\205\263@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/\350\257\235\347\255\222-\345\205\263@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/\350\257\235\347\255\222-\345\205\263@3x.png" new file mode 100644 index 00000000..6904ec93 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_off.imageset/\350\257\235\347\255\222-\345\205\263@3x.png" differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/Contents.json similarity index 78% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/Contents.json index cd88dea9..5bc88027 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/file.imageset/Contents.json +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "Frame@2x-3.png", + "filename" : "编组 8@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Frame@3x-3.png", + "filename" : "编组 8@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/\347\274\226\347\273\204 8@2x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/\347\274\226\347\273\204 8@2x.png" new file mode 100644 index 00000000..7e90f382 Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/\347\274\226\347\273\204 8@2x.png" differ diff --git "a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/\347\274\226\347\273\204 8@3x.png" "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/\347\274\226\347\273\204 8@3x.png" new file mode 100644 index 00000000..76e205dc Binary files /dev/null and "b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/call_voice_on.imageset/\347\274\226\347\273\204 8@3x.png" differ diff --git a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/sendMessage_failed.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/hangup.imageset/Contents.json similarity index 85% rename from NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/sendMessage_failed.imageset/Contents.json rename to NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/hangup.imageset/Contents.json index a1a85bc4..6fc2a5d9 100644 --- a/NEQChatUIKit/NEQChatUIKit/Assets/NEKitQChatUI.xcassets/Chat/sendMessage_failed.imageset/Contents.json +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/hangup.imageset/Contents.json @@ -1,11 +1,11 @@ { "images" : [ { - "filename" : "sendMessage_failed.png", "idiom" : "universal", "scale" : "1x" }, { + "filename" : "hangup@2x.png", "idiom" : "universal", "scale" : "2x" }, diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/hangup.imageset/hangup@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/hangup.imageset/hangup@2x.png new file mode 100644 index 00000000..184a1f49 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/hangup.imageset/hangup@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/Contents.json new file mode 100644 index 00000000..2981b974 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "micro_phone@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "micro_phone@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/micro_phone@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/micro_phone@2x.png new file mode 100644 index 00000000..6c130c79 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/micro_phone@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/micro_phone@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/micro_phone@3x.png new file mode 100644 index 00000000..a0cfbc68 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone.imageset/micro_phone@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/Contents.json new file mode 100644 index 00000000..f122345e --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "micro_phone_mute@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "micro_phone_mute@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/micro_phone_mute@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/micro_phone_mute@2x.png new file mode 100644 index 00000000..0a432b9a Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/micro_phone_mute@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/micro_phone_mute@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/micro_phone_mute@3x.png new file mode 100644 index 00000000..20b5f473 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/micro_phone_mute.imageset/micro_phone_mute@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/Contents.json new file mode 100644 index 00000000..3b4d9db4 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "speaker_off@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "speaker_off@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/speaker_off@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/speaker_off@2x.png new file mode 100644 index 00000000..d43f8722 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/speaker_off@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/speaker_off@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/speaker_off@3x.png new file mode 100644 index 00000000..5943ab7d Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_off.imageset/speaker_off@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/Contents.json new file mode 100644 index 00000000..0b9fdef0 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "speaker_on@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "speaker_on@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/speaker_on@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/speaker_on@2x.png new file mode 100644 index 00000000..6e733c16 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/speaker_on@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/speaker_on@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/speaker_on@3x.png new file mode 100644 index 00000000..1cbf05b3 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/speaker_on.imageset/speaker_on@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/Contents.json new file mode 100644 index 00000000..c960c77a --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "switch_audio@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "switch_audio@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/switch_audio@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/switch_audio@2x.png new file mode 100644 index 00000000..a160cbd1 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/switch_audio@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/switch_audio@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/switch_audio@3x.png new file mode 100644 index 00000000..b29fc41b Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_audio.imageset/switch_audio@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/Contents.json new file mode 100644 index 00000000..0ff6f492 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "switch_video@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "switch_video@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/switch_video@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/switch_video@2x.png new file mode 100644 index 00000000..0c2b7362 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/switch_video@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/switch_video@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/switch_video@3x.png new file mode 100644 index 00000000..d1ef4bf5 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/switch_video.imageset/switch_video@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings b/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings new file mode 100644 index 00000000..9ab47fd7 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings @@ -0,0 +1,37 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + + +"switch_to_audio"="Switch to audio"; +"switch_to_video"="Switch to video"; +"accept_failed"="Answer Failed"; +"network_error"="Network error, try later"; +"switch_error"="Switch Error"; +"remote_cancel"="Cancelled by the opposite"; +"remote_busy"="Busy-line"; +"remote_timeout"="No Responding"; +"remote_reject"="Reject"; +"other_client_accept"="Accept by other client"; +"other_client_reject"="Reject by other client"; + +"permission"="Permission Require"; +"reject"="Reject"; +"agree"="Agree"; +"audio_to_video"="Opposite requests to switch to video, have to turn on your camera"; +"video_to_audio"="Opposite requests to switch to audio, will turn off your camera directly"; +"reject_tip"="Request Denied"; + +"invite_audio_call"="Invite for audio call"; +"invite_video_call"="Invite for video call"; + +"waitting_remote_response"="Waiting for response"; +"call_cancel"="Cancel"; +"call_reject"="Reject"; +"call_accept"="Accept"; +"call_micro_phone"="Microphone"; +"call_speaker"="Speaker"; +"waitting_remote_accept"="Waitting to connect"; +"calling"="Calling"; +"cancel_failed"="The invitation has been accepted and cannot be canceled"; diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings new file mode 100644 index 00000000..bbac656f --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,36 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +"switch_to_audio"="切换到语音通话"; +"switch_to_video"="切换到视频通话"; +"accept_failed"="接听失败"; +"network_error"="网络连接异常,请稍后再试"; +"switch_error"="切换失败"; +"remote_cancel"="对方取消"; +"remote_busy"="对方占线"; +"remote_timeout"="对方超时未响应"; +"remote_reject"="对方已经拒绝"; +"other_client_accept"="已被其他端接受"; +"other_client_reject"="已被其他端拒绝"; + +"permission"="权限请求"; +"reject"="拒绝"; +"agree"="同意"; +"audio_to_video"="对方请求将音频转为视频,需要打开您的摄像头。"; +"video_to_audio"="对方请求将视频转为音频,将直接关闭您的摄像头。"; +"reject_tip"="对方拒绝了您请求"; + +"invite_audio_call"="邀请您音频通话"; +"invite_video_call"="邀请您视频通话"; + +"waitting_remote_response"="正在等待对方响应..."; +"call_cancel"="取消"; +"call_reject"="拒绝"; +"call_accept"="接听"; +"call_micro_phone"="麦克风"; +"call_speaker"="扬声器"; +"waitting_remote_accept"="等待对方接听……"; +"calling"="正在呼叫"; +"cancel_failed"="邀请已接受无法取消"; diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/.gitkeep b/NERtcCallUIKit/NERtcCallUIKit/Classes/.gitkeep similarity index 100% rename from NEQChatUIKit/NEQChatUIKit/Classes/.gitkeep rename to NERtcCallUIKit/NERtcCallUIKit/Classes/.gitkeep diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioCallingController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioCallingController.h new file mode 100644 index 00000000..db1682db --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioCallingController.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallUIStateController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NEAudioCallingController : NECallUIStateController + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioCallingController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioCallingController.m new file mode 100644 index 00000000..5e2a907a --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioCallingController.m @@ -0,0 +1,54 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEAudioCallingController.h" + +@interface NEAudioCallingController () + +@end + +@implementation NEAudioCallingController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)setupUI { + [super setupUI]; + [self setupCenterRemoteAvator]; + + /// 取消按钮 + [self.view addSubview:self.cancelBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.cancelBtn.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [self.cancelBtn.widthAnchor constraintEqualToConstant:self.buttonSize.width], + [self.cancelBtn.heightAnchor constraintEqualToConstant:self.buttonSize.height], + [self.cancelBtn.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-80 * self.factor] + ]]; + + [self.view addSubview:self.microphoneBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.microphoneBtn.centerYAnchor constraintEqualToAnchor:self.cancelBtn.centerYAnchor], + [self.microphoneBtn.centerXAnchor + constraintEqualToAnchor:self.view.centerXAnchor + constant:-self.view.frame.size.width / 4.0 - 20], + [self.microphoneBtn.widthAnchor constraintEqualToConstant:self.buttonSize.width], + [self.microphoneBtn.heightAnchor constraintEqualToConstant:self.buttonSize.height] + ]]; + + [self.view addSubview:self.speakerBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.speakerBtn.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor + constant:self.view.frame.size.width / 4.0 + 20], + [self.speakerBtn.centerYAnchor constraintEqualToAnchor:self.cancelBtn.centerYAnchor], + [self.speakerBtn.heightAnchor constraintEqualToConstant:self.buttonSize.height], + [self.speakerBtn.widthAnchor constraintEqualToConstant:self.buttonSize.width] + ]]; + + [self setupAudioCallingUI]; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioInCallController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioInCallController.h new file mode 100644 index 00000000..b19cddf0 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioInCallController.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallUIStateController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NEAudioInCallController : NECallUIStateController + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioInCallController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioInCallController.m new file mode 100644 index 00000000..b91a66ab --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEAudioInCallController.m @@ -0,0 +1,24 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEAudioInCallController.h" + +@interface NEAudioInCallController () + +@end + +@implementation NEAudioInCallController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)setupUI { + [super setupUI]; + [self setupCenterRemoteAvator]; + [self setupAudioInCallUI]; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h new file mode 100644 index 00000000..8fbc58c5 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h @@ -0,0 +1,83 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import "NECallParam.h" +#import "NECustomButton.h" +#import "NERtcCallUIConfig.h" +#import "NEVideoOperationView.h" +#import "NEVideoView.h" +@class NECallViewController; +NS_ASSUME_NONNULL_BEGIN + +@interface NECallUIStateController : UIViewController + +@property(strong, nonatomic) NEVideoView *smallVideoView; +@property(strong, nonatomic) NEVideoView *bigVideoView; +@property(strong, nonatomic) UIImageView *remoteAvatorView; +@property(strong, nonatomic) UIImageView *remoteBigAvatorView; +@property(strong, nonatomic) UILabel *titleLabel; +@property(strong, nonatomic) UILabel *centerTitleLabel; +@property(strong, nonatomic) UILabel *subTitleLabel; +@property(strong, nonatomic) UILabel *centerSubtitleLabel; + +/// 取消呼叫 +@property(strong, nonatomic) NECustomButton *cancelBtn; +/// 拒绝接听 +@property(strong, nonatomic) NECustomButton *rejectBtn; +/// 接听 +@property(strong, nonatomic) NECustomButton *acceptBtn; +/// 麦克风 +@property(strong, nonatomic) NECustomButton *microphoneBtn; +/// 扬声器 +@property(strong, nonatomic) NECustomButton *speakerBtn; + +@property(strong, nonatomic) NEVideoOperationView *operationView; + +// YES 主叫 NO 被叫 +@property(nonatomic, assign) BOOL isCaller; + +@property(nonatomic, weak) NECallParam *callParam; + +@property(nonatomic, weak) NECallUIConfig *config; + +@property(nonatomic, assign) CGFloat statusHeight; + +@property(assign, nonatomic) CGFloat radius; + +@property(assign, nonatomic) CGFloat titleFontSize; + +@property(assign, nonatomic) CGFloat subTitleFontSize; + +@property(assign, nonatomic) CGFloat factor; + +@property(assign, nonatomic) CGSize buttonSize; + +@property(nonatomic, assign) NERtcCallType callType; + +@property(nonatomic, weak) NECallViewController *mainController; + +@property(nonatomic, strong) NSBundle *bundle; + +- (void)setupUI; + +- (void)setupCenterRemoteAvator; + +- (void)setupVideoCallingUI; + +- (void)setupAudioCallingUI; + +- (void)setupCalledUI; + +- (void)setupAudioInCallUI; + +- (NSString *)getInviteText; + +- (void)refreshUI; + +- (void)refreshVideoView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m new file mode 100644 index 00000000..e7b18d40 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m @@ -0,0 +1,410 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallUIStateController.h" +#import +#import +#import +#import "NECallViewController.h" + +@interface NECallUIStateController () + +@property(nonatomic, weak) UIView *parentView; + +@end + +@implementation NECallUIStateController + +- (instancetype)init { + self = [super init]; + if (self) { + self.factor = 1; + self.radius = 4.0; + self.titleFontSize = 20.0; + self.subTitleFontSize = 14.0; + self.buttonSize = CGSizeMake(75, 103); + self.bundle = [NSBundle bundleForClass:self.class]; + } + return self; +} + +//- (void)loadView { +// NSLog(@"state view load parent view %@",self.parentView); +// self.view = self.parentView; +//} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + self.view.backgroundColor = [UIColor clearColor]; + if (self.view.frame.size.height < 600) { + self.factor = 0.5; + } + self.statusHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; + [self setupUI]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before +navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +#pragma mark lazy init + +- (NEVideoView *)bigVideoView { + if (!_bigVideoView) { + _bigVideoView = [[NEVideoView alloc] init]; + _bigVideoView.backgroundColor = [UIColor darkGrayColor]; + _bigVideoView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _bigVideoView; +} + +- (NEVideoView *)smallVideoView { + if (!_smallVideoView) { + _smallVideoView = [[NEVideoView alloc] init]; + _smallVideoView.backgroundColor = [UIColor darkGrayColor]; + UITapGestureRecognizer *tap = + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(switchVideoView:)]; + [_smallVideoView addGestureRecognizer:tap]; + _smallVideoView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _smallVideoView; +} + +- (void)switchVideoView:(UITapGestureRecognizer *)tap { + self.mainController.showMyBigView = !self.mainController.showMyBigView; + [self refreshVideoView]; + // TODO: 代码整理 + // [self changeDefaultImage:self.operationView.cameraBtn.selected]; +} + +- (UIImageView *)remoteAvatorView { + if (!_remoteAvatorView) { + _remoteAvatorView = [[UIImageView alloc] init]; + _remoteAvatorView.image = [UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _remoteAvatorView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _remoteAvatorView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont boldSystemFontOfSize:self.titleFontSize]; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.textAlignment = NSTextAlignmentRight; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _titleLabel; +} + +- (UILabel *)subTitleLabel { + if (!_subTitleLabel) { + _subTitleLabel = [[UILabel alloc] init]; + _subTitleLabel.font = [UIFont boldSystemFontOfSize:self.subTitleFontSize]; + _subTitleLabel.textColor = [UIColor whiteColor]; + _subTitleLabel.text = [self localizableWithKey:@"waitting_remote_response"]; + _subTitleLabel.textAlignment = NSTextAlignmentRight; + _subTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _subTitleLabel; +} + +- (NECustomButton *)cancelBtn { + if (!_cancelBtn) { + _cancelBtn = [[NECustomButton alloc] init]; + _cancelBtn.titleLabel.text = [self localizableWithKey:@"call_cancel"]; + _cancelBtn.imageView.image = [UIImage imageNamed:@"call_cancel" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _cancelBtn.maskBtn.accessibilityIdentifier = @"cancel_btn"; + [_cancelBtn.maskBtn addTarget:self.mainController + action:@selector(cancelEvent:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _cancelBtn; +} + +- (NECustomButton *)rejectBtn { + if (!_rejectBtn) { + _rejectBtn = [[NECustomButton alloc] init]; + _rejectBtn.titleLabel.text = [self localizableWithKey:@"call_reject"]; + _rejectBtn.imageView.image = [UIImage imageNamed:@"call_cancel" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _rejectBtn.maskBtn.accessibilityIdentifier = @"reject_btn"; + [_rejectBtn.maskBtn addTarget:self.mainController + action:@selector(rejectEvent:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _rejectBtn; +} + +- (NECustomButton *)acceptBtn { + if (!_acceptBtn) { + _acceptBtn = [[NECustomButton alloc] init]; + _acceptBtn.titleLabel.text = [self localizableWithKey:@"call_accept"]; + _acceptBtn.imageView.image = [UIImage imageNamed:@"call_accept" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _acceptBtn.imageView.contentMode = UIViewContentModeCenter; + _acceptBtn.maskBtn.accessibilityIdentifier = @"accept_btn"; + [_acceptBtn.maskBtn addTarget:self.mainController + action:@selector(acceptEvent:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _acceptBtn; +} + +- (NECustomButton *)microphoneBtn { + if (nil == _microphoneBtn) { + _microphoneBtn = [[NECustomButton alloc] init]; + _microphoneBtn.titleLabel.text = [self localizableWithKey:@"call_micro_phone"]; + _microphoneBtn.imageView.image = [UIImage imageNamed:@"micro_phone" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _microphoneBtn.imageView.highlightedImage = [UIImage imageNamed:@"micro_phone_mute" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _microphoneBtn.imageView.contentMode = UIViewContentModeCenter; + _microphoneBtn.maskBtn.accessibilityIdentifier = @"micro_phone"; + [_microphoneBtn.maskBtn addTarget:self.mainController + action:@selector(microphoneBtnClick:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _microphoneBtn; +} + +- (NECustomButton *)speakerBtn { + if (nil == _speakerBtn) { + _speakerBtn = [[NECustomButton alloc] init]; + _speakerBtn.titleLabel.text = [self localizableWithKey:@"call_speaker"]; + _speakerBtn.imageView.image = [UIImage imageNamed:@"speaker_off" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _speakerBtn.imageView.highlightedImage = [UIImage imageNamed:@"speaker_on" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _speakerBtn.imageView.contentMode = UIViewContentModeCenter; + _speakerBtn.maskBtn.accessibilityIdentifier = @"speaker"; + [_speakerBtn.maskBtn addTarget:self.mainController + action:@selector(speakerBtnClick:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _speakerBtn; +} + +- (UILabel *)centerSubtitleLabel { + if (nil == _centerSubtitleLabel) { + _centerSubtitleLabel = [[UILabel alloc] init]; + _centerSubtitleLabel.textColor = [UIColor whiteColor]; + _centerSubtitleLabel.font = [UIFont systemFontOfSize:self.subTitleFontSize]; + _centerSubtitleLabel.text = [self localizableWithKey:@"waitting_remote_accept"]; + _centerSubtitleLabel.textAlignment = NSTextAlignmentCenter; + _centerSubtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _centerSubtitleLabel; +} + +- (UILabel *)centerTitleLabel { + if (nil == _centerTitleLabel) { + _centerTitleLabel = [[UILabel alloc] init]; + _centerTitleLabel.textColor = [UIColor whiteColor]; + _centerTitleLabel.font = [UIFont systemFontOfSize:self.titleFontSize]; + _centerTitleLabel.textAlignment = NSTextAlignmentCenter; + _centerTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _centerTitleLabel; +} + +- (UIImageView *)remoteBigAvatorView { + if (nil == _remoteBigAvatorView) { + _remoteBigAvatorView = [[UIImageView alloc] init]; + _remoteBigAvatorView.image = [UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + _remoteBigAvatorView.clipsToBounds = YES; + _remoteBigAvatorView.layer.cornerRadius = self.radius; + _remoteBigAvatorView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _remoteBigAvatorView; +} + +#pragma mark - publick + +- (void)setupCenterRemoteAvator { + [self.view addSubview:self.centerSubtitleLabel]; + + [NSLayoutConstraint activateConstraints:@[ + [self.centerSubtitleLabel.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.centerSubtitleLabel.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.centerSubtitleLabel.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-(233 * self.factor + 163)], + [self.centerSubtitleLabel.heightAnchor constraintEqualToConstant:self.titleFontSize + 2] + ]]; + + [self.view addSubview:self.centerTitleLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.centerTitleLabel.bottomAnchor constraintEqualToAnchor:self.centerSubtitleLabel.topAnchor + constant:-10 * self.factor], + [self.centerTitleLabel.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.centerTitleLabel.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.centerTitleLabel.heightAnchor constraintEqualToConstant:self.titleFontSize + 2] + + ]]; + + [self.view addSubview:self.remoteBigAvatorView]; + [NSLayoutConstraint activateConstraints:@[ + [self.remoteBigAvatorView.heightAnchor constraintEqualToConstant:90], + [self.remoteBigAvatorView.widthAnchor constraintEqualToConstant:90], + [self.remoteBigAvatorView.bottomAnchor constraintEqualToAnchor:self.centerTitleLabel.topAnchor + constant:-10 * self.factor], + [self.remoteBigAvatorView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] + ]]; + + if (self.callParam.remoteAvatar.length <= 0) { + UIView *cover = [self getDefaultHeaderView:self.callParam.remoteUserAccid + font:[UIFont systemFontOfSize:self.titleFontSize] + showName:self.callParam.remoteShowName]; + [self.remoteBigAvatorView addSubview:cover]; + [NSLayoutConstraint activateConstraints:@[ + [cover.leftAnchor constraintEqualToAnchor:self.remoteBigAvatorView.leftAnchor], + [cover.rightAnchor constraintEqualToAnchor:self.remoteBigAvatorView.rightAnchor], + [cover.topAnchor constraintEqualToAnchor:self.remoteBigAvatorView.topAnchor], + [cover.bottomAnchor constraintEqualToAnchor:self.remoteBigAvatorView.bottomAnchor] + ]]; + } +} + +- (void)setupUI { +} + +- (void)refreshUI { +} + +- (void)setupVideoCallingUI { + self.titleLabel.text = [NSString stringWithFormat:@"%@ %@", [self localizableWithKey:@"calling"], + self.callParam.remoteShowName]; + self.subTitleLabel.text = [self localizableWithKey:@"waitting_remote_accept"]; + + if (self.callParam.remoteAvatar.length <= 0) { + UIView *cover = [self getDefaultHeaderView:self.callParam.remoteUserAccid + font:[UIFont systemFontOfSize:self.titleFontSize] + showName:self.callParam.remoteShowName]; + [self.remoteAvatorView addSubview:cover]; + [NSLayoutConstraint activateConstraints:@[ + [cover.leftAnchor constraintEqualToAnchor:self.remoteAvatorView.leftAnchor], + [cover.rightAnchor constraintEqualToAnchor:self.remoteAvatorView.rightAnchor], + [cover.topAnchor constraintEqualToAnchor:self.remoteAvatorView.topAnchor], + [cover.bottomAnchor constraintEqualToAnchor:self.remoteAvatorView.bottomAnchor] + ]]; + } else { + [self.remoteAvatorView sd_setImageWithURL:[NSURL URLWithString:self.callParam.remoteAvatar] + placeholderImage:[UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]]; + } +} + +- (void)setupAudioCallingUI { + self.centerTitleLabel.text = + [NSString stringWithFormat:@"%@ %@", [self localizableWithKey:@"calling"], + self.callParam.remoteShowName]; + self.centerSubtitleLabel.text = [self localizableWithKey:@"waitting_remote_accept"]; + if (self.callParam.remoteAvatar.length <= 0) { + UIView *cover = [self getDefaultHeaderView:self.callParam.remoteUserAccid + font:[UIFont systemFontOfSize:self.titleFontSize] + showName:self.callParam.remoteShowName]; + [self.remoteBigAvatorView addSubview:cover]; + [NSLayoutConstraint activateConstraints:@[ + [cover.leftAnchor constraintEqualToAnchor:self.remoteBigAvatorView.leftAnchor], + [cover.rightAnchor constraintEqualToAnchor:self.remoteBigAvatorView.rightAnchor], + [cover.topAnchor constraintEqualToAnchor:self.remoteBigAvatorView.topAnchor], + [cover.bottomAnchor constraintEqualToAnchor:self.remoteBigAvatorView.bottomAnchor] + ]]; + } else { + [self.remoteBigAvatorView sd_setImageWithURL:[NSURL URLWithString:self.callParam.remoteAvatar] + placeholderImage:[UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]]; + } +} + +- (void)setupAudioInCallUI { + [self.remoteBigAvatorView sd_setImageWithURL:[NSURL URLWithString:self.callParam.remoteAvatar] + placeholderImage:[UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]]; + self.centerTitleLabel.text = [NSString stringWithFormat:@"%@", self.callParam.remoteShowName]; + self.centerSubtitleLabel.hidden = YES; +} + +- (void)setupCalledUI { + self.centerTitleLabel.text = [NSString stringWithFormat:@"%@", self.callParam.remoteShowName]; +} + +- (NSString *)getInviteText { + return (self.callType == NERtcCallTypeAudio ? [self localizableWithKey:@"invite_audio_call"] + : [self localizableWithKey:@"invite_video_call"]); +} + +- (void)refreshVideoView { + if (self.mainController.showMyBigView) { + [[NERtcCallKit sharedInstance] setupLocalView:self.bigVideoView.videoView]; + [[NERtcCallKit sharedInstance] setupRemoteView:self.smallVideoView.videoView + forUser:self.callParam.remoteUserAccid]; + NSLog(@"show my big view"); + self.smallVideoView.maskView.hidden = self.mainController.remoteCameraAvailable; + self.bigVideoView.maskView.hidden = !self.operationView.cameraBtn.selected; + self.bigVideoView.userID = self.callParam.currentUserAccid; + self.smallVideoView.userID = self.callParam.remoteUserAccid; + } else { + [[NERtcCallKit sharedInstance] setupLocalView:self.smallVideoView.videoView]; + [[NERtcCallKit sharedInstance] setupRemoteView:self.bigVideoView.videoView + forUser:self.callParam.remoteUserAccid]; + NSLog(@"show my small view"); + self.bigVideoView.maskView.hidden = self.mainController.remoteCameraAvailable; + self.smallVideoView.maskView.hidden = !self.operationView.cameraBtn.selected; + self.bigVideoView.userID = self.callParam.remoteUserAccid; + self.smallVideoView.userID = self.callParam.currentUserAccid; + } +} + +- (UIView *)getDefaultHeaderView:(NSString *)accid + font:(UIFont *)font + showName:(NSString *)showName { + UIView *headerView = [[UIView alloc] init]; + headerView.backgroundColor = [UIColor colorWithStringWithString:accid]; + headerView.translatesAutoresizingMaskIntoConstraints = NO; + NSString *show = showName.length > 0 ? showName : accid; + if (show.length >= 2) { + UILabel *label = [[UILabel alloc] init]; + label.translatesAutoresizingMaskIntoConstraints = NO; + [headerView addSubview:label]; + label.textColor = [UIColor whiteColor]; + label.font = font; + label.text = [show substringWithRange:NSMakeRange(show.length - 2, 2)]; + [NSLayoutConstraint activateConstraints:@[ + [label.centerYAnchor constraintEqualToAnchor:headerView.centerYAnchor], + [label.centerXAnchor constraintEqualToAnchor:headerView.centerXAnchor] + ]]; + } + return headerView; +} + +- (NSString *)localizableWithKey:(NSString *)key { + return [self.bundle localizedStringForKey:key value:nil table:@"Localizable"]; + ; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h new file mode 100644 index 00000000..e8ecfa51 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h @@ -0,0 +1,36 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import +#import "NECallParam.h" +#import "NERtcCallUIConfig.h" + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const kCallKitDismissNoti; + +@interface NECallViewController : UIViewController + +@property(nonatomic, assign) NERtcCallStatus status; + +@property(nonatomic, assign) NERtcCallType callType; + +@property(nonatomic, strong) NECallParam *callParam; + +@property(nonatomic, strong) NSMutableDictionary *uiConfigDic; + +@property(nonatomic, strong) NECallUIConfig *config; + +// 当前用户视频显示位置 +@property(nonatomic, assign) BOOL showMyBigView; + +@property(nonatomic, assign) BOOL remoteCameraAvailable; + +// 主叫 +@property(nonatomic, assign) BOOL isCaller; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m new file mode 100644 index 00000000..4dd9cb47 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m @@ -0,0 +1,1183 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallViewController.h" +#import +#import +#import +#import "NECallUIStateController.h" +#import "NECustomButton.h" +#import "NEExpandButton.h" +#import "NERtcCallUIKit.h" +#import "NEVideoOperationView.h" +#import "NEVideoView.h" +#import "NetManager.h" +#import "SettingManager.h" + +NSString *const kCallKitDismissNoti = @"kCallKitDismissNoti"; + +NSString *const kCallKitShowNoti = @"kCallKitShowNoti"; + +@interface NECallViewController () + +@property(nonatomic, strong) UIButton *switchCameraBtn; + +@property(strong, nonatomic) NEVideoOperationView *operationView; + +/// 音视频转换 +@property(strong, nonatomic) NECustomButton *mediaSwitchBtn; + +@property(strong, nonatomic) UILabel *timerLabel; + +@property(strong, nonatomic) NSTimer *timer; + +@property(strong, nonatomic) UIImageView *blurImage; + +@property(strong, nonatomic) UIToolbar *toolBar; + +@property(assign, nonatomic) int timerCount; + +@property(nonatomic, assign) BOOL isPstn; // 当前呼叫是否已进入pstn流程,默认 NO + +@property(nonatomic, strong) UIView *bannerView; + +@property(nonatomic, weak) UIAlertController *alert; + +@property(nonatomic, strong) UILabel *cnameLabel; + +@property(nonatomic, assign) BOOL isRemoteMute; + +@property(assign, nonatomic) CGFloat factor; + +/// 通话状态视图 +@property(nonatomic, strong) NEAudioCallingController *audioCallingController; + +@property(nonatomic, strong) NEAudioInCallController *audioInCallController; + +@property(nonatomic, strong) NEVideoCallingController *videoCallingController; + +@property(nonatomic, strong) NEVideoInCallController *videoInCallController; + +@property(nonatomic, strong) NECalledViewController *calledController; + +@property(nonatomic, weak) NECallUIStateController *stateUIController; + +@property(nonatomic, strong) NSBundle *bundle; + +@end + +@implementation NECallViewController + +- (instancetype)init { + self = [super init]; + if (self) { + self.timerCount = 0; + self.factor = 1.0; + self.bundle = [NSBundle bundleForClass:self.class]; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [[NSNotificationCenter defaultCenter] postNotificationName:kCallKitShowNoti object:nil]; + [[NERtcEngine sharedEngine] setParameters:@{kNERtcKeyVideoStartWithBackCamera : @NO}]; + if (self.callType == NERtcCallTypeVideo) { + self.remoteCameraAvailable = YES; + } + [self setupUI]; + // [self setupCenterRemoteAvator]; + [self setupSDK]; + [self updateUIonStatus:self.status]; + if (self.isCaller == NO && [NERtcCallKit sharedInstance].callStatus == NERtcCallStatusIdle) { + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf onCallEnd]; + }); + } + + [self.view addSubview:self.bannerView]; + [NSLayoutConstraint activateConstraints:@[ + [self.bannerView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:80], + [self.bannerView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:20], + [self.bannerView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor constant:-20], + [self.bannerView.heightAnchor constraintEqualToConstant:40] + ]]; +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + [[NERtcCallKit sharedInstance] setupLocalView:nil]; +} + +#pragma mark - SDK +- (void)setupSDK { + [[NERtcCallKit sharedInstance] addDelegate:self]; + [[NERtcCallKit sharedInstance] enableLocalVideo:YES]; + + __weak typeof(self) weakSelf = self; + if (self.status == NERtcCallStatusCalling) { + [[NERtcCallKit sharedInstance] + call:self.callParam.remoteUserAccid + type:self.callType ? self.callType : NERtcCallTypeVideo + attachment:self.callParam.attachment + globalExtra:self.callParam.extra + withToken:self.callParam.token + channelName:self.callParam.channelName + completion:^(NSError *_Nullable error) { + NSLog(@"call error code : %@", error); + + if (weakSelf.callType == NERtcCallTypeVideo) { + if ([[SettingManager shareInstance] isGlobalInit] == YES) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[NERtcCallKit sharedInstance] + setupLocalView:weakSelf.videoCallingController.bigVideoView.videoView]; + }); + } + self.videoCallingController.bigVideoView.userID = weakSelf.callParam.currentUserAccid; + } + + if (error) { + /// 对方离线时 通过APNS推送 UI不弹框提示 + if (error.code == 10202 || error.code == 10201) { + return; + } else { + [weakSelf onCallEnd]; + } + [UIApplication.sharedApplication.keyWindow makeToast:error.localizedDescription]; + } + }]; + } +} + +- (void)setCallType:(NERtcCallType)callType { + NSLog(@"set current call type : %lu", (unsigned long)callType); + _callType = callType; +} + +#pragma mark - UI +- (void)setupUI { + if (self.view.frame.size.height < 600) { + self.factor = 0.5; + } + + CGSize buttonSize = CGSizeMake(75, 103); + CGFloat statusHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; + + self.blurImage = [[UIImageView alloc] init]; + self.blurImage.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.blurImage]; + [NSLayoutConstraint activateConstraints:@[ + [self.blurImage.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.blurImage.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.blurImage.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [self.blurImage.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] + ]]; + + if (self.callParam.remoteAvatar.length <= 0) { + UIView *cover = [self getDefaultHeaderView:self.callParam.remoteUserAccid + font:[UIFont systemFontOfSize:200] + showName:self.callParam.remoteShowName]; + [self.blurImage addSubview:cover]; + [NSLayoutConstraint activateConstraints:@[ + [cover.leftAnchor constraintEqualToAnchor:self.blurImage.leftAnchor], + [cover.rightAnchor constraintEqualToAnchor:self.blurImage.rightAnchor], + [cover.topAnchor constraintEqualToAnchor:self.blurImage.topAnchor], + [cover.bottomAnchor constraintEqualToAnchor:self.blurImage.bottomAnchor] + ]]; + } + + self.toolBar = [[UIToolbar alloc] initWithFrame:self.view.bounds]; + self.toolBar.barStyle = UIBarStyleBlackOpaque; + [self.blurImage addSubview:self.toolBar]; + + [self setupChildController]; + + [self.view addSubview:self.switchCameraBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.switchCameraBtn.topAnchor constraintEqualToAnchor:self.view.topAnchor + constant:statusHeight + 20], + [self.switchCameraBtn.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:20], + [self.switchCameraBtn.heightAnchor constraintEqualToConstant:30], + [self.switchCameraBtn.widthAnchor constraintEqualToConstant:30] + ]]; + + [self.view addSubview:self.operationView]; + [NSLayoutConstraint activateConstraints:@[ + [self.operationView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [self.operationView.heightAnchor constraintEqualToConstant:60], + [self.operationView.widthAnchor constraintEqualToConstant:self.view.frame.size.width * 0.8], + [self.operationView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-50.0 * self.factor] + ]]; + + /// 未接通状态下的音视频切换按钮 + self.mediaSwitchBtn = [[NECustomButton alloc] init]; + self.mediaSwitchBtn.maskBtn.accessibilityIdentifier = @"inCallSwitch"; + + [self.view addSubview:self.mediaSwitchBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.mediaSwitchBtn.centerXAnchor constraintEqualToAnchor:self.operationView.centerXAnchor], + [self.mediaSwitchBtn.bottomAnchor constraintEqualToAnchor:self.operationView.topAnchor + constant:-150 * self.factor], + [self.mediaSwitchBtn.heightAnchor constraintEqualToConstant:buttonSize.height], + [self.mediaSwitchBtn.widthAnchor constraintEqualToConstant:buttonSize.width] + ]]; + self.mediaSwitchBtn.hidden = YES; + + [self.mediaSwitchBtn.maskBtn addTarget:self + action:@selector(mediaClick:) + forControlEvents:UIControlEventTouchUpInside]; + + [self.view addSubview:self.timerLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.timerLabel.centerYAnchor constraintEqualToAnchor:self.switchCameraBtn.centerYAnchor], + [self.timerLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] + ]]; +} + +#pragma mark - inner function + +- (void)setCallingTypeSwith:(BOOL)show { + if (show == YES && self.config.showCallingSwitchCallType == YES) { + self.mediaSwitchBtn.hidden = NO; + } else { + self.mediaSwitchBtn.hidden = YES; + } +} + +- (void)setupChildController { + if (self.isCaller == YES) { + [self addChildViewController:self.videoCallingController]; + [self.view addSubview:self.videoCallingController.view]; + [self addChildViewController:self.audioCallingController]; + [self.view addSubview:self.audioCallingController.view]; + } else { + [self addChildViewController:self.calledController]; + [self.view addSubview:self.calledController.view]; + } + + [self addChildViewController:self.audioInCallController]; + [self.view addSubview:self.audioInCallController.view]; + [self addChildViewController:self.videoInCallController]; + [self.view addSubview:self.videoInCallController.view]; +} + +- (void)setSwitchAudioStyle { + self.mediaSwitchBtn.imageView.image = [UIImage imageNamed:@"switch_audio" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + self.mediaSwitchBtn.titleLabel.text = [self localizableWithKey:@"switch_to_audio"]; + self.mediaSwitchBtn.tag = NERtcCallTypeAudio; + [self showVideoView]; + [self setUrl:self.callParam.remoteAvatar withPlaceholder:@"avator"]; + [self.stateUIController refreshUI]; +} + +- (void)setSwitchVideoStyle { + self.mediaSwitchBtn.imageView.image = [UIImage imageNamed:@"switch_video" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + self.mediaSwitchBtn.titleLabel.text = [self localizableWithKey:@"switch_to_video"]; + self.mediaSwitchBtn.tag = NERtcCallTypeVideo; + [self hideVideoView]; + [self setUrl:self.callParam.remoteAvatar withPlaceholder:@"avator"]; + [self.stateUIController refreshUI]; +} + +- (void)updateUIonStatus:(NERtcCallStatus)status { + switch (status) { + case NERtcCallStatusCalling: { + [self setCallingTypeSwith:YES]; + self.operationView.hidden = YES; + self.stateUIController.view.hidden = YES; + if (self.callType == NERtcCallTypeVideo) { + self.stateUIController = self.videoCallingController; + [self.videoCallingController refreshUI]; + [self setSwitchAudioStyle]; + } else { + self.stateUIController = self.audioCallingController; + [self setSwitchVideoStyle]; + } + self.stateUIController.view.hidden = NO; + + } break; + case NERtcCallStatusCalled: { + [self setCallingTypeSwith:YES]; + self.operationView.hidden = YES; + self.stateUIController.view.hidden = YES; + self.stateUIController = self.calledController; + self.stateUIController.view.hidden = NO; + [self.calledController refreshUI]; + if (self.callType == NERtcCallTypeVideo) { + self.mediaSwitchBtn.imageView.image = [UIImage imageNamed:@"switch_audio" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + self.mediaSwitchBtn.titleLabel.text = [self localizableWithKey:@"switch_to_audio"]; + [self setSwitchAudioStyle]; + } else { + self.mediaSwitchBtn.imageView.image = [UIImage imageNamed:@"switch_video" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + self.mediaSwitchBtn.titleLabel.text = [self localizableWithKey:@"switch_to_video"]; + [self setSwitchVideoStyle]; + } + __weak typeof(self) weakSelf = self; + [self.calledController.remoteBigAvatorView + sd_setImageWithURL:[NSURL URLWithString:self.callParam.remoteAvatar] + completed:^(UIImage *_Nullable image, NSError *_Nullable error, + SDImageCacheType cacheType, NSURL *_Nullable imageURL) { + if (image == nil) { + image = [UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + } + if (weakSelf.isCaller == false && weakSelf.callType == NERtcCallTypeVideo) { + [weakSelf.blurImage setHidden:NO]; + } + weakSelf.blurImage.image = image; + }]; + + } break; + case NERtcCallStatusInCall: { + [self setCallingTypeSwith:NO]; + self.operationView.hidden = NO; + self.stateUIController.view.hidden = YES; + if (self.callType == NERtcCallTypeVideo) { + self.stateUIController = self.videoInCallController; + self.switchCameraBtn.hidden = NO; + [self.videoInCallController refreshUI]; + } else { + [self.operationView changeAudioStyle]; + self.stateUIController = self.audioInCallController; + } + self.stateUIController.view.hidden = NO; + + } break; + default: + break; + } + self.status = status; +} + +- (void)showVideoView { + if (self.status == NERtcCallStatusCalling) { + [[NERtcCallKit sharedInstance] + setupLocalView:self.videoCallingController.bigVideoView.videoView]; + } + if (self.status == NERtcCallStatusInCall) { + [[NERtcCallKit sharedInstance] + setupLocalView:self.videoInCallController.smallVideoView.videoView]; + [[NERtcCallKit sharedInstance] setupRemoteView:self.videoInCallController.bigVideoView.videoView + forUser:self.callParam.remoteUserAccid]; + } + + [[NERtcCallKit sharedInstance] muteLocalAudio:NO]; + [[NERtcCallKit sharedInstance] muteLocalVideo:NO]; + self.operationView.microPhone.selected = NO; + self.operationView.cameraBtn.selected = NO; + + self.operationView.speakerBtn.selected = NO; + self.operationView.microPhone.selected = NO; + NSError *error; + [[NERtcCallKit sharedInstance] setLoudSpeakerMode:YES error:&error]; + [[NERtcEngine sharedEngine] muteLocalAudio:NO]; +} + +- (void)hideVideoView { + [[NERtcCallKit sharedInstance] setupLocalView:nil]; + [[NERtcCallKit sharedInstance] setupRemoteView:nil forUser:nil]; + self.operationView.speakerBtn.selected = YES; + self.operationView.microPhone.selected = NO; + NSError *error; + [[NERtcCallKit sharedInstance] setLoudSpeakerMode:NO error:&error]; + [[NERtcEngine sharedEngine] muteLocalAudio:NO]; +} + +#pragma mark - event + +- (void)closeEvent:(UIButton *)button { + [[NERtcCallKit sharedInstance] hangup:^(NSError *_Nullable error){ + + }]; +} + +- (void)cancelEvent:(UIButton *)button { + __weak typeof(self) weakSelf = self; + NSLog(@"cancel rtc"); + if ([[NetManager shareInstance] isClose] == YES) { + [self destroy]; + } + [[NERtcCallKit sharedInstance] cancel:^(NSError *_Nullable error) { + NSLog(@"cancel error %@", error); + button.enabled = YES; + if (error.code == 20016) { + [UIApplication.sharedApplication.keyWindow + makeToast:[self localizableWithKey:@"cancel_failed"]]; + } else { + [weakSelf destroy]; + } + }]; +} +- (void)rejectEvent:(UIButton *)button { + if ([[NetManager shareInstance] isClose] == YES) { + [self destroy]; + } + self.calledController.acceptBtn.userInteractionEnabled = NO; + __weak typeof(self) weakSelf = self; + + if ([[SettingManager shareInstance] rejectBusyCode] == YES) { + [[NERtcCallKit sharedInstance] rejectWithReason:TerminalCodeBusy + withCompletion:^(NSError *_Nullable error) { + weakSelf.calledController.acceptBtn.userInteractionEnabled = + YES; + [weakSelf destroy]; + }]; + } else { + [[NERtcCallKit sharedInstance] reject:^(NSError *_Nullable error) { + weakSelf.calledController.acceptBtn.userInteractionEnabled = YES; + [weakSelf destroy]; + }]; + } +} +- (void)acceptEvent:(UIButton *)button { + if ([[NetManager shareInstance] isClose] == YES) { + [self.view makeToast:[self localizableWithKey:@"network_error"]]; + return; + } + + self.calledController.rejectBtn.userInteractionEnabled = NO; + self.calledController.acceptBtn.userInteractionEnabled = NO; + __weak typeof(self) weakSelf = self; + + [[NERtcCallKit sharedInstance] + acceptWithToken:[[SettingManager shareInstance] customToken] + withCompletion:^(NSError *_Nullable error) { + weakSelf.calledController.rejectBtn.userInteractionEnabled = YES; + weakSelf.calledController.acceptBtn.userInteractionEnabled = YES; + if (error) { + if (error.code != 10420) { + [UIApplication.sharedApplication.keyWindow + makeToast:[NSString stringWithFormat:@"%@ %@", + [self localizableWithKey:@"accept_failed"], + error.localizedDescription]]; + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [weakSelf destroy]; + }); + } else { + [[NERtcCallKit sharedInstance] memberOfAccid:@"" + completion:^(NIMSignalingMemberInfo *_Nullable info){ + + }]; + [weakSelf updateUIonStatus:NERtcCallStatusInCall]; + [weakSelf startTimer]; + } + }]; +} +- (void)switchCameraBtn:(UIButton *)button { + [[NERtcCallKit sharedInstance] switchCamera]; + button.selected = !button.selected; + if (button.isSelected == YES) { + [[NERtcEngine sharedEngine] setParameters:@{kNERtcKeyVideoStartWithBackCamera : @YES}]; + } else { + [[NERtcEngine sharedEngine] setParameters:@{kNERtcKeyVideoStartWithBackCamera : @NO}]; + } +} +- (void)microPhoneClick:(UIButton *)button { + button.selected = !button.selected; + [[NERtcCallKit sharedInstance] muteLocalAudio:button.selected]; +} +- (void)cameraBtnClick:(UIButton *)button { + button.selected = !button.selected; + NSLog(@"mute video select : %d", button.selected); + if ([[SettingManager shareInstance] useEnableLocalMute] == YES) { + NSLog(@"enableLocalVideo: %d", !button.selected); + [[NERtcCallKit sharedInstance] enableLocalVideo:!button.selected]; + } else { + [[NERtcCallKit sharedInstance] muteLocalVideo:button.selected]; + } + [self changeDefaultImage:button.selected]; + [self cameraAvailble:!button.selected userId:self.callParam.currentUserAccid]; +} +- (void)hangupBtnClick:(UIButton *)button { + [[NERtcCallKit sharedInstance] hangup:^(NSError *_Nullable error){ + + }]; + + [self destroy]; +} +- (void)microphoneBtnClick:(UIButton *)button { + NSLog(@"micro phone btn click : %d", button.imageView.highlighted); + self.audioCallingController.microphoneBtn.imageView.highlighted = + !self.audioCallingController.microphoneBtn.imageView.highlighted; + [[NERtcCallKit sharedInstance] + muteLocalAudio:self.audioCallingController.microphoneBtn.imageView.highlighted]; + _operationView.microPhone.selected = + self.audioCallingController.microphoneBtn.imageView.highlighted; +} +- (void)speakerBtnClick:(UIButton *)button { + NSLog(@"speaker btn click : %d", self.audioCallingController.speakerBtn.imageView.highlighted); + NSError *error = nil; + + [[NERtcCallKit sharedInstance] + setLoudSpeakerMode:!self.audioCallingController.speakerBtn.imageView.highlighted + error:&error]; + if (error == nil) { + self.audioCallingController.speakerBtn.imageView.highlighted = + !self.audioCallingController.speakerBtn.imageView.highlighted; + _operationView.speakerBtn.selected = + !self.audioCallingController.speakerBtn.imageView.highlighted; + } else { + [self.view makeToast:error.description]; + } +} + +- (void)operationSwitchClick:(UIButton *)btn { + if ([[NetManager shareInstance] isClose] == YES) { + [self.view makeToast:[self localizableWithKey:@"network_error"]]; + return; + } + __weak typeof(self) weakSelf = self; + btn.enabled = NO; + NERtcCallType type = + self.callType == NERtcCallTypeVideo ? NERtcCallTypeAudio : NERtcCallTypeVideo; + [[NERtcCallKit sharedInstance] + switchCallType:type + withState:NERtcSwitchStateInvite + completion:^(NSError *_Nullable error) { + // weakSelf.mediaSwitchBtn.enabled = YES; + btn.enabled = YES; + if (error == nil) { + NSLog(@"切换成功 : %lu", type); + NSLog(@"switch : %d", btn.selected); + if (type == NERtcCallTypeVideo && [SettingManager.shareInstance isVideoConfirm]) { + [weakSelf showBannerView]; + } else if (type == NERtcCallTypeAudio && + [SettingManager.shareInstance isAudioConfirm]) { + [weakSelf showBannerView]; + } + } else { + [weakSelf.view + makeToast:[NSString stringWithFormat:@"%@: %@", + [self localizableWithKey:@"switch_error"], + error]]; + } + }]; +} + +- (void)operationSpeakerClick:(UIButton *)btn { + NSError *error = nil; + BOOL use; + [[NERtcEngine sharedEngine] getLoudspeakerMode:&use]; + NSLog(@"get loud speaker %d", use); + [[NERtcCallKit sharedInstance] setLoudSpeakerMode:btn.selected error:&error]; + if (error == nil) { + btn.selected = !btn.selected; + } else { + [self.view makeToast:error.description]; + } +} + +- (void)mediaClick:(UIButton *)btn { + if ([[NetManager shareInstance] isClose] == YES) { + [self.view makeToast:[self localizableWithKey:@"network_error"]]; + return; + } + __weak typeof(self) weakSelf = self; + self.mediaSwitchBtn.maskBtn.enabled = NO; + NERtcCallType type = + weakSelf.callType == NERtcCallTypeVideo ? NERtcCallTypeAudio : NERtcCallTypeVideo; + [[NERtcCallKit sharedInstance] + switchCallType:type + withState:NERtcSwitchStateInvite + completion:^(NSError *_Nullable error) { + weakSelf.mediaSwitchBtn.maskBtn.enabled = YES; + if (error == nil) { + if (type == NERtcCallTypeVideo && [SettingManager.shareInstance isVideoConfirm]) { + [weakSelf showBannerView]; + } else if (type == NERtcCallTypeAudio && + [SettingManager.shareInstance isAudioConfirm]) { + [weakSelf showBannerView]; + } + } else { + [weakSelf.view + makeToast:[NSString stringWithFormat:@"%@ : %@", + [self localizableWithKey:@"switch_error"], + error]]; + } + }]; +} + +#pragma mark - NERtcVideoCallDelegate + +- (void)onDisconnect:(NSError *)reason { + [self destroy]; +} +- (void)onUserEnter:(NSString *)userID { + [self updateUIonStatus:NERtcCallStatusInCall]; + [self startTimer]; + if ([[SettingManager shareInstance] incallShowCName] == YES && + [self.cnameLabel superview] == nil) { + [self.view addSubview:self.cnameLabel]; + self.cnameLabel.text = + [NSString stringWithFormat:@"cname: %@", [[SettingManager shareInstance] getRtcCName]]; + [NSLayoutConstraint activateConstraints:@[ + [self.cnameLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [self.cnameLabel.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] + ]]; + } +} +- (void)onUserCancel:(NSString *)userID { + [[NERtcCallKit sharedInstance] hangup:^(NSError *_Nullable error){ + }]; + [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_cancel"]]; + [self destroy]; +} +- (void)onCameraAvailable:(BOOL)available userID:(NSString *)userID { + self.isRemoteMute = !available; + [self cameraAvailble:available userId:userID]; +} +- (void)onVideoMuted:(BOOL)muted userID:(NSString *)userID { + self.isRemoteMute = muted; + [self cameraAvailble:!muted userId:userID]; +} +- (void)onUserLeave:(NSString *)userID { + NSLog(@"onUserLeave"); + [self destroy]; +} +- (void)onUserDisconnect:(NSString *)userID { + NSLog(@"onUserDiconnect"); + [self destroy]; +} +- (void)onCallingTimeOut { + if ([[NetManager shareInstance] isClose] == YES) { + [self destroy]; + return; + } + [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_timeout"]]; + [self destroy]; +} +- (void)onUserBusy:(NSString *)userID { + [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_busy"]]; + [self destroy]; +} +- (void)onCallEnd { + [self destroy]; +} +- (void)onUserReject:(NSString *)userID { + [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_reject"]]; + [self destroy]; +} + +- (void)onOtherClientAccept { + [UIApplication.sharedApplication.keyWindow + makeToast:[self localizableWithKey:@"other_client_accept"]]; + [self destroy]; +} + +- (void)onOtherClientReject { + [UIApplication.sharedApplication.keyWindow + makeToast:[self localizableWithKey:@"other_client_reject"]]; + [self destroy]; +} + +- (void)onCallTypeChange:(NERtcCallType)callType withState:(NERtcSwitchState)state { + NSLog(@"onCallTypeChange: %lu withState: %lu", (unsigned long)callType, (unsigned long)state); + switch (state) { + case NERtcSwitchStateAgree: + [self hideBannerView]; + [self onCallTypeChange:callType]; + break; + case NERtcSwitchStateInvite: { + if (self.alert != nil) { + NSLog(@"alert is showing"); + return; + } + UIAlertController *alert = [UIAlertController + alertControllerWithTitle:[self localizableWithKey:@"permission"] + message:callType == NERtcCallTypeVideo + ? [self localizableWithKey:@"audio_to_video"] + : [self localizableWithKey:@"video_to_audio"] + preferredStyle:UIAlertControllerStyleAlert]; + self.alert = alert; + UIAlertAction *rejectAction = + [UIAlertAction actionWithTitle:[self localizableWithKey:@"reject"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + [[NERtcCallKit sharedInstance] + switchCallType:callType + withState:NERtcSwitchStateReject + completion:^(NSError *_Nullable error) { + if (error) { + [UIApplication.sharedApplication.keyWindow + makeToast:error.localizedDescription]; + } + }]; + }]; + __weak typeof(self) weakSelf = self; + UIAlertAction *agreeAction = + [UIAlertAction actionWithTitle:[self localizableWithKey:@"agree"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + [[NERtcCallKit sharedInstance] + switchCallType:callType + withState:NERtcSwitchStateAgree + completion:^(NSError *_Nullable error) { + [weakSelf onCallTypeChange:callType]; + if (error) { + [UIApplication.sharedApplication.keyWindow + makeToast:error.localizedDescription]; + } + }]; + }]; + + [alert addAction:rejectAction]; + [alert addAction:agreeAction]; + [self presentViewController:alert animated:YES completion:nil]; + + NSLog(@"NERtcSwitchStateInvite : %ld", callType); + + } + + break; + case NERtcSwitchStateReject: + [self hideBannerView]; + [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"reject_tip"]]; + break; + default: + break; + } + NSLog(@"onCallTypeChange : %lu with state : %lu", callType, state); +} + +- (void)onCallTypeChange:(NERtcCallType)callType { + NSLog(@"onCallTypeChange:"); + if (self.callType == callType) { + return; + } + self.callType = callType; + [self updateUIonStatus:self.status]; + + if (self.status == NERtcCallStatusInCall) { + switch (callType) { + case NERtcCallTypeAudio: + NSLog(@"NERtcCallTypeAudio"); + [self.operationView changeAudioStyle]; + [self hideVideoView]; + break; + case NERtcCallTypeVideo: + NSLog(@"NERtcCallTypeVideo"); + [self.operationView changeVideoStyle]; + [self showVideoView]; + break; + default: + break; + } + return; + } + + switch (callType) { + case NERtcCallTypeAudio: + [self.operationView changeAudioStyle]; + [self setSwitchVideoStyle]; + break; + case NERtcCallTypeVideo: + [self.operationView changeVideoStyle]; + [self setSwitchAudioStyle]; + break; + default: + break; + } +} + +- (void)onError:(NSError *)error { + NSLog(@"call kit on error : %@", error); +} + +- (void)onAudioAvailable:(BOOL)available userID:(NSString *)userID { + NSLog(@"onAudioAvailable"); +} + +#pragma mark - private mothed +- (void)cameraAvailble:(BOOL)available userId:(NSString *)userId { + if ([self.videoInCallController.bigVideoView.userID isEqualToString:userId]) { + self.videoInCallController.bigVideoView.maskView.hidden = available; + self.remoteCameraAvailable = available; + } + if ([self.videoInCallController.smallVideoView.userID isEqualToString:userId]) { + self.videoInCallController.smallVideoView.maskView.hidden = available; + self.remoteCameraAvailable = available; + } +} + +- (void)setUrl:(NSString *)url withPlaceholder:(NSString *)holder { + __weak typeof(self) weakSelf = self; + UIImageView *remoteAvatorView = nil; + if (self.callType == NERtcCallTypeVideo) { + remoteAvatorView = self.videoCallingController.remoteAvatorView; + } else { + remoteAvatorView = self.calledController.remoteBigAvatorView; + } + [remoteAvatorView + sd_setImageWithURL:[NSURL URLWithString:url] + completed:^(UIImage *_Nullable image, NSError *_Nullable error, + SDImageCacheType cacheType, NSURL *_Nullable imageURL) { + if (image == nil) { + image = [UIImage imageNamed:holder + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + } + if (weakSelf.isCaller == false && weakSelf.callType == NERtcCallTypeVideo) { + [weakSelf.blurImage setHidden:NO]; + } + weakSelf.blurImage.image = image; + }]; +} + +- (void)startTimer { + if (self.timer != nil) { + return; + } + if (self.timerLabel.hidden == YES) { + self.timerLabel.hidden = NO; + } + self.timer = [NSTimer scheduledTimerWithTimeInterval:1 + target:self + selector:@selector(figureTimer) + userInfo:nil + repeats:YES]; +} + +- (void)figureTimer { + self.timerCount++; + self.timerLabel.text = [self timeFormatted:self.timerCount]; +} + +- (NSString *)timeFormatted:(int)totalSeconds { + if (totalSeconds < 3600) { + int seconds = totalSeconds % 60; + int minutes = (totalSeconds / 60) % 60; + return [NSString stringWithFormat:@"%02d:%02d", minutes, seconds]; + } + int seconds = totalSeconds % 60; + int minutes = (totalSeconds / 60) % 60; + int hours = totalSeconds / 3600; + return [NSString stringWithFormat:@"%02d:%02d:%02d", hours, minutes, seconds]; +} + +- (NSString *)getInviteText { + return (self.callType == NERtcCallTypeAudio ? [self localizableWithKey:@"invite_audio_call"] + : [self localizableWithKey:@"invite_video_call"]); +} + +- (void)hideBannerView { + self.bannerView.hidden = YES; +} + +- (void)showBannerView { + self.bannerView.hidden = NO; +} + +#pragma mark - destroy +- (void)destroy { + if (self.alert != nil) { + [self.alert dismissViewControllerAnimated:NO completion:nil]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:kCallKitDismissNoti object:nil]; + [[NERtcCallKit sharedInstance] removeDelegate:self]; + + if (self.timer != nil) { + [self.timer invalidate]; + self.timer = nil; + } +} + +#pragma mark - property + +- (UILabel *)cnameLabel { + if (_cnameLabel == nil) { + _cnameLabel = [[UILabel alloc] init]; + _cnameLabel.textColor = [UIColor redColor]; + _cnameLabel.font = [UIFont systemFontOfSize:14]; + _cnameLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _cnameLabel; +} + +- (UIView *)bannerView { + if (!_bannerView) { + _bannerView = [[UIView alloc] init]; + _bannerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; + _bannerView.clipsToBounds = YES; + _bannerView.layer.cornerRadius = 4.0; + _bannerView.hidden = YES; + _bannerView.translatesAutoresizingMaskIntoConstraints = NO; + + NEExpandButton *closeBtn = [NEExpandButton buttonWithType:UIButtonTypeCustom]; + [_bannerView addSubview:closeBtn]; + closeBtn.translatesAutoresizingMaskIntoConstraints = NO; + closeBtn.backgroundColor = [UIColor clearColor]; + [closeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [closeBtn setTitle:@"X" forState:UIControlStateNormal]; + [closeBtn addTarget:self + action:@selector(hideBannerView) + forControlEvents:UIControlEventTouchUpInside]; + + [NSLayoutConstraint activateConstraints:@[ + [closeBtn.topAnchor constraintEqualToAnchor:_bannerView.topAnchor], + [closeBtn.bottomAnchor constraintEqualToAnchor:_bannerView.bottomAnchor], + [closeBtn.rightAnchor constraintEqualToAnchor:_bannerView.rightAnchor], + [closeBtn.widthAnchor constraintEqualToConstant:40] + ]]; + + UILabel *label = [[UILabel alloc] init]; + label.translatesAutoresizingMaskIntoConstraints = NO; + [_bannerView addSubview:label]; + label.textColor = [UIColor whiteColor]; + [NSLayoutConstraint activateConstraints:@[ + [label.leftAnchor constraintEqualToAnchor:self.bannerView.leftAnchor constant:10], + [label.topAnchor constraintEqualToAnchor:self.bannerView.topAnchor], + [label.rightAnchor constraintEqualToAnchor:closeBtn.leftAnchor constant:-10] + ]]; + + label.adjustsFontSizeToFitWidth = YES; + label.text = [self localizableWithKey:@"waitting_remote_response"]; + } + return _bannerView; +} + +- (UIButton *)switchCameraBtn { + if (!_switchCameraBtn) { + _switchCameraBtn = [[UIButton alloc] init]; + [_switchCameraBtn setImage:[UIImage imageNamed:@"call_switch_camera" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + [_switchCameraBtn addTarget:self + action:@selector(switchCameraBtn:) + forControlEvents:UIControlEventTouchUpInside]; + _switchCameraBtn.translatesAutoresizingMaskIntoConstraints = NO; + _switchCameraBtn.hidden = YES; + } + return _switchCameraBtn; +} + +- (NEVideoOperationView *)operationView { + if (!_operationView) { + _operationView = [[NEVideoOperationView alloc] init]; + _operationView.translatesAutoresizingMaskIntoConstraints = NO; + _operationView.layer.cornerRadius = 30; + [_operationView.microPhone addTarget:self + action:@selector(microPhoneClick:) + forControlEvents:UIControlEventTouchUpInside]; + [_operationView.cameraBtn addTarget:self + action:@selector(cameraBtnClick:) + forControlEvents:UIControlEventTouchUpInside]; + [_operationView.hangupBtn addTarget:self + action:@selector(hangupBtnClick:) + forControlEvents:UIControlEventTouchUpInside]; + [_operationView.mediaBtn addTarget:self + action:@selector(operationSwitchClick:) + forControlEvents:UIControlEventTouchUpInside]; + [_operationView.speakerBtn addTarget:self + action:@selector(operationSpeakerClick:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _operationView; +} + +- (UILabel *)timerLabel { + if (nil == _timerLabel) { + _timerLabel = [[UILabel alloc] init]; + _timerLabel.textColor = [UIColor whiteColor]; + _timerLabel.font = [UIFont systemFontOfSize:14.0]; + _timerLabel.textAlignment = NSTextAlignmentCenter; + _timerLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _timerLabel; +} + +- (void)dealloc { + [[NERtcCallKit sharedInstance] removeDelegate:self]; +} + +- (void)hideViews:(NSArray *)views { + for (UIView *view in views) { + [view setHidden:YES]; + } +} + +- (void)showViews:(NSArray *)views { + for (UIView *view in views) { + [view setHidden:NO]; + } +} + +- (void)changeDefaultImage:(BOOL)mute { + // TODO: 代码整理 + /* + UIImage *image = [[SettingManager shareInstance] muteDefaultImage]; + if (image != nil) { + if (mute == YES) { + if (self.showMyBigView) { + self.bigVideoView.imageView.image = image; + self.bigVideoView.imageView.hidden = NO; + [self changeRemoteMute:self.isRemoteMute videoView:self.smallVideoView]; + } else { + self.smallVideoView.imageView.image = image; + self.smallVideoView.imageView.hidden = NO; + [self changeRemoteMute:self.isRemoteMute videoView:self.bigVideoView]; + } + } else { + if (self.showMyBigView) { + self.bigVideoView.imageView.image = nil; + self.bigVideoView.imageView.hidden = YES; + self.smallVideoView.imageView.hidden = YES; + [self changeRemoteMute:self.isRemoteMute videoView:self.smallVideoView]; + } else { + self.smallVideoView.imageView.image = nil; + self.smallVideoView.imageView.hidden = YES; + [self changeRemoteMute:self.isRemoteMute videoView:self.bigVideoView]; + } + } + } */ +} + +- (void)changeRemoteMute:(BOOL)mute videoView:(NEVideoView *)remoteVideo { + UIImage *defaultImage = [[SettingManager shareInstance] remoteDefaultImage]; + if (mute == true && defaultImage != nil) { + remoteVideo.imageView.hidden = NO; + remoteVideo.imageView.image = defaultImage; + } else { + remoteVideo.imageView.hidden = YES; + } +} + +- (NEAudioCallingController *)audioCallingController { + if (nil == _audioCallingController) { + _audioCallingController = + (NEAudioCallingController *)[self getCallStateInstanceWithClassKey:kAudioCalling]; + } + if (nil == _audioCallingController) { + _audioCallingController = [[NEAudioCallingController alloc] init]; + _audioCallingController.isCaller = self.isCaller; + _audioCallingController.callParam = self.callParam; + _audioCallingController.callType = self.callType; + _audioCallingController.mainController = self; + _audioCallingController.view.hidden = YES; + } + + return _audioCallingController; +} + +- (NEAudioInCallController *)audioInCallController { + if (nil == _audioInCallController) { + _audioInCallController = + (NEAudioInCallController *)[self getCallStateInstanceWithClassKey:kAudioInCall]; + } + if (nil == _audioInCallController) { + _audioInCallController = [[NEAudioInCallController alloc] init]; + _audioInCallController.isCaller = self.isCaller; + _audioInCallController.callParam = self.callParam; + _audioInCallController.callType = self.callType; + _audioInCallController.mainController = self; + _audioInCallController.view.hidden = YES; + } + return _audioInCallController; +} + +- (NEVideoCallingController *)videoCallingController { + if (nil == _videoCallingController) { + _videoCallingController = + (NEVideoCallingController *)[self getCallStateInstanceWithClassKey:kVideoCalling]; + } + if (nil == _videoCallingController) { + _videoCallingController = [[NEVideoCallingController alloc] init]; + _videoCallingController.isCaller = self.isCaller; + _videoCallingController.callParam = self.callParam; + _videoCallingController.callType = self.callType; + _videoCallingController.mainController = self; + _videoCallingController.view.hidden = YES; + } + return _videoCallingController; +} + +- (NEVideoInCallController *)videoInCallController { + if (nil == _videoInCallController) { + _videoInCallController = + (NEVideoInCallController *)[self getCallStateInstanceWithClassKey:kVideoInCall]; + } + if (nil == _videoInCallController) { + _videoInCallController = [[NEVideoInCallController alloc] init]; + _videoInCallController.isCaller = self.isCaller; + _videoInCallController.callParam = self.callParam; + _videoInCallController.callType = self.callType; + _videoInCallController.mainController = self; + _videoInCallController.view.hidden = YES; + } + return _videoInCallController; +} + +- (NECalledViewController *)calledController { + if (nil == _calledController) { + _calledController = + (NECalledViewController *)[self getCallStateInstanceWithClassKey:kCalledState]; + } + if (nil == _calledController) { + _calledController = [[NECalledViewController alloc] init]; + _calledController.isCaller = self.isCaller; + _calledController.callParam = self.callParam; + _calledController.callType = self.callType; + _calledController.mainController = self; + _calledController.view.hidden = YES; + } + return _calledController; +} + +#pragma mark - common fuction + +- (NECallUIStateController *)getCallStateInstanceWithClassKey:(NSString *)key { + Class cls = [self.uiConfigDic objectForKey:key]; + if (nil != cls) { + NECallUIStateController *controller = [[cls alloc] init]; + controller.isCaller = self.isCaller; + controller.callParam = self.callParam; + controller.callType = self.callType; + controller.mainController = self; + controller.view.hidden = YES; + return controller; + } + return nil; +} + +- (UIView *)getDefaultHeaderView:(NSString *)accid + font:(UIFont *)font + showName:(NSString *)showName { + UIView *headerView = [[UIView alloc] init]; + headerView.backgroundColor = [UIColor colorWithStringWithString:accid]; + headerView.translatesAutoresizingMaskIntoConstraints = NO; + NSString *show = showName.length > 0 ? showName : accid; + if (show.length >= 2) { + UILabel *label = [[UILabel alloc] init]; + label.translatesAutoresizingMaskIntoConstraints = NO; + [headerView addSubview:label]; + label.textColor = [UIColor whiteColor]; + label.font = font; + label.text = [show substringWithRange:NSMakeRange(show.length - 2, 2)]; + [NSLayoutConstraint activateConstraints:@[ + [label.centerYAnchor constraintEqualToAnchor:headerView.centerYAnchor], + [label.centerXAnchor constraintEqualToAnchor:headerView.centerXAnchor] + ]]; + } + return headerView; +} + +- (NSString *)localizableWithKey:(NSString *)key { + return [self.bundle localizedStringForKey:key value:nil table:@"Localizable"]; + ; +} +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h new file mode 100644 index 00000000..72cbca29 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallUIStateController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NECalledViewController : NECallUIStateController + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m new file mode 100644 index 00000000..81a49ddb --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m @@ -0,0 +1,64 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECalledViewController.h" + +@interface NECalledViewController () + +@end + +@implementation NECalledViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)setupUI { + [super setupUI]; + /// 接听和拒接按钮 + [self.view addSubview:self.rejectBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.rejectBtn.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor + constant:-self.view.frame.size.width / 4.0], + [self.rejectBtn.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-80 * self.factor], + [self.rejectBtn.widthAnchor constraintEqualToConstant:self.buttonSize.width], + [self.rejectBtn.heightAnchor constraintEqualToConstant:self.buttonSize.height] + ]]; + + [self.view addSubview:self.acceptBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.acceptBtn.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor + constant:self.view.frame.size.width / 4.0], + [self.acceptBtn.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-80 * self.factor], + [self.acceptBtn.widthAnchor constraintEqualToConstant:self.buttonSize.width], + [self.acceptBtn.heightAnchor constraintEqualToConstant:self.buttonSize.height] + ]]; + + [self setupCenterRemoteAvator]; + + [self refreshUI]; +} + +- (void)refreshUI { + self.centerTitleLabel.text = self.callParam.remoteShowName.length > 0 + ? self.callParam.remoteShowName + : self.callParam.remoteUserAccid; + self.centerSubtitleLabel.text = [self getInviteText]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before +navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.h new file mode 100644 index 00000000..4609b176 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallUIStateController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NEVideoCallingController : NECallUIStateController + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m new file mode 100644 index 00000000..9501ad54 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m @@ -0,0 +1,84 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEVideoCallingController.h" + +@interface NEVideoCallingController () + +@end + +@implementation NEVideoCallingController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)setupUI { + [super setupUI]; + + [self.view addSubview:self.bigVideoView]; + [NSLayoutConstraint activateConstraints:@[ + [self.bigVideoView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.bigVideoView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.bigVideoView.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [self.bigVideoView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] + ]]; + + // [self.view addSubview:self.smallVideoView]; + // [NSLayoutConstraint activateConstraints:@[ + // [self.smallVideoView.topAnchor constraintEqualToAnchor:self.view.topAnchor + // constant:self.statusHeight + 20], + // [self.smallVideoView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor + // constant:-20], [self.smallVideoView.heightAnchor constraintEqualToConstant:160], + // [self.smallVideoView.widthAnchor constraintEqualToConstant:90] + // ]]; + // + // self.smallVideoView.clipsToBounds = YES; + // self.smallVideoView.layer.cornerRadius = self.radius; + // self.smallVideoView.hidden = YES; + + [self.view addSubview:self.remoteAvatorView]; + [NSLayoutConstraint activateConstraints:@[ + [self.remoteAvatorView.topAnchor constraintEqualToAnchor:self.view.topAnchor + constant:self.statusHeight + 20], + [self.remoteAvatorView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor constant:-20], + [self.remoteAvatorView.heightAnchor constraintEqualToConstant:60], + [self.remoteAvatorView.widthAnchor constraintEqualToConstant:60] + ]]; + + self.remoteAvatorView.clipsToBounds = YES; + self.remoteAvatorView.layer.cornerRadius = self.radius; + + [self.view addSubview:self.titleLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.titleLabel.topAnchor constraintEqualToAnchor:self.remoteAvatorView.topAnchor constant:5], + [self.titleLabel.rightAnchor constraintEqualToAnchor:self.remoteAvatorView.leftAnchor + constant:-8], + [self.titleLabel.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:20], + [self.titleLabel.heightAnchor constraintEqualToConstant:25] + ]]; + + [self.view addSubview:self.subTitleLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.subTitleLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor], + [self.subTitleLabel.rightAnchor constraintEqualToAnchor:self.titleLabel.rightAnchor], + [self.subTitleLabel.leftAnchor constraintEqualToAnchor:self.titleLabel.leftAnchor], + [self.subTitleLabel.heightAnchor constraintEqualToConstant:20] + ]]; + + /// 取消按钮 + [self.view addSubview:self.cancelBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.cancelBtn.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [self.cancelBtn.widthAnchor constraintEqualToConstant:self.buttonSize.width], + [self.cancelBtn.heightAnchor constraintEqualToConstant:self.buttonSize.height], + [self.cancelBtn.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-80 * self.factor] + ]]; + + [self setupVideoCallingUI]; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.h new file mode 100644 index 00000000..b3b944cc --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallUIStateController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NEVideoInCallController : NECallUIStateController + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m new file mode 100644 index 00000000..618160b6 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m @@ -0,0 +1,56 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEVideoInCallController.h" + +@interface NEVideoInCallController () + +@end + +@implementation NEVideoInCallController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)setupUI { + [super setupUI]; + [self.view addSubview:self.bigVideoView]; + [NSLayoutConstraint activateConstraints:@[ + [self.bigVideoView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.bigVideoView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.bigVideoView.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [self.bigVideoView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] + ]]; + + [self.view addSubview:self.smallVideoView]; + [NSLayoutConstraint activateConstraints:@[ + [self.smallVideoView.topAnchor constraintEqualToAnchor:self.view.topAnchor + constant:self.statusHeight + 20], + [self.smallVideoView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor constant:-20], + [self.smallVideoView.heightAnchor constraintEqualToConstant:160], + [self.smallVideoView.widthAnchor constraintEqualToConstant:90] + ]]; + + self.smallVideoView.clipsToBounds = YES; + self.smallVideoView.layer.cornerRadius = self.radius; +} + +- (void)refreshUI { + [self refreshVideoView]; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before +navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.h new file mode 100644 index 00000000..4cb79720 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.h @@ -0,0 +1,17 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NetManager : NSObject + +@property(nonatomic, assign) BOOL isClose; + ++ (id)shareInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m new file mode 100644 index 00000000..fdf3009c --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m @@ -0,0 +1,59 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NetManager.h" +#import "AFNetworking.h" + +@implementation NetManager + ++ (id)shareInstance { + static NetManager *shareInstance = nil; + static dispatch_once_t once_token; + dispatch_once(&once_token, ^{ + if (!shareInstance) { + shareInstance = [[self alloc] init]; + } + }); + return shareInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [self monitorNetworkState]; + } + return self; +} + +#pragma mark - 监测网络状态 +- (void)monitorNetworkState { + AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; + [manager startMonitoring]; + self.isClose = [manager isReachable] ? NO : YES; + NSLog(@"net work close state : %d", self.isClose); + [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { + switch (status) { + case AFNetworkReachabilityStatusNotReachable: + NSLog(@"没有网络"); + self.isClose = YES; + break; + case AFNetworkReachabilityStatusUnknown: + NSLog(@"未知"); + self.isClose = YES; + break; + case AFNetworkReachabilityStatusReachableViaWiFi: + NSLog(@"WiFi"); + self.isClose = NO; + break; + case AFNetworkReachabilityStatusReachableViaWWAN: + NSLog(@"3G|4G"); + self.isClose = NO; + break; + default: + break; + } + }]; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.h new file mode 100644 index 00000000..67e510d0 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.h @@ -0,0 +1,71 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SettingManager : NSObject + +@property(nonatomic, assign, readonly) NSInteger timeout; + +@property(nonatomic, assign, readonly) BOOL supportAutoJoinWhenCalled; + +@property(nonatomic, assign, readonly) BOOL rejectBusyCode; + +@property(nonatomic, assign, readonly) BOOL openCustomTokenAndChannelName; + +@property(nonatomic, assign) uint64_t customUid; + +@property(nonatomic, strong) NSString *customChannelName; + +@property(nonatomic, strong) NSString *customToken; + +@property(nonatomic, strong) NSString *globalExtra; + +@property(nonatomic, assign) BOOL isAudioConfirm; + +@property(nonatomic, assign) BOOL isJoinRtcWhenCall; + +@property(nonatomic, assign) BOOL isVideoConfirm; + +@property(nonatomic, assign, readonly) bool incallShowCName; + +@property(nonatomic, strong, nullable) UIImage *muteDefaultImage; + +@property(nonatomic, strong, nullable) UIImage *remoteDefaultImage; + +@property(nonatomic, assign) BOOL isGroupPush; + +@property(nonatomic, strong) NSString *customPushContent; + +@property(nonatomic, assign, readonly) BOOL isGlobalInit; + +@property(nonatomic, assign, readonly) BOOL useEnableLocalMute; + ++ (id)shareInstance; + +- (void)setTimeoutWithSecond:(NSInteger)second; + +- (void)setAutoJoin:(BOOL)autoJoin; + +- (void)setBusyCode:(BOOL)open; + +- (void)setCallKitUid:(uint64_t)uid; + +- (void)setShowCName:(BOOL)show; + +- (NSString *)getRtcCName; + +- (uint64_t)getCallKitUid; + +- (void)setEnableLocal:(BOOL)enable; + +- (void)setIsGlobalInit:(BOOL)isGlobalInit + withApnsCer:(NSString *)apnsCer + withAppkey:(NSString *)appkey; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.m new file mode 100644 index 00000000..40f2bcf4 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.m @@ -0,0 +1,157 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "SettingManager.h" +#import +NSString *const kYXOTOTimeOut = @"kYXOTOTimeOut"; + +NSString *const kShowCName = @"kShowCName"; + +@interface SettingManager () + +@property(nonatomic, assign, readwrite) NSInteger timeout; + +@property(nonatomic, assign, readwrite) BOOL supportAutoJoinWhenCalled; + +@property(nonatomic, assign, readwrite) BOOL rejectBusyCode; + +@property(nonatomic, assign, readwrite) BOOL openCustomTokenAndChannelName; + +@property(nonatomic, assign, readwrite) bool incallShowCName; + +@property(nonatomic, assign, readwrite) BOOL useEnableLocalMute; + +@property(nonatomic, assign, readwrite) BOOL isGlobalInit; + +@end + +@implementation SettingManager + ++ (id)shareInstance { + static SettingManager *shareInstance = nil; + static dispatch_once_t once_token; + dispatch_once(&once_token, ^{ + if (!shareInstance) { + shareInstance = [[self alloc] init]; + } + }); + return shareInstance; +} + +- (void)setCallKitUid:(uint64_t)uid { + [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithUnsignedLongLong:uid] + forKeyPath:@"context.currentUserUid"]; + + // if ([[NERtcCallKit sharedInstance] respondsToSelector:@selector(changeStatusIdle)]) { + // [[NERtcCallKit sharedInstance] changeStatusIdle]; + // } +} + +- (uint64_t)getCallKitUid { + return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.currentUserUid"] + unsignedLongLongValue]; +} + +- (void)setAutoJoin:(BOOL)autoJoin { + [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:autoJoin] + forKeyPath:@"context.supportAutoJoinWhenCalled"]; + self.supportAutoJoinWhenCalled = autoJoin; +} + +- (void)setBusyCode:(BOOL)open { + self.rejectBusyCode = open; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.isGroupPush = YES; + self.supportAutoJoinWhenCalled = [[[NERtcCallKit sharedInstance] + valueForKeyPath:@"context.supportAutoJoinWhenCalled"] boolValue]; + self.rejectBusyCode = NO; + NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; + NSNumber *showCname = [userDefault objectForKey:kShowCName]; + if (showCname != nil) { + self.incallShowCName = [showCname boolValue]; + } + NSLog(@"current accid : %@", NIMSDK.sharedSDK.loginManager.currentAccount); + } + return self; +} + +- (void)setTimeoutWithSecond:(NSInteger)second { + [[NERtcCallKit sharedInstance] setTimeOutSeconds:second]; +} + +- (NSInteger)timeout { + return [[NERtcCallKit sharedInstance] timeOutSeconds]; +} + +- (BOOL)isGlobalInit { + return ![[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.globalInit"] boolValue]; +} + +- (void)setIsGlobalInit:(BOOL)isGlobalInit + withApnsCer:(NSString *)apnsCer + withAppkey:(NSString *)appkey { + [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:!isGlobalInit] + forKeyPath:@"context.globalInit"]; + if (isGlobalInit == NO) { + NERtcCallOptions *option = [NERtcCallOptions new]; + option.APNSCerName = apnsCer; + option.disableRecord = NO; + option.joinRtcWhenCall = [self isJoinRtcWhenCall]; + option.globalInit = YES; + NERtcCallKit *callkit = [NERtcCallKit sharedInstance]; + option.supportAutoJoinWhenCalled = self.supportAutoJoinWhenCalled; + [callkit setupAppKey:appkey options:option]; + } else { + [NERtcEngine destroyEngine]; + } +} + +- (BOOL)isJoinRtcWhenCall { + return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.joinRtcWhenCall"] boolValue]; +} + +- (void)setIsJoinRtcWhenCall:(BOOL)isJoinRtcWhenCall { + [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:isJoinRtcWhenCall] + forKeyPath:@"context.joinRtcWhenCall"]; +} + +- (BOOL)isAudioConfirm { + return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.confirmAudio"] boolValue]; +} + +- (void)setIsAudioConfirm:(BOOL)isAudioConfirm { + [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:isAudioConfirm] + forKeyPath:@"context.confirmAudio"]; +} + +- (BOOL)isVideoConfirm { + return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.confirmVideo"] boolValue]; +} + +- (void)setIsVideoConfirm:(BOOL)isVideoConfirm { + [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:isVideoConfirm] + forKeyPath:@"context.confirmVideo"]; +} + +- (NSString *)getRtcCName { + return [[NERtcCallKit sharedInstance] valueForKeyPath:@"context.channelInfo.channelName"]; +} + +- (void)setShowCName:(BOOL)show { + self.incallShowCName = show; + NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; + [userDefault setObject:[NSNumber numberWithBool:show] forKey:kShowCName]; + [userDefault synchronize]; +} + +// 1.5.6 add +- (void)setEnableLocal:(BOOL)enable { + self.useEnableLocalMute = enable; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.h new file mode 100644 index 00000000..ace9ddb5 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.h @@ -0,0 +1,32 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NECallParam : NSObject + +#pragma mark - 必要参数 +// 被叫accid +@property(nonatomic, strong) NSString *remoteUserAccid; +// 主叫accid +@property(nonatomic, strong) NSString *currentUserAccid; +// 通话页面被叫显示名称 +@property(nonatomic, strong) NSString *remoteShowName; +// 被叫头像链接 +@property(nonatomic, strong) NSString *remoteAvatar; +// 呼叫类型 +@property(assign, nonatomic) NERtcCallType callType; + +#pragma mark - 可选自定义参数 +@property(nonatomic, strong) NSString *token; +@property(nonatomic, strong) NSString *extra; +@property(nonatomic, strong) NSString *channelName; +@property(nonatomic, strong) NSString *attachment; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.m similarity index 68% rename from NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift rename to NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.m index c64290c5..3d6e0ec0 100644 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.m @@ -1,8 +1,9 @@ - // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit +#import "NECallParam.h" + +@implementation NECallParam -class QChatBaseCollectionViewCell: UICollectionViewCell {} +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.h new file mode 100644 index 00000000..624b5a2e --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.h @@ -0,0 +1,46 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NECallUIConfig : NSObject + +/// 是否禁止音频通话转视频通话,默认NO,支持转换 +@property(nonatomic, assign) BOOL audioToVideoDisable; + +/// 是否禁止音频通话转视频通话,默认NO,支持转换 +@property(nonatomic, assign) BOOL videoToAudioDisable; + +/// 收到呼叫时是否禁止弹出被叫页面,默认NO,弹出被叫页面,用户可以通过此配置禁止组件弹出,自己通过继承以及监听被叫回调实现相关功能 +@property(nonatomic, assign) BOOL disableShowCalleeView; + +/// 是否初始化路由配置,默认NO,不进行路由初始化配置 +@property(nonatomic, assign) BOOL isInitRouter; + +/// 通话前音视频切换按钮是否显示,默认NO,不显示,开启此配置前需要开启 NERtcCallOptions 中 +/// supportAutoJoinWhenCalled 属性 +@property(nonatomic, assign) BOOL showCallingSwitchCallType; + +/// 被叫显示昵称字段还是手机号字段,默认显示昵称 +@property(nonatomic, assign) BOOL calleeShowPhone; + +@end + +@interface NERtcCallUIConfig : NSObject + +/// 透传 NERtcCallKit 初始化配置,如果不需要UI组件内部初始化 NERtcCallKit 则不传此参数即可 +@property(nonatomic, strong) NERtcCallOptions *option; + +/// appkey +@property(nonatomic, strong) NSString *appKey; + +/// UI 配置 +@property(nonatomic, strong) NECallUIConfig *uiConfig; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.m new file mode 100644 index 00000000..068e1aea --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.m @@ -0,0 +1,20 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NERtcCallUIConfig.h" + +@implementation NECallUIConfig + +@end + +@implementation NERtcCallUIConfig + +- (NECallUIConfig *)uiConfig { + if (nil == _uiConfig) { + _uiConfig = [[NECallUIConfig alloc] init]; + } + return _uiConfig; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h new file mode 100644 index 00000000..49f2ba70 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h @@ -0,0 +1,57 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#ifndef NERtcCallUIKit_h +#define NERtcCallUIKit_h + +#import "NECallParam.h" +#import "NECallViewController.h" +#import "NECustomButton.h" +#import "NEExpandButton.h" +#import "NERtcCallUIConfig.h" +#import "NEVideoOperationView.h" +#import "NEVideoView.h" +#import "NetManager.h" +#import "SettingManager.h" + +#import "NEAudioCallingController.h" +#import "NEAudioInCallController.h" +#import "NECalledViewController.h" +#import "NEVideoCallingController.h" +#import "NEVideoInCallController.h" + +// 音频呼叫中UI状态 +extern NSString *_Nonnull kAudioCalling; +// 视频呼叫中UI状态 +extern NSString *_Nonnull kVideoCalling; +// 音频通话中UI状态 +extern NSString *_Nonnull kAudioInCall; +// 视频通话中UI状态 +extern NSString *_Nonnull kVideoInCall; +// 被叫UI状态(音频&视频) +extern NSString *_Nonnull kCalledState; + +#endif /* NERtcCallUIKit_h */ + +NS_ASSUME_NONNULL_BEGIN + +@interface NERtcCallUIKit : NSObject + +/// UI状态配置类,如果用户需要自定义某个状态的UI,需要继承通话状态类,通过对应key值覆盖对应Class +@property(nonatomic, strong, readonly) NSMutableDictionary *uiConfigDic; + ++ (instancetype)sharedInstance; + +/// 初始化,所有功能需要先初始化 +/// @param config 初始化参数 +- (void)setupWithConfig:(NERtcCallUIConfig *)config; + +- (void)callWithParam:(NECallParam *)callParam withCallType:(NERtcCallType)callType; + +/// 版本号 ++ (NSString *)version; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m new file mode 100644 index 00000000..8edb6e21 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m @@ -0,0 +1,230 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NERtcCallUIKit.h" +#import +#import +#import +#import "NetManager.h" + +NSString *kAudioCalling = @"kAudioCalling"; + +NSString *kVideoCalling = @"kVideoCalling"; + +NSString *kAudioInCall = @"kAudioInCall"; + +NSString *kVideoInCall = @"kVideoInCall"; + +NSString *kCalledState = @"kCalledState"; + +NSString *kMouldName = @"NERtcCallUIKit"; + +@interface NERtcCallUIKit () + +@property(nonatomic, strong) NERtcCallUIConfig *config; + +@property(nonatomic, strong) UIWindow *keywindow; + +@property(nonatomic, strong, readwrite) NSMutableDictionary *uiConfigDic; + +@property(nonatomic, strong) NSBundle *bundle; + +@end + +@implementation NERtcCallUIKit + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static NERtcCallUIKit *instance; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +- (NSString *)serviceName { + return kMouldName; +} + +- (NSString *)versionName { + return [NERtcCallUIKit version]; +} + +- (NSString *)appKey { + return self.config.appKey; +} + +- (void)setupWithConfig:(NERtcCallUIConfig *)config { + if (nil != config.option && config.appKey != nil) { + [[NERtcCallKit sharedInstance] setupAppKey:config.appKey options:config.option]; + } + [[XKit instance] registerService:self]; + self.config = config; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [NetManager shareInstance]; + [[NERtcCallKit sharedInstance] addDelegate:self]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didDismiss:) + name:kCallKitDismissNoti + object:nil]; + self.uiConfigDic = [[NSMutableDictionary alloc] init]; + [self.uiConfigDic setObject:NEAudioCallingController.class forKey:kAudioCalling]; + [self.uiConfigDic setObject:NEAudioInCallController.class forKey:kAudioInCall]; + [self.uiConfigDic setObject:NEVideoCallingController.class forKey:kVideoCalling]; + [self.uiConfigDic setObject:NEVideoInCallController.class forKey:kVideoInCall]; + [self registerRouter]; + [NERtcCallKit sharedInstance].recordHandler = ^(NIMMessage *message) { + if ([[NetManager shareInstance] isClose] == YES) { + NIMRtcCallRecordObject *object = (NIMRtcCallRecordObject *)message.messageObject; + object.callStatus = NIMRtcCallStatusCanceled; + } + }; + self.bundle = [NSBundle bundleForClass:self.class]; + } + return self; +} + +- (NSString *)localizableWithKey:(NSString *)key { + return [self.bundle localizedStringForKey:key value:nil table:@"Localizable"]; +} + +- (void)registerRouter { + [[Router shared] register:@"imkit://callkit.page" + closure:^(NSDictionary *_Nonnull param) { + if ([[NetManager shareInstance] isClose] == YES) { + [UIApplication.sharedApplication.keyWindow + makeToast:[self localizableWithKey:@"network_error"]]; + return; + } + NECallParam *callParam = [[NECallParam alloc] init]; + callParam.currentUserAccid = [param objectForKey:@"currentUserAccid"]; + callParam.remoteUserAccid = [param objectForKey:@"remoteUserAccid"]; + callParam.remoteShowName = [param objectForKey:@"remoteShowName"]; + callParam.remoteAvatar = [param objectForKey:@"remoteAvatar"]; + NSNumber *type = [param objectForKey:@"type"]; + NERtcCallType callType = NERtcCallTypeAudio; + if (type.intValue == 1) { + callType = NERtcCallTypeAudio; + } else if (type.intValue == 2) { + callType = NERtcCallTypeVideo; + } + [self callWithParam:callParam withCallType:callType]; + }]; +} + +- (void)callWithParam:(NECallParam *)callParam withCallType:(NERtcCallType)callType { + NECallViewController *callVC = [[NECallViewController alloc] init]; + if (callParam.remoteShowName.length <= 0) { + callParam.remoteShowName = callParam.remoteUserAccid; + } + callVC.isCaller = YES; + callVC.callType = callType; + callVC.status = NERtcCallStatusCalling; + callVC.callParam = callParam; + callVC.uiConfigDic = self.uiConfigDic; + callVC.config = self.config.uiConfig; + [self showCallView:callVC]; +} + +- (void)onInvited:(NSString *)invitor + userIDs:(NSArray *)userIDs + isFromGroup:(BOOL)isFromGroup + groupID:(NSString *)groupID + type:(NERtcCallType)type + attachment:(NSString *)attachment { + if (self.config.uiConfig.disableShowCalleeView == YES) { + return; + } + + [NIMSDK.sharedSDK.userManager + fetchUserInfos:@[ invitor ] + completion:^(NSArray *_Nullable users, NSError *_Nullable error) { + if (error) { + [UIApplication.sharedApplication.keyWindow makeToast:error.description]; + return; + } else { + NIMUser *imUser = users.firstObject; + NECallViewController *callVC = [[NECallViewController alloc] init]; + NECallParam *callParam = [[NECallParam alloc] init]; + callParam.remoteUserAccid = imUser.userId; + callParam.remoteShowName = self.config.uiConfig.calleeShowPhone == YES + ? imUser.userInfo.mobile + : imUser.userInfo.nickName; + callParam.remoteAvatar = imUser.userInfo.avatarUrl; + callParam.currentUserAccid = NIMSDK.sharedSDK.loginManager.currentAccount; + callVC.callParam = callParam; + callVC.isCaller = NO; + callVC.status = NERtcCallStatusCalled; + callVC.callType = type; + callVC.uiConfigDic = self.uiConfigDic; + callVC.config = self.config.uiConfig; + [self showCallView:callVC]; + } + }]; +} + +- (void)showCalled:(NIMUser *)imUser + callType:(NERtcCallType)type + attachment:(NSString *)attachment { + NECallViewController *callVC = [[NECallViewController alloc] init]; + NECallParam *callParam = [[NECallParam alloc] init]; + callParam.remoteUserAccid = imUser.userId; + callParam.remoteShowName = imUser.userInfo.mobile; + callParam.remoteAvatar = imUser.userInfo.avatarUrl; + callParam.currentUserAccid = NIMSDK.sharedSDK.loginManager.currentAccount; + callVC.callParam = callParam; + callVC.isCaller = NO; + callVC.status = NERtcCallStatusCalled; + callVC.callType = type; + callVC.uiConfigDic = self.uiConfigDic; + callVC.config = self.config.uiConfig; + [self showCallView:callVC]; +} + +- (void)showCallView:(UIViewController *)callVC { + UINavigationController *nav = [self getKeyWindowNav]; + UINavigationController *callNav = + [[UINavigationController alloc] initWithRootViewController:callVC]; + callNav.modalPresentationStyle = UIModalPresentationFullScreen; + [callNav.navigationBar setHidden:YES]; + [nav presentViewController:callNav animated:YES completion:nil]; +} + +- (UINavigationController *)getKeyWindowNav { + UIWindow *window = [[UIWindow alloc] init]; + window.frame = [[UIScreen mainScreen] bounds]; + window.windowLevel = UIWindowLevelStatusBar - 1; + UIViewController *root = [[UIViewController alloc] init]; + root.view.backgroundColor = [UIColor clearColor]; + UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root]; + nav.navigationBar.tintColor = [UIColor clearColor]; + nav.view.backgroundColor = [UIColor clearColor]; + [nav.navigationBar setHidden:YES]; + self.keywindow = window; + window.rootViewController = nav; + window.backgroundColor = [UIColor clearColor]; + [window makeKeyAndVisible]; + return nav; +} + +- (void)didDismiss:(NSNotification *)noti { + UINavigationController *nav = (UINavigationController *)self.keywindow.rootViewController; + __weak typeof(self) weakSelf = self; + [nav dismissViewControllerAnimated:YES + completion:^{ + NSLog(@"self window %@", weakSelf.keywindow); + [weakSelf.keywindow resignKeyWindow]; + weakSelf.keywindow = nil; + }]; +} + ++ (NSString *)version { + return @"1.8.2"; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NECustomButton.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NECustomButton.h new file mode 100644 index 00000000..4971da31 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NECustomButton.h @@ -0,0 +1,15 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NECustomButton : UIView +@property(strong, nonatomic) UIImageView *imageView; +@property(strong, nonatomic) UILabel *titleLabel; +@property(strong, nonatomic) UIButton *maskBtn; +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NECustomButton.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NECustomButton.m new file mode 100644 index 00000000..929bcd11 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NECustomButton.m @@ -0,0 +1,70 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECustomButton.h" + +@implementation NECustomButton +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self addSubview:self.imageView]; + [self addSubview:self.titleLabel]; + [self addSubview:self.maskBtn]; + + [NSLayoutConstraint activateConstraints:@[ + [self.imageView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.imageView.leftAnchor constraintEqualToAnchor:self.leftAnchor], + [self.imageView.rightAnchor constraintEqualToAnchor:self.rightAnchor], + [self.imageView.widthAnchor constraintEqualToConstant:75], + [self.imageView.heightAnchor constraintEqualToConstant:75], + ]]; + + [NSLayoutConstraint activateConstraints:@[ + [self.titleLabel.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:-40], + [self.titleLabel.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:40], + [self.titleLabel.topAnchor constraintEqualToAnchor:self.imageView.bottomAnchor constant:8], + [self.titleLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0] + ]]; + + [NSLayoutConstraint activateConstraints:@[ + [self.maskBtn.leftAnchor constraintEqualToAnchor:self.leftAnchor], + [self.maskBtn.rightAnchor constraintEqualToAnchor:self.rightAnchor], + [self.maskBtn.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.maskBtn.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] + ]]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + } + return self; +} + +- (UIImageView *)imageView { + if (!_imageView) { + _imageView = [[UIImageView alloc] init]; + _imageView.userInteractionEnabled = NO; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + _imageView.contentMode = UIViewContentModeCenter; + } + return _imageView; +} +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:14]; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _titleLabel; +} + +- (UIButton *)maskBtn { + if (!_maskBtn) { + _maskBtn = [[UIButton alloc] init]; + _maskBtn.backgroundColor = [UIColor clearColor]; + _maskBtn.translatesAutoresizingMaskIntoConstraints = NO; + } + return _maskBtn; +} +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEExpandButton.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEExpandButton.h new file mode 100644 index 00000000..4be819ea --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEExpandButton.h @@ -0,0 +1,13 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NEExpandButton : UIButton + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEExpandButton.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEExpandButton.m new file mode 100644 index 00000000..64071d2c --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEExpandButton.m @@ -0,0 +1,18 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEExpandButton.h" + +@implementation NEExpandButton + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { + CGRect bounds = self.bounds; + // 若原热区小于44x44,则放大热区,否则保持原大小不变 + CGFloat widthDelta = MAX(44.0 - bounds.size.width, 0); + CGFloat heightDelta = MAX(44.0 - bounds.size.height, 0); + bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta); + return CGRectContainsPoint(bounds, point); +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h new file mode 100644 index 00000000..8604c52f --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h @@ -0,0 +1,24 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NEVideoOperationView : UIView +@property(strong, nonatomic) UIButton *microPhone; +@property(strong, nonatomic) UIButton *cameraBtn; +@property(strong, nonatomic) UIButton *hangupBtn; +@property(strong, nonatomic) UIButton *speakerBtn; +@property(strong, nonatomic) UIButton *mediaBtn; + +- (void)changeAudioStyle; +- (void)changeVideoStyle; +- (void)hideMediaSwitch; + +- (void)setGroupStyle; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m new file mode 100644 index 00000000..86562072 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m @@ -0,0 +1,146 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEVideoOperationView.h" + +@interface NEVideoOperationView () + +@property(nonatomic, strong) UIStackView *stack; + +@property(nonatomic, strong) NSBundle *bundle; + +@end + +@implementation NEVideoOperationView +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.bundle = [NSBundle bundleForClass:self.class]; + [self setupUI]; + } + return self; +} +- (void)setupUI { + self.backgroundColor = [UIColor colorWithRed:39 / 255.0 + green:48 / 255.0 + blue:48 / 255.0 + alpha:1.0]; + UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[ + self.microPhone, self.cameraBtn, self.speakerBtn, self.mediaBtn, self.hangupBtn + ]]; + stackView.distribution = + UIStackViewDistributionEqualCentering; // UIStackViewDistributionFillEqually; + + [self addSubview:stackView]; + stackView.translatesAutoresizingMaskIntoConstraints = NO; + [NSLayoutConstraint activateConstraints:@[ + [stackView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:20], + [stackView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-20], + [stackView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0], + [stackView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0], + + ]]; + // [stackView mas_makeConstraints:^(MASConstraintMaker *make) { + // make.edges.mas_equalTo(UIEdgeInsetsMake(0, 20, 0, 20)); + // }]; + self.stack = stackView; +} +- (UIButton *)microPhone { + if (!_microPhone) { + _microPhone = [UIButton buttonWithType:UIButtonTypeCustom]; + [_microPhone setImage:[UIImage imageNamed:@"call_voice_on" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + [_microPhone setImage:[UIImage imageNamed:@"call_voice_off" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateSelected]; + _microPhone.accessibilityIdentifier = @"op_micro_phone"; + } + return _microPhone; +} +- (UIButton *)cameraBtn { + if (!_cameraBtn) { + _cameraBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_cameraBtn setImage:[UIImage imageNamed:@"call_camera_on" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + [_cameraBtn setImage:[UIImage imageNamed:@"call_camera_off" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateSelected]; + _cameraBtn.accessibilityIdentifier = @"op_video_mute"; + } + return _cameraBtn; +} +- (UIButton *)hangupBtn { + if (!_hangupBtn) { + _hangupBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_hangupBtn setImage:[UIImage imageNamed:@"hangup" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + _hangupBtn.accessibilityIdentifier = @"op_hangup"; + } + return _hangupBtn; +} +- (UIButton *)speakerBtn { + if (nil == _speakerBtn) { + _speakerBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_speakerBtn setImage:[UIImage imageNamed:@"call_speaker_off" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateSelected]; + [_speakerBtn setImage:[UIImage imageNamed:@"call_speaker_on" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + _speakerBtn.accessibilityIdentifier = @"op_speaker"; + } + return _speakerBtn; +} +- (UIButton *)mediaBtn { + if (nil == _mediaBtn) { + _mediaBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_mediaBtn setImage:[UIImage imageNamed:@"call_switch_audio" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + [_mediaBtn setImage:[UIImage imageNamed:@"call_switch_video" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateSelected]; + _mediaBtn.accessibilityIdentifier = @"switch_media_btn"; + } + return _mediaBtn; +} + +- (void)changeAudioStyle { + [self.stack removeArrangedSubview:self.cameraBtn]; + [self.cameraBtn removeFromSuperview]; + self.mediaBtn.selected = YES; +} + +- (void)changeVideoStyle { + [self.stack insertArrangedSubview:self.cameraBtn atIndex:1]; + self.mediaBtn.selected = NO; +} + +- (void)hideMediaSwitch { + [self.stack removeArrangedSubview:self.mediaBtn]; + [self.mediaBtn removeFromSuperview]; + [self.stack removeArrangedSubview:self.cameraBtn]; + [self.cameraBtn removeFromSuperview]; +} + +- (void)setGroupStyle { + [self.stack removeArrangedSubview:self.mediaBtn]; + [self.stack removeArrangedSubview:self.speakerBtn]; + [self.mediaBtn removeFromSuperview]; + [self.speakerBtn removeFromSuperview]; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoView.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoView.h new file mode 100644 index 00000000..a33bfeae --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoView.h @@ -0,0 +1,18 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NEVideoView : UIView +@property(strong, nonatomic) NSString *userID; +@property(strong, nonatomic) UIView *videoView; +@property(strong, nonatomic) UILabel *titleLabel; +@property(strong, nonatomic) UIView *maskView; +@property(strong, nonatomic) UIImageView *imageView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoView.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoView.m new file mode 100644 index 00000000..25d6e1b9 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoView.m @@ -0,0 +1,80 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEVideoView.h" + +@implementation NEVideoView +- (instancetype)init { + self = [super init]; + if (self) { + [self addSubview:self.videoView]; + [NSLayoutConstraint activateConstraints:@[ + [self.videoView.leftAnchor constraintEqualToAnchor:self.leftAnchor], + [self.videoView.rightAnchor constraintEqualToAnchor:self.rightAnchor], + [self.videoView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.videoView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] + ]]; + [self addSubview:self.maskView]; + [NSLayoutConstraint activateConstraints:@[ + [self.maskView.leftAnchor constraintEqualToAnchor:self.leftAnchor], + [self.maskView.rightAnchor constraintEqualToAnchor:self.rightAnchor], + [self.maskView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.maskView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] + ]]; + [self addSubview:self.titleLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.titleLabel.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:10], + [self.titleLabel.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-10], + [self.titleLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:10], + [self.titleLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-10] + ]]; + [self addSubview:self.imageView]; + [NSLayoutConstraint activateConstraints:@[ + [self.imageView.leftAnchor constraintEqualToAnchor:self.leftAnchor], + [self.imageView.rightAnchor constraintEqualToAnchor:self.rightAnchor], + [self.imageView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.imageView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] + ]]; + } + return self; +} +- (UIView *)videoView { + if (!_videoView) { + _videoView = [[UIView alloc] init]; + _videoView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _videoView; +} +- (UIView *)maskView { + if (!_maskView) { + _maskView = [[UIView alloc] init]; + _maskView.backgroundColor = [UIColor darkGrayColor]; + _maskView.hidden = YES; + _maskView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _maskView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.font = [UIFont systemFontOfSize:20]; + _titleLabel.numberOfLines = 0; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + } + return _titleLabel; +} + +- (UIImageView *)imageView { + if (_imageView == nil) { + _imageView = [[UIImageView alloc] init]; + _imageView.userInteractionEnabled = YES; + _imageView.contentMode = UIViewContentModeScaleAspectFill; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _imageView; +} +@end diff --git a/NETeamUIKit/NETeamUIKit.podspec b/NETeamUIKit/NETeamUIKit.podspec index 4f1f43cd..d23b9064 100644 --- a/NETeamUIKit/NETeamUIKit.podspec +++ b/NETeamUIKit/NETeamUIKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NETeamUIKit' - s.version = '9.3.0' + s.version = '9.2.10' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -27,9 +27,9 @@ TODO: Add long description of the pod here. s.source = { :git => 'https://github.com/netease/NEKitGroupUI.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' s.pod_target_xcconfig = { + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64', 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } - s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } s.ios.deployment_target = '9.0' s.swift_version = '5.0' @@ -45,6 +45,6 @@ TODO: Add long description of the pod here. s.dependency 'NECommonUIKit' s.dependency 'NETeamKit' s.dependency 'NIMSDK_LITE' - s.dependency 'YXAlog_iOS' + s.dependency 'YXAlog' end diff --git a/NETeamUIKit/NETeamUIKit/Assets/en.lproj/Localizable.strings b/NETeamUIKit/NETeamUIKit/Assets/en.lproj/Localizable.strings index ec826c22..7fecc69e 100644 --- a/NETeamUIKit/NETeamUIKit/Assets/en.lproj/Localizable.strings +++ b/NETeamUIKit/NETeamUIKit/Assets/en.lproj/Localizable.strings @@ -33,7 +33,7 @@ "save"="Save"; "historical_record"="History"; "search"="Search"; -"no_search_results"="No content"; +"no_search_results"="No History"; "discuss_info"="Temp Group Info"; "group_info"="Group Info"; "discuss_introduce"="Temp Group Introduce"; @@ -48,3 +48,4 @@ "discuss_name"="Temp Group Name"; "discuss_intro"="Temp Group Introduce"; "invite_has_send"="Invitation sent"; +"space_not_support"="All Spaces are not supported"; diff --git a/NETeamUIKit/NETeamUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NETeamUIKit/NETeamUIKit/Assets/zh-Hans.lproj/Localizable.strings index a2f371d5..5834a476 100644 --- a/NETeamUIKit/NETeamUIKit/Assets/zh-Hans.lproj/Localizable.strings +++ b/NETeamUIKit/NETeamUIKit/Assets/zh-Hans.lproj/Localizable.strings @@ -33,7 +33,7 @@ "save"="保存"; "historical_record"="历史记录"; "search"="搜索"; -"no_search_results"="暂无搜索结果"; +"no_search_results"="暂无聊天记录"; "discuss_info"="讨论组信息"; "group_info"="群信息"; "discuss_introduce"="讨论组介绍"; @@ -48,3 +48,4 @@ "discuss_name"="讨论组名称"; "discuss_intro"="讨论组介绍"; "invite_has_send"="邀请已发送"; +"space_not_support"="不支持全空格"; diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingCellModel.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingCellModel.swift index 5963d485..dbaa8807 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingCellModel.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingCellModel.swift @@ -24,6 +24,7 @@ public class SettingCellModel: NSObject { public var type = SettingCellType.SettingArrowCell.rawValue public var swichChange: SwitchChangeCompletion? public var rowHeight: CGFloat = 49 + public var titleWidth: CGFloat = 32 public var cornerType = CornerType.none public var headerUrl: String? public var cellClick: CellClick? diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamIntroduceViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamIntroduceViewController.swift index cd08085f..fd2364ae 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamIntroduceViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamIntroduceViewController.swift @@ -15,7 +15,7 @@ public class TeamIntroduceViewController: NEBaseViewController, UITextViewDelega // var block: SaveCompletion? var team: NIMTeam? - + let textLimit = 100 let repo = TeamRepo() lazy var textView: UITextView = { @@ -96,9 +96,9 @@ public class TeamIntroduceViewController: NEBaseViewController, UITextViewDelega ]) if let intr = team?.intro { - countLabel.text = "\(intr.count)/100" + countLabel.text = "\(intr.count)/\(textLimit)" } else { - countLabel.text = "0/100" + countLabel.text = "0/\(textLimit)" } if changePermission() == false { @@ -161,28 +161,17 @@ public class TeamIntroduceViewController: NEBaseViewController, UITextViewDelega // MARK: UITextViewDelegate - public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, - replacementText text: String) -> Bool { - let currentText = textView.text ?? "" - guard let stringRange = Range(range, in: currentText) else { return false } - let updatedText = currentText.replacingCharacters(in: stringRange, with: text) - return updatedText.count <= 100 - } - public func textViewDidChange(_ textView: UITextView) { + if let _ = textView.markedTextRange { + return + } if var text = textView.text { - if let lang = textView.textInputMode?.primaryLanguage, lang == "zh-Hans", - let selectRange = textView.markedTextRange { - let position = textView.position(from: selectRange.start, offset: 0) - if position == nil { - if text.count > 30 { - text = String(text.prefix(30)) - textView.text = String(text.prefix(30)) - } - countLabel.text = "\(text.count)/100" + if let lang = textView.textInputMode?.primaryLanguage, lang == "zh-Hans" { + if text.count > textLimit { + text = String(text.prefix(textLimit)) + textView.text = String(text) } - } else { - countLabel.text = "\(text.count)/100" + countLabel.text = "\(text.count)/\(textLimit)" } } } diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamNameViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamNameViewController.swift index 9943340d..dd81c52e 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamNameViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamNameViewController.swift @@ -20,6 +20,7 @@ public class TeamNameViewController: NEBaseViewController, UITextFieldDelegate { var type = ChangeType.TeamName var teamMember: NIMTeamMember? var repo = TeamRepo() + let textLimit = 30 lazy var countLabel: UILabel = { let label = UILabel() @@ -108,7 +109,7 @@ public class TeamNameViewController: NEBaseViewController, UITextFieldDelegate { name = n } - countLabel.text = "\(name.count)/30" + countLabel.text = "\(name.count)/\(textLimit)" textField.text = name if name.count <= 0, type != .NickName { @@ -162,24 +163,32 @@ public class TeamNameViewController: NEBaseViewController, UITextFieldDelegate { // MARK: objc 方法 func textFieldChange() { + if let _ = textField.markedTextRange { + return + } if var text = textField.text { - if let lang = textField.textInputMode?.primaryLanguage, lang == "zh-Hans", - let selectRange = textField.markedTextRange { - let position = textField.position(from: selectRange.start, offset: 0) - if position == nil { - if text.count > 30 { - text = String(text.prefix(30)) - textField.text = String(text.prefix(30)) - } - figureTextCount(text) + if let lang = textField.textInputMode?.primaryLanguage, lang == "zh-Hans" { + if text.count > textLimit { + text = String(text.prefix(textLimit)) + textField.text = String(text) } - } else { figureTextCount(text) } } } func saveName() { + if let text = textField.text, + !text.isEmpty { + let trimText = text.trimmingCharacters(in: .whitespaces) + if trimText.isEmpty { + view.makeToast(localizable("space_not_support"), duration: 2, position: .center) + textField.text = trimText + figureTextCount(trimText) + return + } + } + weak var weakSelf = self textField.resignFirstResponder() if type == .TeamName, let tid = team?.teamId { @@ -208,21 +217,11 @@ public class TeamNameViewController: NEBaseViewController, UITextFieldDelegate { } } } - - // MAKR: UITextFieldDelegate - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - if let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string), - text.count > 30 { - return false - } - return true - } } extension TeamNameViewController { func figureTextCount(_ text: String) { - countLabel.text = "\(text.count)/30" + countLabel.text = "\(text.count)/\(textLimit)" if type == .NickName { return } diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamSettingViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamSettingViewController.swift index 64ee7e73..9d177b4d 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamSettingViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/TeamSettingViewController.swift @@ -8,16 +8,26 @@ import NECommonUIKit import NECoreIMKit import NIMSDK +@objc +public enum TeamSettingType: Int { + case Discuss = 0 + case Senior = 1 +} + @objcMembers public class TeamSettingViewController: NEBaseViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITableViewDataSource, UITableViewDelegate { - let viewmodel = TeamSettingViewModel() + public let viewmodel = TeamSettingViewModel() - var teamId: String? + public var teamId: String? var addBtnWidth: NSLayoutConstraint? + public var teamSettingType: TeamSettingType = .Discuss + + public var isSeniorDiscuss = false // 是否是高级群扩展的讨论组 + private let className = "TeamSettingViewController" public var cellClassDic = [ @@ -104,6 +114,7 @@ public class TeamSettingViewController: NEBaseViewController, UICollectionViewDe override public func viewDidLoad() { super.viewDidLoad() + title = localizable("setting") weak var weakSelf = self viewmodel.delegate = self @@ -116,6 +127,18 @@ public class TeamSettingViewController: NEBaseViewController, UICollectionViewDe if let err = error { weakSelf?.showToast(err.localizedDescription) } else { + if let type = weakSelf?.viewmodel.teamInfoModel?.team?.type { + if type == .normal { + weakSelf?.teamSettingType = .Discuss + } else if type == .advanced { + if let custom = weakSelf?.viewmodel.teamInfoModel?.team?.clientCustomInfo, custom.contains(discussTeamKey) { + weakSelf?.teamSettingType = .Discuss + weakSelf?.isSeniorDiscuss = true + } else { + weakSelf?.teamSettingType = .Senior + } + } + } weakSelf?.contentTable.tableHeaderView = weakSelf?.getHeaderView() weakSelf?.contentTable.tableFooterView = weakSelf?.getFooterView() weakSelf?.contentTable.reloadData() @@ -216,7 +239,7 @@ public class TeamSettingViewController: NEBaseViewController, UICollectionViewDe memberLabel.topAnchor.constraint(equalTo: line.bottomAnchor, constant: 12), ]) - if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + if teamSettingType == .Senior { memberLabel.text = localizable("group_memmber") } else { memberLabel.text = localizable("discuss_mebmer") @@ -305,9 +328,9 @@ public class TeamSettingViewController: NEBaseViewController, UICollectionViewDe } func getBottomText() -> String? { - if let type = viewmodel.teamInfoModel?.team?.type, type == .normal { + if teamSettingType == .Discuss { return localizable("leave_discuss") - } else if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + } else if teamSettingType == .Senior { return viewmodel.isOwner() ? localizable("dismiss_team") : localizable("leave_team") } return nil @@ -366,23 +389,54 @@ public class TeamSettingViewController: NEBaseViewController, UICollectionViewDe func removeTeamForMyself() { weak var weakSelf = self - if viewmodel.isOwner(), let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { - showAlert(message: localizable("dissolute_team_chat")) { - weakSelf?.dismissTeam() + if teamSettingType == .Senior { + showAlert(message: viewmodel.isOwner() ? localizable("dissolute_team_chat") : localizable("quit_team_chat")) { + if weakSelf?.viewmodel.isOwner() == true { + weakSelf?.dismissTeam() + } else { + weakSelf?.leaveTeam() + } } - } else { - if let type = viewmodel.teamInfoModel?.team?.type { - if type == .advanced { - showAlert(message: localizable("quit_team_chat")) { - weakSelf?.leveaTeam() - } - } else if type == .normal { - showAlert(message: localizable("quit_discuss_chat")) { - weakSelf?.leveaTeam() - } + } else if teamSettingType == .Discuss { + showAlert(message: localizable("quit_discuss_chat")) { + weakSelf?.leaveDiscuss() + } + } + /* + if viewmodel.isOwner(), let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + showAlert(message: localizable("dissolute_team_chat")) { + weakSelf?.dismissTeam() + } + } else { + if let type = viewmodel.teamInfoModel?.team?.type { + if let custom = viewmodel.teamInfoModel?.team?.clientCustomInfo, type == .normal || (type == .advanced && custom.contains(discussTeamKey)) { + showAlert(message: localizable("quit_discuss_chat")) { + weakSelf?.leveaTeam() + } + }else if type == .advanced { + showAlert(message: localizable("quit_team_chat")) { + weakSelf?.leveaTeam() + } + } + } + } */ + } + + func leaveDiscuss() { + weak var weakSelf = self + if isSeniorDiscuss == true, viewmodel.isOwner() { + view.makeToastActivity(.center) + viewmodel.transferTeamOwner { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + return } + weakSelf?.navigationController?.popViewController(animated: true) } + return } + leaveTeam() } func toInfoView() { @@ -394,7 +448,7 @@ public class TeamSettingViewController: NEBaseViewController, UICollectionViewDe func toMemberList() { let memberController = TeamMembersController() memberController.datas = viewmodel.teamInfoModel?.users - if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + if teamSettingType == .Senior { memberController.isSenior = true } memberController.ownerId = viewmodel.teamInfoModel?.team?.owner @@ -585,20 +639,28 @@ extension TeamSettingViewController { } } - func leveaTeam() { + func leaveTeam() { if let tid = teamId { - weak var weakSelf = self view.makeToastActivity(.center) - viewmodel.quitTeam(tid) { error in + viewmodel.quitTeam(tid) { [weak self] error in NELog.infoLog( - ModuleName + " " + self.className, + ModuleName + " " + (self?.className ?? "TeamSettingViewController"), desc: "CALLBACK quitTeam " + (error?.localizedDescription ?? "no error") ) - weakSelf?.view.hideToastActivity() + self?.view.hideToastActivity() if let err = error { - weakSelf?.showToast(err.localizedDescription) + self?.showToast(err.localizedDescription) } else { - weakSelf?.navigationController?.popViewController(animated: true) + let session = NIMSession(tid, type: .team) + if let stickInfo = self?.viewmodel.getTopSessionInfo(session) { + self?.viewmodel.removeStickTop(params: stickInfo) { err, _ in + NELog.infoLog( + ModuleName + " " + (self?.className ?? "TeamSettingViewController"), + desc: "CALLBACK removeStickTop " + (error?.localizedDescription ?? "no error") + ) + } + } + self?.navigationController?.popViewController(animated: true) } } } @@ -612,6 +674,8 @@ extension TeamSettingViewController: TeamSettingViewModelDelegate { func didNeedRefreshUI() { contentTable.reloadData() + refreshMemberCount() + userinfoCollection.reloadData() } func didChangeInviteModeClick(_ model: SettingCellModel) { diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/TeamSettingSubtitleCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/TeamSettingSubtitleCell.swift index 21ea2341..4ae2cc12 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/TeamSettingSubtitleCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/TeamSettingSubtitleCell.swift @@ -7,6 +7,8 @@ import UIKit @objcMembers public class TeamSettingSubtitleCell: BaseTeamSettingCell { + var titleWidthAnchor: NSLayoutConstraint? + override public func awakeFromNib() { super.awakeFromNib() // Initialization code @@ -36,26 +38,30 @@ public class TeamSettingSubtitleCell: BaseTeamSettingCell { NSLayoutConstraint.activate([ titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), ]) + titleWidthAnchor = titleLabel.widthAnchor.constraint(equalToConstant: 0) + titleWidthAnchor?.isActive = true NSLayoutConstraint.activate([ arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + arrow.widthAnchor.constraint(equalToConstant: 7), ]) NSLayoutConstraint.activate([ + subTitleLabel.leftAnchor.constraint(equalTo: titleLabel.rightAnchor, constant: 10), subTitleLabel.rightAnchor.constraint(equalTo: arrow.leftAnchor, constant: -10), subTitleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - subTitleLabel.widthAnchor.constraint(equalToConstant: 200), ]) - - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true } override public func configure(_ anyModel: Any) { super.configure(anyModel) - subTitleLabel.text = model?.subTitle + if let m = anyModel as? SettingCellModel { + titleWidthAnchor?.constant = m.titleWidth + subTitleLabel.text = m.subTitle + } } lazy var subTitleLabel: UILabel = { diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift index 639af2b4..8e8a0519 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift @@ -5,6 +5,7 @@ import Foundation import NETeamKit import NIMSDK +import NECoreIMKit @objcMembers public class TeamInfoViewModel: NSObject { @@ -27,7 +28,7 @@ public class TeamInfoViewModel: NSObject { intrCell.type = SettingCellType.SettingArrowCell.rawValue intrCell.cornerType = .bottomLeft.union(.bottomRight) - if let type = team?.type, type == .normal { + if let type = team?.type, type == .normal || (type == .advanced && team?.clientCustomInfo?.contains(discussTeamKey) == true) { headerCell.cellName = localizable("discuss_avatar") nameCell.cellName = localizable("discuss_name") intrCell.cellName = localizable("discuss_intro") diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift index e863632b..9dcfb20c 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift @@ -6,6 +6,7 @@ import Foundation import NETeamKit import NIMSDK import UIKit +import NECoreIMKit protocol TeamSettingViewModelDelegate: NSObjectProtocol { func didClickChangeNick() @@ -17,22 +18,31 @@ protocol TeamSettingViewModelDelegate: NSObjectProtocol { } @objcMembers -public class TeamSettingViewModel: NSObject { - var sectionData = [SettingSectionModel]() +public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { + public var sectionData = [SettingSectionModel]() - var searchResultInfos: [HistoryMessageModel]? + public var searchResultInfos: [HistoryMessageModel]? - var teamInfoModel: TeamInfoModel? + public var teamInfoModel: TeamInfoModel? - let repo = TeamRepo() + public let repo = TeamRepo() - var memberInTeam: NIMTeamMember? + public var memberInTeam: NIMTeamMember? weak var delegate: TeamSettingViewModelDelegate? private let className = "TeamSettingViewModel" - override public init() {} + private var usersDic = [String: TeamMemberInfoModel]() + + override public init() { + super.init() + NIMSDK.shared().teamManager.add(self) + } + + deinit { + NIMSDK.shared().teamManager.remove(self) + } func getData() { NELog.infoLog(ModuleName + " " + className, desc: #function) @@ -40,6 +50,9 @@ public class TeamSettingViewModel: NSObject { sectionData.append(getTwoSection()) print("current team type : ", teamInfoModel?.team?.type.rawValue as Any) if let type = teamInfoModel?.team?.type, type == .advanced { + if teamInfoModel?.team?.clientCustomInfo?.contains(discussTeamKey) == true { + return + } sectionData.append(getThreeSection()) sectionData.append(getFourSection()) } @@ -153,6 +166,7 @@ public class TeamSettingViewModel: NSObject { return model } + // 群昵称/群禁言 private func getThreeSection() -> SettingSectionModel { NELog.infoLog(ModuleName + " " + className, desc: #function) let model = SettingSectionModel() @@ -289,9 +303,16 @@ public class TeamSettingViewModel: NSObject { repo.fetchTeamInfo(teamId) { error, teamInfo in weakSelf?.teamInfoModel = teamInfo print("get team info user: ", teamInfo?.users as Any) + teamInfo?.users.forEach { member in + print("team meber accid : ", member.nimUser?.userId as Any) + } print("get team info team: ", teamInfo?.team as Any) print("get team info error: ", error as Any) - + teamInfo?.users.forEach { model in + if let id = model.nimUser?.userId as? String { + weakSelf?.usersDic[id] = model + } + } if error == nil { weakSelf?.getData() weakSelf?.getCurrentMember(IMKitEngine.instance.imAccid, teamId) @@ -310,6 +331,18 @@ public class TeamSettingViewModel: NSObject { repo.quitTeam(teamId, completion) } + public func getTopSessionInfo(_ session: NIMSession) -> NIMStickTopSessionInfo { + NELog.infoLog(ModuleName + " " + className, desc: #function + ", teamId:\(session.sessionId)") + return repo.getTopSessionInfo(session) + } + + public func removeStickTop(params: NIMStickTopSessionInfo, + _ completion: @escaping (NSError?, NIMStickTopSessionInfo?) + -> Void) { + NELog.infoLog(ModuleName + " " + className, desc: #function + ", teamId:\(params.session.sessionId)") + repo.removeStickTop(params: params, completion) + } + @discardableResult func getCurrentMember(_ userId: String, _ teamId: String?) -> NIMTeamMember? { NELog.infoLog(ModuleName + " " + className, desc: #function + ", userId:\(userId)") @@ -329,6 +362,38 @@ public class TeamSettingViewModel: NSObject { return false } + private func sampleMemberId(arr: [TeamMemberInfoModel], owner: String) -> String? { + var index = arc4random_uniform(UInt32(arr.count)) + while arr[Int(index)].teamMember?.userId == owner { + index = arc4random_uniform(UInt32(arr.count)) + } + return arr[Int(index)].teamMember?.userId + } + + func transferTeamOwner(_ completion: @escaping (Error?) -> Void) { + if isOwner() == false { + completion(NSError(domain: "imuikit", code: -1, userInfo: [NSLocalizedDescriptionKey: "not team manager"])) + return + } + + guard let members = teamInfoModel?.users, let teamId = teamInfoModel?.team?.teamId else { + completion(NSError(domain: "imuikit", code: -1, userInfo: [NSLocalizedDescriptionKey: "team info error"])) + return + } + + var userId = NIMSDK.shared().loginManager.currentAccount() + if members.count == 1 { + dismissTeam(teamId, completion) + return + } else if let sampleOwnerId = sampleMemberId(arr: members, owner: userId) { + userId = sampleOwnerId + } + + NIMSDK.shared().teamManager.transferManager(withTeam: teamId, newOwnerId: userId, isLeave: true) { error in + completion(error) + } + } + public func updateInfoMode(_ mode: NIMTeamUpdateInfoMode, _ teamId: String, _ completion: @escaping (Error?) -> Void) { NELog.infoLog(ModuleName + " " + className, desc: #function + ", mode:\(mode.rawValue)") @@ -362,4 +427,24 @@ public class TeamSettingViewModel: NSObject { } } } + + public func onTeamMemberRemoved(_ team: NIMTeam, withMembers memberIDs: [String]?) { + if let accids = memberIDs { + weak var weakSelf = self + accids.forEach { accid in + if let model = weakSelf?.usersDic[accid] { + if let index = weakSelf?.teamInfoModel?.users.firstIndex(of: model) { + weakSelf?.teamInfoModel?.users.remove(at: index) + } + } + } + delegate?.didNeedRefreshUI() + } + } + + public func onTeamMemberChanged(_ team: NIMTeam) {} + + public func onTeamUpdated(_ team: NIMTeam) { + teamInfoModel?.team = team + } } diff --git a/NETeamUIKit/NETeamUIKit/Classes/TeamRouter.swift b/NETeamUIKit/NETeamUIKit/Classes/TeamRouter.swift index f60840b4..7103bd9a 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/TeamRouter.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/TeamRouter.swift @@ -33,9 +33,21 @@ public class TeamRouter: NSObject { if name.count > 30 { name = String(name.prefix(30)) } + let iconUrl = (param["url"] as? String) ?? iconUrls[Int(arc4random()) % iconUrls.count] - repo.createNormalTeam(name, iconUrl, accids) { error, teamid, failedIds in + + let option = NIMCreateTeamOption() + option.type = .advanced + option.avatarUrl = iconUrl + option.name = name + option.joinMode = .noAuth + option.inviteMode = .all + option.beInviteMode = .noAuth + option.updateInfoMode = .all + option.updateClientCustomMode = .all + + repo.createAdvanceTeam(accids, option) { error, teamid, failedIds in var result = [String: Any]() if let err = error { result["code"] = err.code @@ -44,6 +56,13 @@ public class TeamRouter: NSObject { result["code"] = 0 result["msg"] = "ok" result["teamId"] = teamid + if let tid = teamid { + repo.updateTeamCustomInfo(discussTeamKey, tid) { error in + if let err = error { + print(#function + "error: \(err.localizedDescription)") + } + } + } } Router.shared.use(TeamCreateDiscussResult, parameters: result, closure: nil) } @@ -57,9 +76,16 @@ public class TeamRouter: NSObject { if name.count > 30 { name = String(name.prefix(30)) } + let iconUrl = (param["url"] as? String) ?? iconUrls[Int(arc4random()) % iconUrls.count] - repo.createAdvanceTeam(name, iconUrl, accids) { error, teamid, failedIds in + + let option = NIMCreateTeamOption() + option.type = .advanced + option.avatarUrl = iconUrl + option.name = name + + repo.createAdvanceTeam(accids, option) { error, teamid, failedIds in var result = [String: Any]() if let err = error { result["code"] = err.code diff --git a/Podfile b/Podfile index 97b5f636..56b9fe0f 100644 --- a/Podfile +++ b/Podfile @@ -10,37 +10,39 @@ target 'app' do pod 'YXLogin', '1.0.0' #可选UI库 - pod 'NEContactUIKit', '9.3.0' - pod 'NEQChatUIKit', '9.3.0' - pod 'NEConversationUIKit', '9.3.1' - pod 'NEChatUIKit', '9.3.0' - pod 'NETeamUIKit', '9.3.0' + pod 'NEContactUIKit', '9.4.0' + pod 'NEConversationUIKit', '9.4.0' + pod 'NEChatUIKit', '9.4.0' + pod 'NETeamUIKit', '9.4.0' #可选Kit库(和UIKit对应) - pod 'NEContactKit', '9.3.0' - pod 'NEQChatKit', '9.3.0' - pod 'NEConversationKit', '9.3.0' - pod 'NEChatKit', '9.3.0' - pod 'NETeamKit', '9.3.0' + pod 'NEContactKit', '9.4.0' + pod 'NEConversationKit', '9.4.0' + pod 'NEChatKit', '9.4.0' + pod 'NETeamKit', '9.4.0' #基础kit库 - pod 'NECommonUIKit', '9.3.0' - pod 'NECommonKit', '9.3.0' - pod 'NECoreIMKit', '9.3.0' - pod 'NECoreKit', '9.3.0' + pod 'NECommonUIKit', '9.4.0' + pod 'NECommonKit', '9.4.0' + pod 'NECoreIMKit', '9.4.0' + pod 'NECoreKit', '9.4.0' #扩展库 - pod 'NEMapKit', '9.3.1' - +# pod 'NEMapKit', '9.4.0' + + #呼叫组件,音视频通话能力,需要开通 音视频2.0,可选,聊天一面会根据依赖初始化自动显示音视频通话入口 + pod 'NERtcCallUIKit', '1.8.2' + pod 'NERtcCallKit', '1.8.2' + pod 'NERtcSDK', '4.6.29' # 如果需要查看UI部分源码请注释掉以上在线依赖,打开下面的本地依赖 -# pod 'NEQChatUIKit', :path => 'NEQChatUIKit/NEQChatUIKit.podspec' # pod 'NEContactUIKit', :path => 'NEContactUIKit/NEContactUIKit.podspec' # pod 'NEConversationUIKit', :path => 'NEConversationUIKit/NEConversationUIKit.podspec' # pod 'NETeamUIKit', :path => 'NETeamUIKit/NETeamUIKit.podspec' # pod 'NEChatUIKit', :path => 'NEChatUIKit/NEChatUIKit.podspec' # pod 'NEMapKit', :path => 'NEMapKit/NEMapKit.podspec' +# pod 'NERtcCallUIKit', :path => 'NERtcCallUIKit/NERtcCallUIKit.podspec' end diff --git a/app.xcodeproj/project.pbxproj b/app.xcodeproj/project.pbxproj index f04b2571..b6c28802 100644 --- a/app.xcodeproj/project.pbxproj +++ b/app.xcodeproj/project.pbxproj @@ -7,30 +7,34 @@ objects = { /* Begin PBXBuildFile section */ - 398D733F290692FC00662649 /* MineSettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D732C290692FC00662649 /* MineSettingViewModel.swift */; }; - 398D7340290692FC00662649 /* PersonInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D732D290692FC00662649 /* PersonInfoViewModel.swift */; }; - 398D7341290692FC00662649 /* MessageRemindViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D732E290692FC00662649 /* MessageRemindViewModel.swift */; }; - 398D7342290692FC00662649 /* IntroduceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D732F290692FC00662649 /* IntroduceViewModel.swift */; }; - 398D7343290692FC00662649 /* MeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D7331290692FC00662649 /* MeViewController.swift */; }; - 398D7344290692FC00662649 /* NEAboutWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D7332290692FC00662649 /* NEAboutWebViewController.swift */; }; - 398D7346290692FC00662649 /* InputPersonInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D7334290692FC00662649 /* InputPersonInfoController.swift */; }; - 398D7347290692FC00662649 /* MessageRemindViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D7335290692FC00662649 /* MessageRemindViewController.swift */; }; - 398D7349290692FC00662649 /* PersonInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D7337290692FC00662649 /* PersonInfoViewController.swift */; }; - 398D734A290692FC00662649 /* IntroduceBrandViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D7338290692FC00662649 /* IntroduceBrandViewController.swift */; }; - 398D734B290692FC00662649 /* MineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D733A290692FC00662649 /* MineTableViewCell.swift */; }; - 398D734C290692FC00662649 /* BirthdayDatePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D733B290692FC00662649 /* BirthdayDatePickerView.swift */; }; - 398D734E290692FC00662649 /* VersionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D733D290692FC00662649 /* VersionCell.swift */; }; - 398D73512906940C00662649 /* MineSettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 398D73502906940C00662649 /* MineSettingViewController.swift */; }; - 39A36F8128002CFF009B07A9 /* NETabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39A36F8028002CFF009B07A9 /* NETabBarController.swift */; }; 39E9E27728D87E9800A11820 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 39E9E27528D87E9800A11820 /* Localizable.strings */; }; - 39F793C827E20434007F63FF /* NENavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39F793C727E20434007F63FF /* NENavigationController.swift */; }; - 4B3B9BDF277AFEE50091A74E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3B9BDE277AFEE50091A74E /* AppDelegate.swift */; }; - 4B3B9BE3277AFEE50091A74E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3B9BE2277AFEE50091A74E /* ViewController.swift */; }; 4B3B9BE6277AFEE50091A74E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B3B9BE4277AFEE50091A74E /* Main.storyboard */; }; 4B3B9BE8277AFEE70091A74E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4B3B9BE7277AFEE70091A74E /* Assets.xcassets */; }; 4B3B9BEB277AFEE70091A74E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B3B9BE9277AFEE70091A74E /* LaunchScreen.storyboard */; }; 8D94D1BFC1723D94D352756A /* Pods_app.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8ECED9A11CC9DB62207FC66 /* Pods_app.framework */; }; 9EA2014127BE4B4800F8BBD0 /* AppKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA2014027BE4B4800F8BBD0 /* AppKey.swift */; }; + DDFAAE8029BACE0B00834C08 /* NodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6229BACE0B00834C08 /* NodeViewModel.swift */; }; + DDFAAE8129BACE0B00834C08 /* MineSettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6329BACE0B00834C08 /* MineSettingViewModel.swift */; }; + DDFAAE8229BACE0B00834C08 /* PersonInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6429BACE0B00834C08 /* PersonInfoViewModel.swift */; }; + DDFAAE8329BACE0B00834C08 /* MessageRemindViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6529BACE0B00834C08 /* MessageRemindViewModel.swift */; }; + DDFAAE8429BACE0B00834C08 /* IntroduceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6629BACE0B00834C08 /* IntroduceViewModel.swift */; }; + DDFAAE8529BACE0B00834C08 /* MeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6829BACE0B00834C08 /* MeViewController.swift */; }; + DDFAAE8629BACE0B00834C08 /* NEAboutWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6929BACE0B00834C08 /* NEAboutWebViewController.swift */; }; + DDFAAE8829BACE0B00834C08 /* InputPersonInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6B29BACE0B00834C08 /* InputPersonInfoController.swift */; }; + DDFAAE8929BACE0B00834C08 /* MineSettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6C29BACE0B00834C08 /* MineSettingViewController.swift */; }; + DDFAAE8A29BACE0B00834C08 /* MessageRemindViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6D29BACE0B00834C08 /* MessageRemindViewController.swift */; }; + DDFAAE8B29BACE0B00834C08 /* NENodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6E29BACE0B00834C08 /* NENodeViewController.swift */; }; + DDFAAE8C29BACE0B00834C08 /* PersonInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE6F29BACE0B00834C08 /* PersonInfoViewController.swift */; }; + DDFAAE8D29BACE0C00834C08 /* IntroduceBrandViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7029BACE0B00834C08 /* IntroduceBrandViewController.swift */; }; + DDFAAE8E29BACE0C00834C08 /* MineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7229BACE0B00834C08 /* MineTableViewCell.swift */; }; + DDFAAE8F29BACE0C00834C08 /* BirthdayDatePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7329BACE0B00834C08 /* BirthdayDatePickerView.swift */; }; + DDFAAE9029BACE0C00834C08 /* NodeSelectCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7429BACE0B00834C08 /* NodeSelectCell.swift */; }; + DDFAAE9129BACE0C00834C08 /* VersionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7529BACE0B00834C08 /* VersionCell.swift */; }; + DDFAAE9329BACE0C00834C08 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7929BACE0B00834C08 /* ViewController.swift */; }; + DDFAAE9529BACE0C00834C08 /* NENavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7B29BACE0B00834C08 /* NENavigationController.swift */; }; + DDFAAE9729BACE0C00834C08 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7D29BACE0B00834C08 /* AppDelegate.swift */; }; + DDFAAE9829BACE0C00834C08 /* NETabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE7E29BACE0B00834C08 /* NETabBarController.swift */; }; + DDFAAE9F29BAFD1500834C08 /* NEUserHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFAAE9E29BAFD1500834C08 /* NEUserHeaderView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -52,27 +56,9 @@ 01B0A28E2816CF41009065C5 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = ""; }; 01C0FC0F27BE754400C32949 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; 01C0FC1027BE754500C32949 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; - 398D732C290692FC00662649 /* MineSettingViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineSettingViewModel.swift; sourceTree = ""; }; - 398D732D290692FC00662649 /* PersonInfoViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonInfoViewModel.swift; sourceTree = ""; }; - 398D732E290692FC00662649 /* MessageRemindViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRemindViewModel.swift; sourceTree = ""; }; - 398D732F290692FC00662649 /* IntroduceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntroduceViewModel.swift; sourceTree = ""; }; - 398D7331290692FC00662649 /* MeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeViewController.swift; sourceTree = ""; }; - 398D7332290692FC00662649 /* NEAboutWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NEAboutWebViewController.swift; sourceTree = ""; }; - 398D7334290692FC00662649 /* InputPersonInfoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputPersonInfoController.swift; sourceTree = ""; }; - 398D7335290692FC00662649 /* MessageRemindViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRemindViewController.swift; sourceTree = ""; }; - 398D7337290692FC00662649 /* PersonInfoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonInfoViewController.swift; sourceTree = ""; }; - 398D7338290692FC00662649 /* IntroduceBrandViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntroduceBrandViewController.swift; sourceTree = ""; }; - 398D733A290692FC00662649 /* MineTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineTableViewCell.swift; sourceTree = ""; }; - 398D733B290692FC00662649 /* BirthdayDatePickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BirthdayDatePickerView.swift; sourceTree = ""; }; - 398D733D290692FC00662649 /* VersionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionCell.swift; sourceTree = ""; }; - 398D73502906940C00662649 /* MineSettingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineSettingViewController.swift; sourceTree = ""; }; - 39A36F8028002CFF009B07A9 /* NETabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NETabBarController.swift; sourceTree = ""; }; 39E9E27628D87E9800A11820 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 39E9E27828D87EA000A11820 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; - 39F793C727E20434007F63FF /* NENavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NENavigationController.swift; sourceTree = ""; }; 4B3B9BDB277AFEE50091A74E /* app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = app.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B3B9BDE277AFEE50091A74E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 4B3B9BE2277AFEE50091A74E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 4B3B9BE5277AFEE50091A74E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 4B3B9BE7277AFEE70091A74E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 4B3B9BEA277AFEE70091A74E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; @@ -80,6 +66,29 @@ A9E4316D70F3EF2E6BD5E5CB /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = ""; }; B831F1EC5F2E309A7BB5582D /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = ""; }; D8ECED9A11CC9DB62207FC66 /* Pods_app.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_app.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DDFAAE6229BACE0B00834C08 /* NodeViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NodeViewModel.swift; sourceTree = ""; }; + DDFAAE6329BACE0B00834C08 /* MineSettingViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineSettingViewModel.swift; sourceTree = ""; }; + DDFAAE6429BACE0B00834C08 /* PersonInfoViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonInfoViewModel.swift; sourceTree = ""; }; + DDFAAE6529BACE0B00834C08 /* MessageRemindViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRemindViewModel.swift; sourceTree = ""; }; + DDFAAE6629BACE0B00834C08 /* IntroduceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntroduceViewModel.swift; sourceTree = ""; }; + DDFAAE6829BACE0B00834C08 /* MeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeViewController.swift; sourceTree = ""; }; + DDFAAE6929BACE0B00834C08 /* NEAboutWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NEAboutWebViewController.swift; sourceTree = ""; }; + DDFAAE6B29BACE0B00834C08 /* InputPersonInfoController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputPersonInfoController.swift; sourceTree = ""; }; + DDFAAE6C29BACE0B00834C08 /* MineSettingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineSettingViewController.swift; sourceTree = ""; }; + DDFAAE6D29BACE0B00834C08 /* MessageRemindViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRemindViewController.swift; sourceTree = ""; }; + DDFAAE6E29BACE0B00834C08 /* NENodeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NENodeViewController.swift; sourceTree = ""; }; + DDFAAE6F29BACE0B00834C08 /* PersonInfoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonInfoViewController.swift; sourceTree = ""; }; + DDFAAE7029BACE0B00834C08 /* IntroduceBrandViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntroduceBrandViewController.swift; sourceTree = ""; }; + DDFAAE7229BACE0B00834C08 /* MineTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineTableViewCell.swift; sourceTree = ""; }; + DDFAAE7329BACE0B00834C08 /* BirthdayDatePickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BirthdayDatePickerView.swift; sourceTree = ""; }; + DDFAAE7429BACE0B00834C08 /* NodeSelectCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NodeSelectCell.swift; sourceTree = ""; }; + DDFAAE7529BACE0B00834C08 /* VersionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionCell.swift; sourceTree = ""; }; + DDFAAE7929BACE0B00834C08 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + DDFAAE7B29BACE0B00834C08 /* NENavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NENavigationController.swift; sourceTree = ""; }; + DDFAAE7D29BACE0B00834C08 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + DDFAAE7E29BACE0B00834C08 /* NETabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NETabBarController.swift; sourceTree = ""; }; + DDFAAE9A29BAECF100834C08 /* app-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "app-Bridging-Header.h"; sourceTree = ""; }; + DDFAAE9E29BAFD1500834C08 /* NEUserHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NEUserHeaderView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -102,102 +111,107 @@ name = Frameworks; sourceTree = ""; }; - 398D7329290692FC00662649 /* Mine */ = { + 4B3B9BD2277AFEE50091A74E = { isa = PBXGroup; children = ( - 398D732A290692FC00662649 /* ViewModel */, - 398D7330290692FC00662649 /* Controller */, - 398D7339290692FC00662649 /* View */, + 4B3B9BDD277AFEE50091A74E /* app */, + 4B3B9BDC277AFEE50091A74E /* Products */, + BF083551FB71DB2F668919FB /* Pods */, + 345791C57A67E47F5C6B3317 /* Frameworks */, ); - path = Mine; sourceTree = ""; }; - 398D732A290692FC00662649 /* ViewModel */ = { + 4B3B9BDC277AFEE50091A74E /* Products */ = { isa = PBXGroup; children = ( - 398D732C290692FC00662649 /* MineSettingViewModel.swift */, - 398D732D290692FC00662649 /* PersonInfoViewModel.swift */, - 398D732E290692FC00662649 /* MessageRemindViewModel.swift */, - 398D732F290692FC00662649 /* IntroduceViewModel.swift */, + 4B3B9BDB277AFEE50091A74E /* app.app */, ); - path = ViewModel; + name = Products; sourceTree = ""; }; - 398D7330290692FC00662649 /* Controller */ = { + 4B3B9BDD277AFEE50091A74E /* app */ = { isa = PBXGroup; children = ( - 398D73502906940C00662649 /* MineSettingViewController.swift */, - 398D7331290692FC00662649 /* MeViewController.swift */, - 398D7332290692FC00662649 /* NEAboutWebViewController.swift */, - 398D7334290692FC00662649 /* InputPersonInfoController.swift */, - 398D7335290692FC00662649 /* MessageRemindViewController.swift */, - 398D7337290692FC00662649 /* PersonInfoViewController.swift */, - 398D7338290692FC00662649 /* IntroduceBrandViewController.swift */, + DDFAAE7829BACE0B00834C08 /* Main */, + DDFAAE6029BACE0B00834C08 /* Mine */, + 01B0A28E2816CF41009065C5 /* app.entitlements */, + 9EA2014027BE4B4800F8BBD0 /* AppKey.swift */, + 39E9E27528D87E9800A11820 /* Localizable.strings */, + 4B3B9BE4277AFEE50091A74E /* Main.storyboard */, + 4B3B9BE7277AFEE70091A74E /* Assets.xcassets */, + 4B3B9BE9277AFEE70091A74E /* LaunchScreen.storyboard */, + DDFAAE9A29BAECF100834C08 /* app-Bridging-Header.h */, ); - path = Controller; + path = app; sourceTree = ""; }; - 398D7339290692FC00662649 /* View */ = { + BF083551FB71DB2F668919FB /* Pods */ = { isa = PBXGroup; children = ( - 398D733A290692FC00662649 /* MineTableViewCell.swift */, - 398D733B290692FC00662649 /* BirthdayDatePickerView.swift */, - 398D733D290692FC00662649 /* VersionCell.swift */, + B831F1EC5F2E309A7BB5582D /* Pods-app.debug.xcconfig */, + A9E4316D70F3EF2E6BD5E5CB /* Pods-app.release.xcconfig */, ); - path = View; + path = Pods; sourceTree = ""; }; - 398D734F2906931E00662649 /* Main */ = { + DDFAAE6029BACE0B00834C08 /* Mine */ = { isa = PBXGroup; children = ( - 39F793C727E20434007F63FF /* NENavigationController.swift */, - 39A36F8028002CFF009B07A9 /* NETabBarController.swift */, - 4B3B9BDE277AFEE50091A74E /* AppDelegate.swift */, + DDFAAE6129BACE0B00834C08 /* ViewModel */, + DDFAAE6729BACE0B00834C08 /* Controller */, + DDFAAE7129BACE0B00834C08 /* View */, ); - path = Main; + path = Mine; sourceTree = ""; }; - 4B3B9BD2277AFEE50091A74E = { + DDFAAE6129BACE0B00834C08 /* ViewModel */ = { isa = PBXGroup; children = ( - 4B3B9BDD277AFEE50091A74E /* app */, - 4B3B9BDC277AFEE50091A74E /* Products */, - BF083551FB71DB2F668919FB /* Pods */, - 345791C57A67E47F5C6B3317 /* Frameworks */, + DDFAAE6229BACE0B00834C08 /* NodeViewModel.swift */, + DDFAAE6329BACE0B00834C08 /* MineSettingViewModel.swift */, + DDFAAE6429BACE0B00834C08 /* PersonInfoViewModel.swift */, + DDFAAE6529BACE0B00834C08 /* MessageRemindViewModel.swift */, + DDFAAE6629BACE0B00834C08 /* IntroduceViewModel.swift */, ); + path = ViewModel; sourceTree = ""; }; - 4B3B9BDC277AFEE50091A74E /* Products */ = { + DDFAAE6729BACE0B00834C08 /* Controller */ = { isa = PBXGroup; children = ( - 4B3B9BDB277AFEE50091A74E /* app.app */, + DDFAAE6829BACE0B00834C08 /* MeViewController.swift */, + DDFAAE6929BACE0B00834C08 /* NEAboutWebViewController.swift */, + DDFAAE6B29BACE0B00834C08 /* InputPersonInfoController.swift */, + DDFAAE6C29BACE0B00834C08 /* MineSettingViewController.swift */, + DDFAAE6D29BACE0B00834C08 /* MessageRemindViewController.swift */, + DDFAAE6E29BACE0B00834C08 /* NENodeViewController.swift */, + DDFAAE6F29BACE0B00834C08 /* PersonInfoViewController.swift */, + DDFAAE7029BACE0B00834C08 /* IntroduceBrandViewController.swift */, ); - name = Products; + path = Controller; sourceTree = ""; }; - 4B3B9BDD277AFEE50091A74E /* app */ = { + DDFAAE7129BACE0B00834C08 /* View */ = { isa = PBXGroup; children = ( - 398D734F2906931E00662649 /* Main */, - 398D7329290692FC00662649 /* Mine */, - 01B0A28E2816CF41009065C5 /* app.entitlements */, - 9EA2014027BE4B4800F8BBD0 /* AppKey.swift */, - 4B3B9BE2277AFEE50091A74E /* ViewController.swift */, - 39E9E27528D87E9800A11820 /* Localizable.strings */, - 4B3B9BE4277AFEE50091A74E /* Main.storyboard */, - 4B3B9BE7277AFEE70091A74E /* Assets.xcassets */, - 4B3B9BE9277AFEE70091A74E /* LaunchScreen.storyboard */, + DDFAAE9E29BAFD1500834C08 /* NEUserHeaderView.swift */, + DDFAAE7229BACE0B00834C08 /* MineTableViewCell.swift */, + DDFAAE7329BACE0B00834C08 /* BirthdayDatePickerView.swift */, + DDFAAE7429BACE0B00834C08 /* NodeSelectCell.swift */, + DDFAAE7529BACE0B00834C08 /* VersionCell.swift */, ); - path = app; + path = View; sourceTree = ""; }; - BF083551FB71DB2F668919FB /* Pods */ = { + DDFAAE7829BACE0B00834C08 /* Main */ = { isa = PBXGroup; children = ( - B831F1EC5F2E309A7BB5582D /* Pods-app.debug.xcconfig */, - A9E4316D70F3EF2E6BD5E5CB /* Pods-app.release.xcconfig */, + DDFAAE7929BACE0B00834C08 /* ViewController.swift */, + DDFAAE7B29BACE0B00834C08 /* NENavigationController.swift */, + DDFAAE7D29BACE0B00834C08 /* AppDelegate.swift */, + DDFAAE7E29BACE0B00834C08 /* NETabBarController.swift */, ); - path = Pods; + path = Main; sourceTree = ""; }; /* End PBXGroup section */ @@ -237,6 +251,7 @@ TargetAttributes = { 4B3B9BDA277AFEE50091A74E = { CreatedOnToolsVersion = 13.0; + LastSwiftMigration = 1410; }; }; }; @@ -337,25 +352,29 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 39F793C827E20434007F63FF /* NENavigationController.swift in Sources */, - 398D7346290692FC00662649 /* InputPersonInfoController.swift in Sources */, - 398D7343290692FC00662649 /* MeViewController.swift in Sources */, - 398D7349290692FC00662649 /* PersonInfoViewController.swift in Sources */, - 398D734A290692FC00662649 /* IntroduceBrandViewController.swift in Sources */, - 398D733F290692FC00662649 /* MineSettingViewModel.swift in Sources */, + DDFAAE8129BACE0B00834C08 /* MineSettingViewModel.swift in Sources */, + DDFAAE8A29BACE0B00834C08 /* MessageRemindViewController.swift in Sources */, + DDFAAE8529BACE0B00834C08 /* MeViewController.swift in Sources */, + DDFAAE8929BACE0B00834C08 /* MineSettingViewController.swift in Sources */, + DDFAAE8D29BACE0C00834C08 /* IntroduceBrandViewController.swift in Sources */, + DDFAAE8029BACE0B00834C08 /* NodeViewModel.swift in Sources */, + DDFAAE9829BACE0C00834C08 /* NETabBarController.swift in Sources */, + DDFAAE8C29BACE0B00834C08 /* PersonInfoViewController.swift in Sources */, + DDFAAE8F29BACE0C00834C08 /* BirthdayDatePickerView.swift in Sources */, + DDFAAE8B29BACE0B00834C08 /* NENodeViewController.swift in Sources */, 9EA2014127BE4B4800F8BBD0 /* AppKey.swift in Sources */, - 398D7340290692FC00662649 /* PersonInfoViewModel.swift in Sources */, - 4B3B9BE3277AFEE50091A74E /* ViewController.swift in Sources */, - 398D734C290692FC00662649 /* BirthdayDatePickerView.swift in Sources */, - 39A36F8128002CFF009B07A9 /* NETabBarController.swift in Sources */, - 398D7342290692FC00662649 /* IntroduceViewModel.swift in Sources */, - 398D7344290692FC00662649 /* NEAboutWebViewController.swift in Sources */, - 398D7347290692FC00662649 /* MessageRemindViewController.swift in Sources */, - 4B3B9BDF277AFEE50091A74E /* AppDelegate.swift in Sources */, - 398D734E290692FC00662649 /* VersionCell.swift in Sources */, - 398D7341290692FC00662649 /* MessageRemindViewModel.swift in Sources */, - 398D73512906940C00662649 /* MineSettingViewController.swift in Sources */, - 398D734B290692FC00662649 /* MineTableViewCell.swift in Sources */, + DDFAAE8829BACE0B00834C08 /* InputPersonInfoController.swift in Sources */, + DDFAAE9729BACE0C00834C08 /* AppDelegate.swift in Sources */, + DDFAAE8629BACE0B00834C08 /* NEAboutWebViewController.swift in Sources */, + DDFAAE9129BACE0C00834C08 /* VersionCell.swift in Sources */, + DDFAAE8229BACE0B00834C08 /* PersonInfoViewModel.swift in Sources */, + DDFAAE8429BACE0B00834C08 /* IntroduceViewModel.swift in Sources */, + DDFAAE9F29BAFD1500834C08 /* NEUserHeaderView.swift in Sources */, + DDFAAE8E29BACE0C00834C08 /* MineTableViewCell.swift in Sources */, + DDFAAE9329BACE0C00834C08 /* ViewController.swift in Sources */, + DDFAAE8329BACE0B00834C08 /* MessageRemindViewModel.swift in Sources */, + DDFAAE9029BACE0C00834C08 /* NodeSelectCell.swift in Sources */, + DDFAAE9529BACE0C00834C08 /* NENavigationController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -520,6 +539,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = app/app.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; @@ -554,7 +574,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "app/app-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -566,6 +587,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = app/app.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; @@ -600,7 +622,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = inHouseYunxin; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "app/app-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/app/Main/AppDelegate.swift b/app/Main/AppDelegate.swift index 5280ff4b..83b7336f 100644 --- a/app/Main/AppDelegate.swift +++ b/app/Main/AppDelegate.swift @@ -1,45 +1,56 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEContactUIKit import YXLogin import NECoreKit import NIMSDK -import NEQChatUIKit import NECoreIMKit import NEConversationUIKit import NETeamUIKit import NEChatUIKit import NEMapKit +import NERtcCallKit +import NERtcCallUIKit @main class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { public var window: UIWindow? + private var tabbarCtrl = UITabBarController() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + window?.backgroundColor = .white setupInit() NotificationCenter.default.addObserver(self, selector: #selector(refreshRoot), name: Notification.Name("logout"), object: nil) registerAPNS() return true } + func setupInit(){ + // init let option = NIMSDKOption() option.appKey = AppKey.appKey option.apnsCername = AppKey.pushCerName IMKitClient.instance.setupCoreKitIM(option) - NEKeyboardManager.shared.enable = true NEKeyboardManager.shared.shouldResignOnTouchOutside = true - - //login action - startLogin(account: <#imAccid#>, token: <#imToken#>) - + + weak var weakSelf = self + IMKitClient.instance.loginIM("<#accid#>", "<#token#>") { error in + if let err = error { + print("NEKitCore login error : ", err) + }else { + ChatRouter.setupInit() + weakSelf?.initializePage() + } + } } @objc func refreshRoot(){ @@ -79,46 +90,47 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD NELog.infoLog("app delegate : ", desc: error.localizedDescription) } - func startLogin(account:String,token:String){ - weak var weakSelf = self - IMKitClient.instance.loginIM(account, token) { error in - if let err = error { - print("NEKitCore login error : ", err) - }else { - ChatRouter.setupInit() - let param = QChatLoginParam(account,token) - IMKitClient.instance.loginQchat(param) { error, response in - if let err = error { - print("qchatLogin failed, error : ", err) - }else { - weakSelf?.setupTabbar() - } - } - } - } - } - - - func setupTabbar() { + func initializePage() { self.window?.rootViewController = NETabBarController() loadService() } - //路由注册 +// regist router func loadService() { + //TODO: service ContactRouter.register() ChatRouter.register() TeamRouter.register() ConversationRouter.register() + + //地图map初始化 + NEMapClient.shared().setupMapClient(withAppkey: AppKey.gaodeMapAppkey) + + /* 聊天面板外部扩展示例 + let item = NEMoreItemModel() + item.customDelegate = self + item.action = #selector(testLog) + item.customImage = UIImage(named: "chatSelect") + NEChatUIKitClient.instance.moreAction.append(item) + */ + + //呼叫组件初始化 + let option = NERtcCallOptions() + option.apnsCerName = AppKey.pushCerName + option.isDisableLog = true + let uiConfig = NERtcCallUIConfig() + uiConfig.option = option + uiConfig.appKey = AppKey.appKey + uiConfig.uiConfig.showCallingSwitchCallType = option.supportAutoJoinWhenCalled + NERtcCallKit.sharedInstance().timeOutSeconds = 30 + NERtcCallUIKit.sharedInstance().setup(with: uiConfig) + Router.shared.register(MeSettingRouter) { param in if let nav = param["nav"] as? UINavigationController { let me = PersonInfoViewController() nav.pushViewController(me, animated: true) } } - - //地图map初始化 - NEMapClient.shared().setupMapClient(withAppkey: AppKey.gaodeMapAppkey) } func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { diff --git a/app/Main/NENavigationController.swift b/app/Main/NENavigationController.swift index 803b1104..9d3a996b 100644 --- a/app/Main/NENavigationController.swift +++ b/app/Main/NENavigationController.swift @@ -31,4 +31,11 @@ class NENavigationController: UINavigationController { } super.pushViewController(viewController, animated: true) } + + override func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? { + if children.count > 0 { + viewController.hidesBottomBarWhenPushed = true + } + return super.popToViewController(viewController, animated: animated) + } } diff --git a/app/Main/NETabBarController.swift b/app/Main/NETabBarController.swift index d6947b0b..ba6c56a8 100644 --- a/app/Main/NETabBarController.swift +++ b/app/Main/NETabBarController.swift @@ -6,7 +6,6 @@ import UIKit import NIMSDK import NECoreKit -import NEQChatUIKit import NECoreIMKit import NEConversationUIKit import NETeamUIKit @@ -37,16 +36,6 @@ class NETabBarController: UITabBarController { ) let chatNav = NENavigationController(rootViewController: chat) - // qchat - let qchat = QChatHomeViewController() - qchat.view.backgroundColor = UIColor(hexString: "#e9eff5") - qchat.tabBarItem = UITabBarItem( - title: NSLocalizedString("qchat", comment: ""), - image: UIImage(named: "qchat_tabbar_icon"), - selectedImage: UIImage(named: "qchat_tabbar_icon")?.withRenderingMode(.alwaysOriginal) - ) - let qChatNav = NENavigationController(rootViewController: qchat) - // Contacts let contactVC = ContactsViewController() contactVC.tabBarItem = UITabBarItem( @@ -68,14 +57,14 @@ class NETabBarController: UITabBarController { let meNav = NENavigationController(rootViewController: meVC) tabBar.backgroundColor = .white - viewControllers = [chatNav, qChatNav, contactsNav, meNav] + viewControllers = [chatNav, contactsNav, meNav] selectedIndex = 0 } func setUpSessionBadgeValue() { - sessionUnreadCount = ConversationRepo().getMsgUnreadCount(notify: true) + sessionUnreadCount = ConversationProvider.shared.allUnreadCount(notify: true) if sessionUnreadCount > 0 { - tabBar.showBadgOn(index: 0) + tabBar.showBadgOn(index: 0, tabbarItemNums: 3) } else { tabBar.hideBadg(on: 0) } @@ -84,9 +73,9 @@ class NETabBarController: UITabBarController { func setUpContactBadgeValue() { contactUnreadCount = NIMSDK.shared().systemNotificationManager.allUnreadCount() if contactUnreadCount > 0 { - tabBar.showBadgOn(index: 2) + tabBar.showBadgOn(index: 1, tabbarItemNums: 3) } else { - tabBar.hideBadg(on: 2) + tabBar.hideBadg(on: 1) } } diff --git a/app/ViewController.swift b/app/Main/ViewController.swift similarity index 100% rename from app/ViewController.swift rename to app/Main/ViewController.swift diff --git a/app/Mine/Controller/InputPersonInfoController.swift b/app/Mine/Controller/InputPersonInfoController.swift index 47c54f9c..de711202 100644 --- a/app/Mine/Controller/InputPersonInfoController.swift +++ b/app/Mine/Controller/InputPersonInfoController.swift @@ -43,12 +43,21 @@ class InputPersonInfoController: NEBaseViewController, UITextFieldDelegate { textfieldBgView.heightAnchor.constraint(equalToConstant: 50), ]) } else { - NSLayoutConstraint.activate([ - textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), - textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - textfieldBgView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12), - textfieldBgView.heightAnchor.constraint(equalToConstant: 50), - ]) + if #available(iOS 10.0, *) { + NSLayoutConstraint.activate([ + textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), + textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + textfieldBgView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12), + textfieldBgView.heightAnchor.constraint(equalToConstant: 50), + ]) + } else { + NSLayoutConstraint.activate([ + textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), + textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + textfieldBgView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12 + kNavigationHeight + KStatusBarHeight), + textfieldBgView.heightAnchor.constraint(equalToConstant: 50), + ]) + } } textfieldBgView.addSubview(textField) @@ -69,7 +78,7 @@ class InputPersonInfoController: NEBaseViewController, UITextFieldDelegate { weak var weakSelf = self if let block = callBack { block(textField.text ?? "") - weakSelf?.navigationController?.popViewController(animated: true) +// weakSelf?.navigationController?.popViewController(animated: true) } } @@ -100,6 +109,7 @@ class InputPersonInfoController: NEBaseViewController, UITextFieldDelegate { text.delegate = self text.clearButtonMode = .always text.becomeFirstResponder() + text.addTarget(self, action: #selector(textFieldChange), for: .editingChanged) return text }() @@ -112,15 +122,15 @@ class InputPersonInfoController: NEBaseViewController, UITextFieldDelegate { return backView }() - // MARK: UITextFieldDelegate - - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { - if let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string), - text.count > limitNumberCount { - showToast("最多只能输入\(limitNumberCount)个字符哦") - return false + @objc + func textFieldChange() { + guard let _ = textField.markedTextRange else { + if let text = textField.text, + text.count > limitNumberCount { + textField.text = String(text.prefix(limitNumberCount)) + showToast(String(format: NSLocalizedString("text_count_limit", comment: ""), limitNumberCount)) + } + return } - return true } } diff --git a/app/Mine/Controller/IntroduceBrandViewController.swift b/app/Mine/Controller/IntroduceBrandViewController.swift index cd2dd54f..66ad1621 100644 --- a/app/Mine/Controller/IntroduceBrandViewController.swift +++ b/app/Mine/Controller/IntroduceBrandViewController.swift @@ -1,4 +1,3 @@ - // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. @@ -25,7 +24,7 @@ class IntroduceBrandViewController: NEBaseViewController, UITableViewDelegate, func setupSubviews() { view.addSubview(headImage) - view.addSubview(headLable) + view.addSubview(headLabel) view.addSubview(tableView) @@ -37,12 +36,11 @@ class IntroduceBrandViewController: NEBaseViewController, UITableViewDelegate, ), headImage.widthAnchor.constraint(equalToConstant: 72), headImage.heightAnchor.constraint(equalToConstant: 53), - ]) NSLayoutConstraint.activate([ - headLable.centerXAnchor.constraint(equalTo: headImage.centerXAnchor), - headLable.topAnchor.constraint(equalTo: headImage.bottomAnchor, constant: 10), + headLabel.centerXAnchor.constraint(equalTo: headImage.centerXAnchor), + headLabel.topAnchor.constraint(equalTo: headImage.bottomAnchor, constant: 10), ]) NSLayoutConstraint.activate([ @@ -61,7 +59,7 @@ class IntroduceBrandViewController: NEBaseViewController, UITableViewDelegate, return image }() - private lazy var headLable: UILabel = { + private lazy var headLabel: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.text = NSLocalizedString("brand_des", comment: "") diff --git a/app/Mine/Controller/MeViewController.swift b/app/Mine/Controller/MeViewController.swift index dbca3e46..7e103ffc 100644 --- a/app/Mine/Controller/MeViewController.swift +++ b/app/Mine/Controller/MeViewController.swift @@ -8,7 +8,6 @@ import YXLogin import NECoreKit import NIMSDK import NECoreIMKit -import NEQChatUIKit class MeViewController: UIViewController { private let mineData = [ @@ -59,7 +58,7 @@ class MeViewController: UIViewController { header.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), header.topAnchor.constraint( equalTo: self.view.safeAreaLayoutGuide.topAnchor, - constant: 20 + constant: 32 ), header.widthAnchor.constraint(equalToConstant: 60), header.heightAnchor.constraint(equalToConstant: 60), @@ -68,7 +67,7 @@ class MeViewController: UIViewController { // Fallback on earlier versions NSLayoutConstraint.activate([ header.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - header.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), + header.topAnchor.constraint(equalTo: view.topAnchor, constant: 32), header.widthAnchor.constraint(equalToConstant: 60), header.heightAnchor.constraint(equalToConstant: 60), ]) @@ -130,7 +129,7 @@ class MeViewController: UIViewController { } func updateUserInfo() { - let user = userProvider.getUserInfo(userId: IMKitClient.instance.imAccid) + let user = userProvider.getUserInfo(userId: IMKitEngine.instance.imAccid) idLabel.text = "\(NSLocalizedString("account", comment: "")):\(user?.userId ?? "")" nameLabel.text = user?.userInfo?.nickName header.configHeadData(headUrl: user?.userInfo?.avatarUrl, name: user?.showName() ?? "") diff --git a/app/Mine/Controller/MineSettingViewController.swift b/app/Mine/Controller/MineSettingViewController.swift index 6f7b5e2d..6268af24 100644 --- a/app/Mine/Controller/MineSettingViewController.swift +++ b/app/Mine/Controller/MineSettingViewController.swift @@ -89,18 +89,9 @@ class MineSettingViewController: NEBaseViewController, UITableViewDataSource, UI return footer } - @objc func loginOutAction(){ - NIMSDK.shared().loginManager.logout { error in - NIMSDK.shared().qchatManager.logout { chatError in - if error != nil { - self.view.makeToast(error?.localizedDescription) - }else { - print("logout success") - NotificationCenter.default.post(name: Notification.Name("logout"), object: nil) - } - } - } - } + @objc func loginOutAction() { + view.makeToast("demo not support logout") + } // MARK: UITableViewDataSource, UITableViewDelegate diff --git a/app/Mine/Controller/NENodeViewController.swift b/app/Mine/Controller/NENodeViewController.swift new file mode 100644 index 00000000..b053108e --- /dev/null +++ b/app/Mine/Controller/NENodeViewController.swift @@ -0,0 +1,123 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +import UIKit +import NECoreKit +import NETeamUIKit + +class NENodeViewController: NEBaseViewController, UITableViewDataSource, UITableViewDelegate { + private var viewModel = NodeViewModel() + // 记录默认选中的cell + private var selectIndex = 0 + + override func viewDidLoad() { + super.viewDidLoad() + viewModel.getData() + setupUI() + } + + func setupUI() { + title = NSLocalizedString("node_select", comment: "") + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + tableView.register( + NodeSelectCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(NodeSelectCell.self))" + ) + } + + private func showAlert(_ isDomestic: Bool) { + let alertController = UIAlertController( + title: NSLocalizedString("change_node", comment: ""), + message: NSLocalizedString("restart_take_effect", comment: ""), + preferredStyle: .alert + ) + + let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .default) { action in + } + alertController.addAction(cancelAction) + let sureAction = UIAlertAction(title: NSLocalizedString("restart", comment: ""), style: .default) { action in + // 设置节点 + IMKitClient.instance.repo.setNodeValue(isDomestic) + exit(0) + } + alertController.addAction(sureAction) + present(alertController, animated: true, completion: nil) + } + + lazy var tableView: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = UIColor(hexString: "0xF1F1F6") + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 + } + return table + }() + + // MARK: UITableViewDataSource, UITableViewDelegate + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + return model.cellModels.count + } + return 0 + } + + func numberOfSections(in tableView: UITableView) -> Int { + viewModel.sectionData.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(NodeSelectCell.self))", + for: indexPath + ) as! NodeSelectCell + cell.configure(model) + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.row == 0 { + showAlert(true) + } else { + showAlert(false) + } + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + return model.rowHeight + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + if model.cellModels.count > 0 { + return 12.0 + } + } + return 0 + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let header = UIView() + header.backgroundColor = UIColor(hexString: "0xF1F1F6") + return header + } +} diff --git a/app/Mine/Controller/PersonInfoViewController.swift b/app/Mine/Controller/PersonInfoViewController.swift index 3aef86f4..bcbac4e4 100644 --- a/app/Mine/Controller/PersonInfoViewController.swift +++ b/app/Mine/Controller/PersonInfoViewController.swift @@ -1,4 +1,3 @@ - // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. @@ -9,6 +8,7 @@ import NETeamUIKit import NEChatUIKit import NIMSDK +@objcMembers class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, UINavigationControllerDelegate, PersonInfoViewModelDelegate, UITableViewDelegate, UITableViewDataSource { @@ -69,8 +69,8 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, second.setValue(UIColor(hexString: "0x333333"), forKey: "_titleTextColor") let cancel = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), - style: .cancel) { action in - } + style: .cancel) + cancel.setValue(UIColor(hexString: "0x333333"), forKey: "_titleTextColor") alert.addAction(first) @@ -130,7 +130,7 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, // MARK: NIMUserManagerDelegate func onUserInfoChanged(_ user: NIMUser) { - if user.userId == IMKitClient.instance.imAccid { + if user.userId == IMKitEngine.instance.imAccid { viewModel.getData() tableView.reloadData() } @@ -151,7 +151,7 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, weak var weakSelf = self if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { let filePath = NSHomeDirectory().appending("/Documents/") - .appending(IMKitClient.instance.imAccid) + .appending(IMKitEngine.instance.imAccid) let succcess = imageData.write(toFile: filePath, atomically: true) if succcess { NIMSDK.shared().resourceManager @@ -190,7 +190,9 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, ctrl.callBack = { editText in weakSelf?.viewModel.updateNickName(name: editText) { error in if error != nil { - weakSelf?.showToast(NSLocalizedString("setting_nickname_failure", comment: "")) + weakSelf?.showToastInWindow(NSLocalizedString("setting_nickname_failure", comment: "")) + } else { + weakSelf?.navigationController?.popViewController(animated: true) } } } @@ -225,7 +227,9 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, ctrl.callBack = { editText in weakSelf?.viewModel.updateMobile(mobile: editText) { error in if error != nil { - weakSelf?.showToast(NSLocalizedString("change_phone_failure", comment: "")) + weakSelf?.showToastInWindow(NSLocalizedString("change_phone_failure", comment: "")) + } else { + weakSelf?.navigationController?.popViewController(animated: true) } } } @@ -240,7 +244,9 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, ctrl.callBack = { editText in weakSelf?.viewModel.updateEmail(email: editText) { error in if error != nil { - weakSelf?.showToast(NSLocalizedString("change_email_failure", comment: "")) + weakSelf?.showToastInWindow(NSLocalizedString("change_email_failure", comment: "")) + } else { + weakSelf?.navigationController?.popViewController(animated: true) } } } @@ -255,7 +261,9 @@ class PersonInfoViewController: NEBaseViewController, NIMUserManagerDelegate, ctrl.callBack = { editText in weakSelf?.viewModel.updateSign(sign: editText) { error in if error != nil { - weakSelf?.showToast(NSLocalizedString("change_sign_failure", comment: "")) + weakSelf?.showToastInWindow(NSLocalizedString("change_sign_failure", comment: "")) + } else { + weakSelf?.navigationController?.popViewController(animated: true) } } } diff --git a/app/Mine/View/BirthdayDatePickerView.swift b/app/Mine/View/BirthdayDatePickerView.swift index d5b773b5..8e6b376f 100644 --- a/app/Mine/View/BirthdayDatePickerView.swift +++ b/app/Mine/View/BirthdayDatePickerView.swift @@ -27,6 +27,11 @@ public class BirthdayDatePickerView: UIView { // 将日期选择器区域设置为中文,则选择器日期显示为中文 datePicker.locale = Locale(identifier: "zh_CN") datePicker.datePickerMode = .date + datePicker.maximumDate = Date() + if #available(iOS 13.4, *) { + datePicker.preferredDatePickerStyle = .wheels + } + // 注意:action里面的方法名后面需要加个冒号“:” datePicker.addTarget(self, action: #selector(dateChanged), for: .valueChanged) diff --git a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatHeaderView.swift b/app/Mine/View/NEUserHeaderView.swift similarity index 50% rename from NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatHeaderView.swift rename to app/Mine/View/NEUserHeaderView.swift index 2b56daa1..19ce8eb2 100644 --- a/NEQChatUIKit/NEQChatUIKit/Classes/Base/BaseView/QChatHeaderView.swift +++ b/app/Mine/View/NEUserHeaderView.swift @@ -5,24 +5,16 @@ import UIKit -public class QChatHeaderView: UIView { +public class NEUserHeaderView: UIImageView { public lazy var titleLabel: UILabel = { let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = .ne_greyText + label.font = UIFont.systemFont(ofSize: 12) + label.textColor = .white label.translatesAutoresizingMaskIntoConstraints = false return label }() - /* - // Only override draw() if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - override func draw(_ rect: CGRect) { - // Drawing code - } - */ - - override init(frame: CGRect) { + override public init(frame: CGRect) { super.init(frame: frame) setupUI() } @@ -32,15 +24,29 @@ public class QChatHeaderView: UIView { } func setupUI() { + contentMode = .scaleAspectFill + isUserInteractionEnabled = true clipsToBounds = false addSubview(titleLabel) NSLayoutConstraint.activate([ - titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), - titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 33), + titleLabel.centerYAnchor + .constraint(equalTo: centerYAnchor), + titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor), ]) backgroundColor = .clear } + public func configHeadData(headUrl: String?, name: String) { + if let avatar = headUrl, !avatar.isEmpty { + setTitle("") + sd_setImage(with: URL(string: avatar), completed: nil) + } else { + setTitle(name) + sd_setImage(with: nil, completed: nil) + backgroundColor = UIColor.colorWithString(string: name) + } + } + public func setTitle(_ name: String) { titleLabel.text = name .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name diff --git a/app/Mine/View/NodeSelectCell.swift b/app/Mine/View/NodeSelectCell.swift new file mode 100644 index 00000000..cef006f9 --- /dev/null +++ b/app/Mine/View/NodeSelectCell.swift @@ -0,0 +1,67 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +import UIKit +import NETeamUIKit + +class NodeSelectCell: CornerCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func configure(_ cellModel: SettingCellModel) { + cornerType = cellModel.cornerType + stateImg.isHighlighted = cellModel.switchOpen ? true : false + titleLabel.text = cellModel.subTitle + } + + func setupUI() { + contentView.addSubview(titleLabel) + contentView.addSubview(stateImg) + + NSLayoutConstraint.activate([ + stateImg.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + stateImg.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 30), + ]) + + NSLayoutConstraint.activate([ + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + titleLabel.leftAnchor.constraint(equalTo: stateImg.rightAnchor, constant: 10), + ]) + } + + lazy var titleLabel: UILabel = { + let label = UILabel() + label.textColor = UIColor.ne_darkText + label.font = NEConstant.defaultTextFont(14.0) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + lazy var stateImg: UIImageView = { + let img = UIImageView() + img.image = UIImage(named: "unselect") + img.highlightedImage = UIImage(named: "select") + img.translatesAutoresizingMaskIntoConstraints = false + return img + }() +} diff --git a/app/Mine/ViewModel/MineSettingViewModel.swift b/app/Mine/ViewModel/MineSettingViewModel.swift index 1c069e23..0b20346f 100644 --- a/app/Mine/ViewModel/MineSettingViewModel.swift +++ b/app/Mine/ViewModel/MineSettingViewModel.swift @@ -55,10 +55,10 @@ public class MineSettingViewModel: NSObject { receiverModel.type = SettingCellType.SettingSwitchCell.rawValue receiverModel.cornerType = .topLeft.union(.topRight) // receiverModel.switchOpen = CoreKitEngine.instance.repo.getHandSetMode() - receiverModel.switchOpen = IMKitClient.instance.repo.getHandsetMode() + receiverModel.switchOpen = IMKitEngine.instance.repo.getHandsetMode() receiverModel.swichChange = { isOpen in - IMKitClient.instance.repo.setHandsetMode(isOpen) + IMKitEngine.instance.repo.setHandsetMode(isOpen) } // //过滤通知 // let filterNotify = SettingCellModel() @@ -74,10 +74,10 @@ public class MineSettingViewModel: NSObject { // let deleteFriend = SettingCellModel() // deleteFriend.cellName = NSLocalizedString("delete_friend", comment: "") // deleteFriend.type = SettingCellType.SettingSwitchCell.rawValue -// deleteFriend.switchOpen = IMKitClient.instance.repo.getDeleteFriendAlias() +// deleteFriend.switchOpen = IMKitEngine.instance.repo.getDeleteFriendAlias() // // deleteFriend.swichChange = { isOpen in -// IMKitClient.instance.repo.setDeleteFriendAlias(isOpen) +// IMKitEngine.instance.repo.setDeleteFriendAlias(isOpen) // } // 消息已读未读功能 @@ -86,9 +86,9 @@ public class MineSettingViewModel: NSObject { hasRead.type = SettingCellType.SettingSwitchCell.rawValue hasRead.cornerType = .bottomLeft.union(.bottomRight) // hasRead.switchOpen = true - hasRead.switchOpen = IMKitClient.instance.repo.getShowReadStatus() + hasRead.switchOpen = IMKitEngine.instance.repo.getShowReadStatus() hasRead.swichChange = { isOpen in - IMKitClient.instance.repo.setShowReadStatus(isOpen) + IMKitEngine.instance.repo.setShowReadStatus(isOpen) } model.cellModels.append(contentsOf: [receiverModel, hasRead]) return model diff --git a/app/Mine/ViewModel/NodeViewModel.swift b/app/Mine/ViewModel/NodeViewModel.swift new file mode 100644 index 00000000..cd36dfc7 --- /dev/null +++ b/app/Mine/ViewModel/NodeViewModel.swift @@ -0,0 +1,35 @@ + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +import UIKit +import NETeamUIKit + +class NodeViewModel: NSObject { + var sectionData = [SettingSectionModel]() + + public func getData() { + sectionData.append(getSection()) + } + + private func getSection() -> SettingSectionModel { + let model = SettingSectionModel() + // 国内节点配置 + let home = SettingCellModel() + home.subTitle = NSLocalizedString("domestic_node", comment: "") + home.cornerType = .topLeft.union(.topRight) + home.rowHeight = 44.0 + home.switchOpen = IMKitClient.instance.repo.getNodeValue() == true ? true : false + + // 海外节点配置 + let overseas = SettingCellModel() + overseas.subTitle = NSLocalizedString("overseas_node", comment: "") + overseas.cornerType = .bottomLeft.union(.bottomRight) + overseas.switchOpen = IMKitClient.instance.repo.getNodeValue() == true ? false : true + overseas.rowHeight = 44.0 + + model.cellModels.append(contentsOf: [home, overseas]) + return model + } +} diff --git a/app/Mine/ViewModel/PersonInfoViewModel.swift b/app/Mine/ViewModel/PersonInfoViewModel.swift index 30aecd18..d607a482 100644 --- a/app/Mine/ViewModel/PersonInfoViewModel.swift +++ b/app/Mine/ViewModel/PersonInfoViewModel.swift @@ -29,7 +29,7 @@ public class PersonInfoViewModel: NSObject { func getData() { sectionData.removeAll() - userInfo = userProvider.getUserInfo(userId: IMKitClient.instance.imAccid) + userInfo = userProvider.getUserInfo(userId: IMKitEngine.instance.imAccid) sectionData.append(getFirstSection()) sectionData.append(getSecondSection()) } @@ -145,6 +145,7 @@ public class PersonInfoViewModel: NSObject { signItem.cellName = NSLocalizedString("individuality_sign", comment: "") signItem.subTitle = mineInfo.userInfo?.sign signItem.rowHeight = 46.0 + signItem.titleWidth = 64 signItem.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.bottomRight) weak var weakSelf = self signItem.cellClick = { diff --git a/app/app-Bridging-Header.h b/app/app-Bridging-Header.h new file mode 100644 index 00000000..5323061e --- /dev/null +++ b/app/app-Bridging-Header.h @@ -0,0 +1,2 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file.