改了中英互译,调通流程
authorliangzhenying <867174124@qq.com>
Tue, 16 Sep 2025 06:09:07 +0000 (14:09 +0800)
committerliangzhenying <867174124@qq.com>
Tue, 16 Sep 2025 06:09:07 +0000 (14:09 +0800)
43 files changed:
ShenYin/ShenYin.xcodeproj/project.pbxproj
ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme [new file with mode: 0644]
ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved [deleted file]
ShenYin/ShenYin/AppLaunch.swift
ShenYin/ShenYin/Assets.xcassets/home/Frame 2247_slices/Contents.json [deleted file]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Info.plist
ShenYin/ShenYin/JoySdkManager.swift
ShenYin/ShenYin/SceneDelegate.swift
ShenYin/ShenYin/ShenYin.entitlements [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/CallingRecordVC.swift
ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift
ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishCell.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/Chinese2EnglishVC.swift [deleted file]
ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordBar.swift
ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift
ShenYin/ShenYin/UI/Home/FieldRecording/RecordBar.swift
ShenYin/ShenYin/UI/Home/RecordDetail/RecordDetailVC.swift
ShenYin/ShenYin/UI/Home/RecordTranslateVC.swift
ShenYin/ShenYin/UI/Home/TextTranslate/TextTranslateVC.swift [moved from ShenYin/ShenYin/UI/Home/textTranslateVC/TextTranslateVC.swift with 100% similarity]
ShenYin/ShenYin/UI/Home/TextTranslate/TranslateCell.swift [moved from ShenYin/ShenYin/UI/Home/textTranslateVC/TranslateCell.swift with 100% similarity]
ShenYin/ShenYin/UI/Scan/QrVC.swift
ShenYin/ShenYin/UI/common/AppManager.swift
ShenYin/ShenYin/UI/common/LogVC.swift
ShenYin/ShenYin/UI/common/PlaceHolderTextView.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/common/pop/LanguagePicker/LanguagePickerView.swift
ShenYin/ShenYin/UI/common/pop/PopTextField.swift
ShenYin/ShenYin/UI/common/pop/RecordTipsView.swift

index 52afbf1..229bec3 100644 (file)
@@ -9,8 +9,6 @@
 /* Begin PBXBuildFile section */
                3F79C6142E6055E500EC38B9 /* JoyGemAI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */; };
                3F79C6152E6055E500EC38B9 /* JoyGemAI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
-               3FF8A4622E72CBBA00271F9E /* DSWaveformImage in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF8A4612E72CBBA00271F9E /* DSWaveformImage */; };
-               3FF8A4642E72CBBA00271F9E /* DSWaveformImageViews in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF8A4632E72CBBA00271F9E /* DSWaveformImageViews */; };
                F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3862D5561144E20721225B96 /* Pods_ShenYin.framework */; };
 /* End PBXBuildFile section */
 
@@ -65,9 +63,7 @@
                        buildActionMask = 2147483647;
                        files = (
                                F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */,
-                               3FF8A4622E72CBBA00271F9E /* DSWaveformImage in Frameworks */,
                                3F79C6142E6055E500EC38B9 /* JoyGemAI.framework in Frameworks */,
-                               3FF8A4642E72CBBA00271F9E /* DSWaveformImageViews in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        mainGroup = 3F887B932E38D8DC00C98658;
                        minimizedProjectReferenceProxies = 1;
                        packageReferences = (
-                               3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */,
                        );
                        preferredProjectObjectVersion = 77;
                        productRefGroup = 3F887B9D2E38D8DC00C98658 /* Products */;
                        buildSettings = {
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
                                ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+                               CODE_SIGN_ENTITLEMENTS = ShenYin/ShenYin.entitlements;
                                CODE_SIGN_STYLE = Automatic;
                                CURRENT_PROJECT_VERSION = 1;
                                DEVELOPMENT_TEAM = M33X987285;
                                );
                                GENERATE_INFOPLIST_FILE = YES;
                                INFOPLIST_FILE = ShenYin/Info.plist;
+                               INFOPLIST_KEY_CFBundleDisplayName = "深音";
                                INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "扫描附近蓝牙设备需要获得权限";
                                INFOPLIST_KEY_NSCameraUsageDescription = "修改用户头像、提交意见反馈需要访问相册使用摄像头";
                                INFOPLIST_KEY_NSMicrophoneUsageDescription = "录音需要使用麦克风";
                        buildSettings = {
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
                                ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+                               CODE_SIGN_ENTITLEMENTS = ShenYin/ShenYin.entitlements;
                                CODE_SIGN_STYLE = Automatic;
                                CURRENT_PROJECT_VERSION = 1;
                                DEVELOPMENT_TEAM = M33X987285;
                                );
                                GENERATE_INFOPLIST_FILE = YES;
                                INFOPLIST_FILE = ShenYin/Info.plist;
+                               INFOPLIST_KEY_CFBundleDisplayName = "深音";
                                INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "扫描附近蓝牙设备需要获得权限";
                                INFOPLIST_KEY_NSCameraUsageDescription = "修改用户头像、提交意见反馈需要访问相册使用摄像头";
                                INFOPLIST_KEY_NSMicrophoneUsageDescription = "录音需要使用麦克风";
                        defaultConfigurationName = Release;
                };
 /* End XCConfigurationList section */
-
-/* Begin XCRemoteSwiftPackageReference section */
-               3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */ = {
-                       isa = XCRemoteSwiftPackageReference;
-                       repositoryURL = "https://github.com/dmrschmidt/DSWaveformImage";
-                       requirement = {
-                               kind = upToNextMajorVersion;
-                               minimumVersion = 14.2.2;
-                       };
-               };
-/* End XCRemoteSwiftPackageReference section */
-
-/* Begin XCSwiftPackageProductDependency section */
-               3FF8A4612E72CBBA00271F9E /* DSWaveformImage */ = {
-                       isa = XCSwiftPackageProductDependency;
-                       package = 3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */;
-                       productName = DSWaveformImage;
-               };
-               3FF8A4632E72CBBA00271F9E /* DSWaveformImageViews */ = {
-                       isa = XCSwiftPackageProductDependency;
-                       package = 3FF8A4602E72CBBA00271F9E /* XCRemoteSwiftPackageReference "DSWaveformImage" */;
-                       productName = DSWaveformImageViews;
-               };
-/* End XCSwiftPackageProductDependency section */
        };
        rootObject = 3F887B942E38D8DC00C98658 /* Project object */;
 }
diff --git a/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme b/ShenYin/ShenYin.xcodeproj/xcshareddata/xcschemes/ShenYin.xcscheme
new file mode 100644 (file)
index 0000000..7b6a0f6
--- /dev/null
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1640"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "3F887B9B2E38D8DC00C98658"
+               BuildableName = "ShenYin.app"
+               BlueprintName = "ShenYin"
+               ReferencedContainer = "container:ShenYin.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3F887B9B2E38D8DC00C98658"
+            BuildableName = "ShenYin.app"
+            BlueprintName = "ShenYin"
+            ReferencedContainer = "container:ShenYin.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3F887B9B2E38D8DC00C98658"
+            BuildableName = "ShenYin.app"
+            BlueprintName = "ShenYin"
+            ReferencedContainer = "container:ShenYin.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ShenYin/ShenYin.xcworkspace/xcshareddata/swiftpm/Package.resolved
deleted file mode 100644 (file)
index 6851bcf..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "originHash" : "eb3e6467aa3b79663b371a20cbe7f1b7c7a6a3c9f98e6945bc9704361b5ae42d",
-  "pins" : [
-    {
-      "identity" : "dswaveformimage",
-      "kind" : "remoteSourceControl",
-      "location" : "https://github.com/dmrschmidt/DSWaveformImage",
-      "state" : {
-        "revision" : "4c56578ee10128ee2b2c04c9c5aa73812de722db",
-        "version" : "14.2.2"
-      }
-    }
-  ],
-  "version" : 3
-}
index d021252..1fa4370 100644 (file)
@@ -27,10 +27,10 @@ class AppLaunch:NSObject{
     static func loadCache(){
         let list = DeviceCache.shared.getDeviceList()
         Logger.debug("缓存设备",list)
-        if list.count > 0 {
-            CacheManager.shared.currentDevice = list.first
-            BleManager.shared.startScanDevice()
-            App.shared.enter()
-        }
+//        if list.count > 0 {
+//            CacheManager.shared.currentDevice = list.first
+//            BleManager.shared.startScanDevice()
+//            App.shared.enter()
+//        }
     }
 }
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/Frame 2247_slices/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/Frame 2247_slices/Contents.json
deleted file mode 100644 (file)
index 73c0059..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Contents.json
new file mode 100644 (file)
index 0000000..7be0bc8
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 2094.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 2094@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 2094@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094.png
new file mode 100644 (file)
index 0000000..e30d1ec
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@2x.png
new file mode 100644 (file)
index 0000000..167b65c
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@3x.png
new file mode 100644 (file)
index 0000000..5880006
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_1.imageset/Group 2094@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..30b8a9e
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 2288.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 2288@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 2288@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288.png
new file mode 100644 (file)
index 0000000..f307fdd
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@2x.png
new file mode 100644 (file)
index 0000000..7f95d5b
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@3x.png
new file mode 100644 (file)
index 0000000..c1c1311
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_2.imageset/Group 2288@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Contents.json
new file mode 100644 (file)
index 0000000..d30d76e
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 2289.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 2289@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 2289@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289.png
new file mode 100644 (file)
index 0000000..22d828f
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@2x.png
new file mode 100644 (file)
index 0000000..05aa77e
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@3x.png
new file mode 100644 (file)
index 0000000..1b71907
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/play_animate_3.imageset/Group 2289@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Contents.json
new file mode 100644 (file)
index 0000000..8b4e60a
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Polygon_2@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Polygon_2@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@2x.png b/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@2x.png
new file mode 100644 (file)
index 0000000..3467ca6
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@3x.png b/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@3x.png
new file mode 100644 (file)
index 0000000..9e427b4
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/home/polygon.imageset/Polygon_2@3x.png differ
index 0850455..e31de9e 100644 (file)
@@ -27,7 +27,5 @@
                <string>bluetooth-central</string>
                <string>audio</string>
        </array>
-       <key>CFBundleDisplayName</key>
-       <string>深音</string>
 </dict>
 </plist>
index ff76bd3..64f2405 100644 (file)
@@ -16,7 +16,7 @@ class JoySdkManager:NSObject{
         //MARK: 初始化SDK
         JoyGemAIManager.shared().initSdk()
         //MARK: 配置日志类型
-        JoyGemAIManager.shared().setLogMode(JoyGemLogMode.close)
+        JoyGemAIManager.shared().setLogMode(JoyGemLogMode.all)
         
         
         let fileManager = FileManager.default
@@ -28,12 +28,12 @@ class JoySdkManager:NSObject{
                 do {
                     // 创建 log 文件夹
                     try fileManager.createDirectory(at: logDirectory, withIntermediateDirectories: true, attributes: nil)
-                    print("log 文件夹已创建: \(logDirectory.path)")
+                    Logger.debug("log 文件夹已创建: \(logDirectory.path)")
                 } catch {
-                    print("创建 log 文件夹时出错: \(error.localizedDescription)")
+                    Logger.debug("创建 log 文件夹时出错: \(error.localizedDescription)")
                 }
             } else {
-                print("log 文件夹已存在: \(logDirectory.path)")
+                Logger.debug("log 文件夹已存在: \(logDirectory.path)")
             }
             
             // 获取当前日期并格式化
@@ -50,15 +50,15 @@ class JoySdkManager:NSObject{
             if !fileManager.fileExists(atPath: filePath.path) {
                 // 创建空文件
                 fileManager.createFile(atPath: filePath.path, contents: nil, attributes: nil)
-                print("日志文件已创建: \(filePath.path)")
+                Logger.debug("日志文件已创建: \(filePath.path)")
             } else {
-                print("日志文件已存在: \(filePath.path)")
+                Logger.debug("日志文件已存在: \(filePath.path)")
             }
             
             //MARK: 配置日志路径
             JoyGemAIManager.shared().setLogPath(filePath.path)
         } else {
-            print("无法找到应用支持目录")
+            Logger.debug("无法找到应用支持目录")
         }
         
         //MARK: 配置缓存路径
index 593c36c..cdba428 100644 (file)
@@ -20,7 +20,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
         
         App.shared.window = window
         window?.rootViewController = BaseTC()
-//        window?.rootViewController = UINavigationController(rootViewController: TextTranlateVC())
+        window?.rootViewController = UINavigationController(rootViewController: RecordTranslateVC())
         AppLaunch.start()
     }
 
diff --git a/ShenYin/ShenYin/ShenYin.entitlements b/ShenYin/ShenYin/ShenYin.entitlements
new file mode 100644 (file)
index 0000000..0c67376
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict/>
+</plist>
index 3a156d8..40e4993 100644 (file)
@@ -6,19 +6,28 @@
 //
 
 import UIKit
-
+import JoyGemAI
+import AVFAudio
 class CallingRecordVC:BaseVC{
     let toolBar = FieldRecordBar()
     let textView = UITextView()
     let rhythView = RhythView()
+    var messageList : [(String,UInt)] = []
+    var recordFilePath : String?
+    
+    
     override func viewDidLoad() {
         super.viewDidLoad()
     }
     override func setupViews() {
         navBar.title = "通话录音"
+        toolBar.delegate = self
+        toolBar.hasRightItem = false
+        
         textView.do { v in
             v.isEditable = false
             v.font = .regular(14)
+            v.text = ""
             v.textColor = .hexString("#121212")
             v.contentInset = UIEdgeInsets(top: 0, left: 18, bottom: 0, right: 18)
         }
@@ -42,7 +51,104 @@ class CallingRecordVC:BaseVC{
             make.bottom.equalTo(toolBar.snp.top)
         }
     }
+    override func setupData() {
+        JoyGemCallManager.shared().delegate = self
+//        JoyGemCallManager.shared().stereoDelegate = self//双声道
+    }
     func scrollToBottom(){
         
+    }
+    ///播放最后一次录音文件
+    @objc func playRecord() {
+        guard let file = recordFilePath else {return;}
+        
+//        do {
+//            // 创建 AVAudioPlayer 实例
+//            audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: file))
+//            audioPlayer?.prepareToPlay() // 准备播放
+//            audioPlayer?.play() // 播放音频
+//        } catch {
+//            debugPrint("播放音频时发生错误: \(error.localizedDescription)")
+//        }
+    }
+}
+
+extension CallingRecordVC:FieldRecordBarDelegate{
+    func fieldRecordBar(_ bar: FieldRecordBar, languageChange language: AiSupportLanguage) {
+        JoyGemCallManager.shared().originalLanguage = language.value
+    }
+    
+    func fieldRecordBar(_ bar: FieldRecordBar, stateChange state: RecordSate) {
+        if state == .start {
+            textView.text = ""
+            messageList.removeAll()
+            JoyGemCallManager.shared().start()
+        }
+        else if state == .stop{
+            JoyGemCallManager.shared().stop()
+            bar.recordBtn.startAnimating {[weak self] in
+                guard let self = self else{return}
+                //                toolBar.recordBtn.stopCli()
+                let v = PopTextField()
+                v.show()
+                v.cancelTap = {
+                    
+                }
+                v.okTap = {
+                    
+                }
+            }
+        }
+    }
+}
+extension CallingRecordVC : JoyGemCallManagerDelegate {
+    
+    func callManagerStopped(_ manager: JoyGemCallManager, reason code: JoyGemRecordStopCode) {
+        if (code == .actively) {
+            YLprogressHUD.showAutoHiden( "用户主动结束")
+        } else {
+            YLprogressHUD.showAutoHiden( "自动结束")
+            ///判断当前蓝牙是否连接从而确定是否因为蓝牙断开造成的录音断开
+        }
+    }
+    
+    func callManagerNotonCall(_ manager: JoyGemCallManager) {
+        YLprogressHUD.showAutoHiden("未处于通话状态")
+    }
+    
+    func callManager(_ manager: JoyGemCallManager, saveFile path: String) {
+        debugPrint("path: \(path)")
+        recordFilePath = path
+    }
+    
+    func callManager(_ manager: JoyGemCallManager, stateChange code: JoyGemStateCode) {
+        debugPrint("code: \(code)")
+    }
+    
+    func callManager(_ manager: JoyGemCallManager, onError code: JoyGemErrorCode) {
+        
+    }
+    
+    func callManager(_ manager: JoyGemCallManager, didUpdateAsr model: JoyGemAsrModel) {
+        debugPrint("text: \(model.text),index: \(model.index)")
+        let msg = messageList.firstIndex (where: { (str,idx) in
+            return idx == model.index;
+        })
+        if (msg == nil) {
+            messageList.append((model.text,model.index))
+        } else {
+            messageList[msg!] = (model.text,model.index)
+        }
+        
+        textView.text = messageList.compactMap({ (str,idx) in
+            return str
+        }).joined(separator: "\n")
+    }
+    
+}
+
+extension CallingRecordVC:JoyGemCallStereoDelegate{
+    func callManager(_ manager: JoyGemCallManager, didUpdateStereoAsr model: JoyGemAsrModel, channel index: UInt) {
+        
     }
 }
index 93d5cf2..1534d1e 100644 (file)
@@ -182,7 +182,7 @@ extension ChatVC : JoyGemChatManagerDelegate {
                     try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
                     try AVAudioSession.sharedInstance().setActive(true)
                 } catch {
-                    print(error)
+                    Logger.debug(error)
                 }
             }
 //            stateLabel.text = "正在录音"
diff --git a/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishCell.swift b/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishCell.swift
new file mode 100644 (file)
index 0000000..69b31f3
--- /dev/null
@@ -0,0 +1,119 @@
+//
+//  Chinese2EnglishCell.swift
+//  ShenYin
+//
+//  Created by liangshi on 2025/9/15.
+//
+
+class Chinese2EnglishCellModel{
+    var send = ""
+    var response = ""
+    
+    init(send: String = "", response: String = "") {
+        self.send = send
+        self.response = response
+    }
+}
+
+
+
+
+class Chinese2EnglishCell:BaseTableViewCell{
+    let bgView = UIView()
+    let line = BrokenLineView()
+    let originalLabel = UILabel()
+    let translationLabel = UILabel()
+    let copyIcon = UIImageView()
+    
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+        
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func setupViews() {
+        contentView.backgroundColor = .rgb(0xF6F6F6)
+        
+        bgView.do { v in
+            v.yc.setCornerRadius(12)
+            v.backgroundColor = .white
+        }
+        originalLabel.do { v in
+            v.font = .regular(14)
+            v.textColor = .hexString("#606D80")
+            v.numberOfLines = 0
+            v.textAlignment = .left
+        }
+        translationLabel.do { v in
+            v.font = .regular(14)
+            v.textColor = .hexString("#121212")
+            v.numberOfLines = 0
+            v.textAlignment = .left
+        }
+        line.do { v in
+            //            v.backgroundColor = .hexString("#93C6EC")
+        }
+        copyIcon.do { v in
+            v.image = UIImage(named: "play_animate_3")
+            v.animationImages = [UIImage(named: "play_animate_1")!,UIImage(named: "play_animate_2")!,UIImage(named: "play_animate_3")!]
+            v.animationDuration = 0.6
+            v.animationRepeatCount = 0
+            v.yc.addTap(target: self, action: #selector(copyAction))
+        }
+        contentView.addSubview(bgView)
+        bgView.addSubviews([originalLabel,translationLabel,line,copyIcon])
+    }
+    
+    override func setupLayout() {
+        bgView.snp.makeConstraints { make in
+            make.top.bottom.equalToSuperview().inset(10)
+            make.width.lessThanOrEqualTo(kScreenWid - 58)
+            make.left.equalToSuperview().inset(18)
+        }
+        
+        originalLabel.snp.makeConstraints { make in
+            make.top.equalToSuperview().inset(14)
+            make.left.equalToSuperview().inset(12)
+            make.width.lessThanOrEqualTo(kScreenWid - 82)
+        }
+        line.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(12)
+            make.height.equalTo(1)
+            make.top.equalTo(originalLabel.snp.bottom).offset(15)
+        }
+        
+        translationLabel.snp.makeConstraints { make in
+            make.top.equalTo(line.snp.bottom).offset(15)
+            make.left.equalToSuperview().inset(12)
+            make.width.lessThanOrEqualTo(kScreenWid - 82)
+            make.bottom.equalToSuperview().inset(47)
+        }
+        copyIcon.snp.makeConstraints { make in
+            make.right.equalToSuperview().inset(12)
+            make.size.equalTo(24)
+            make.bottom.equalToSuperview().inset(10)
+        }
+    }
+    
+    var data:Chinese2EnglishCellModel!{
+        didSet{
+            originalLabel.text = data.send
+            translationLabel.text = data.response
+        }
+    }
+    @objc func copyAction(){
+//        UIPasteboard.general.string = data.send + "\n" + data.response
+//        YLprogressHUD.showAutoHiden("已拷贝")
+        if copyIcon.isAnimating {
+            copyIcon.stopAnimating()
+        }
+        else{
+            copyIcon.startAnimating()
+        }
+    }
+}
+
+
diff --git a/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift b/ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift
new file mode 100644 (file)
index 0000000..14fdfae
--- /dev/null
@@ -0,0 +1,186 @@
+//
+//  Chinese2EnglishVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2025/8/6.
+//
+
+import UIKit
+import JoyGemAI
+import AVFAudio
+class Chinese2EnglishVC:BaseVC{
+    let toolBar = RecordBar()
+    let tableView = UITableView(frame: CGRectZero, style: .plain)
+    var dataList:[(Chinese2EnglishCellModel,UInt)] = []
+    var pcmData = Data()
+    override func viewDidLoad() {
+        super.viewDidLoad()
+    }
+    override func setupViews() {
+        navBar.title = "中英互译"
+        navBar.rightView.setImage(UIImage(named: "help_icon"), for: .normal)
+        toolBar.delegate = self
+        
+        tableView.backgroundColor = .clear
+        tableView.delegate = self
+        tableView.dataSource = self
+        tableView.estimatedRowHeight = 60
+        tableView.separatorStyle = .none
+        tableView.register(Chinese2EnglishCell.self, forCellReuseIdentifier: Chinese2EnglishCell.reuseID)
+        view.addSubview(tableView)
+        view.addSubview(toolBar)
+        
+    }
+    override func setupLayout() {
+        toolBar.snp.makeConstraints { make in
+            make.width.centerX.equalToSuperview()
+            make.height.equalTo(120)
+            make.bottom.equalToSuperview().inset(20)
+        }
+        tableView.snp.makeConstraints { make in
+            make.top.equalToSuperview().inset(80)
+            make.left.right.equalToSuperview()
+            make.bottom.equalTo(toolBar.snp.top)
+        }
+    }
+    override func setupData() {
+        JoyGemSIDeviceManager.shared().delegate = self
+        
+        PcmSound.sharedInstance().delegate = self;
+        PcmSound.sharedInstance().setup(16000, withchannels: 1)
+//        do {
+//            try AVAudioSession.sharedInstance().setActive(true)
+//        } catch {
+//            print(error)
+//        }
+    }
+    override func navRightViewTapped() {
+        let tip = RecordTipsView(type: .chinese2english)
+        tip.show()
+    }
+    func refreshData(){
+        tableView.reloadData()
+        if dataList.count > 0 {
+            tableView.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true)
+        }
+    }
+}
+extension Chinese2EnglishVC:RecordBarDelegate{
+    
+    func recordBar(_ bar: RecordBar, stateChange state: RecordBarSate) {
+        if state == .start {
+            pcmData = Data()
+            dataList.removeAll()
+            refreshData()
+            
+            JoyGemSIDeviceManager.shared().originalLanguage = bar.leftItem.language.value
+            JoyGemSIDeviceManager.shared().targetLanguage = bar.rightItem.language.value
+            JoyGemSIDeviceManager.shared().start()
+//            do {
+//                try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker])
+//                try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
+//            } catch {
+//                print(error)
+//            }
+        }
+        else if state == .stop{
+            JoyGemSIDeviceManager.shared().stop()
+            bar.recordBtn.startAnimating {[weak self] in
+                guard let self = self else{return}
+                //                toolBar.recordBtn.stopCli()
+                let v = PopTextField()
+                v.show()
+                v.cancelTap = {
+                    
+                }
+                v.okTap = {
+                    
+                }
+            }
+        }
+    }
+}
+extension Chinese2EnglishVC:UITableViewDelegate,UITableViewDataSource {
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return dataList.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = Chinese2EnglishCell.cell(withTableView: tableView, indexPath: indexPath)
+        let (vallue,index) = dataList[indexPath.row]
+        cell.data = vallue
+        return cell
+    }
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        
+    }
+}
+
+extension Chinese2EnglishVC:JoyGemSIDeviceManagerDelegate{
+    func siDeviceManagerStopped(_ manager: JoyGemSIDeviceManager, reason code: JoyGemRecordStopCode) {
+        Logger.debug("停止",code.rawValue)
+        if code == .passively {
+            toolBar.recordBtn.isSelected = false
+        }
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, didUpdateRaw model: JoyGemAsrModel) {
+        debugPrint("text: \(model.text),index: \(model.index)")
+        let msg = dataList.firstIndex (where: { (str,idx) in
+            return idx == model.index;
+        })
+        if (msg == nil) {
+            dataList.append((Chinese2EnglishCellModel(send: model.text),model.index))
+        } else {
+            let (item,_) = dataList[msg!]
+            item.send =  model.text
+        }
+//        
+//        ///监听到一句话结束,自动结束当前录音
+//        if (model.definite == true) {
+//            stopEarRecord()
+//        }
+        refreshData()
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, didUpdateTranslate model: JoyGemAsrModel) {
+        let msg = dataList.firstIndex (where: { (str,idx) in
+            return idx == model.index;
+        })
+        if (msg == nil) {
+            dataList.append((Chinese2EnglishCellModel(response: model.text),model.index))
+        } else {
+            let (item,_) = dataList[msg!]
+            item.response =  model.text
+        }
+        refreshData()
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, didUpdateAudioData data: Data) {
+        pcmData.append(data)
+        PcmSound.sharedInstance().feed(data)
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, update mode: JoyGemRecordMode) {
+        
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, saveFile path: String) {
+        debugPrint("path: \(path)")
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, stateChange code: JoyGemStateCode) {
+        debugPrint("code: \(code)")
+    }
+    
+    func siDeviceManager(_ manager: JoyGemSIDeviceManager, onError code: JoyGemErrorCode) {
+        
+    }
+}
+extension Chinese2EnglishVC:PcmSoundDelegate{
+    func remaining(_ frames: UInt) {
+        
+    }
+    
+    
+}
diff --git a/ShenYin/ShenYin/UI/Home/Chinese2EnglishVC.swift b/ShenYin/ShenYin/UI/Home/Chinese2EnglishVC.swift
deleted file mode 100644 (file)
index 063792c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-//  Chinese2EnglishVC.swift
-//  ShenYin
-//
-//  Created by liangshi on 2025/8/6.
-//
-
-import UIKit
-
-class Chinese2EnglishVC:BaseVC{
-    let toolBar = RecordBar()
-    let tableView = UITableView(frame: CGRectZero, style: .plain)
-    var dataList = [1,2,3]
-    override func viewDidLoad() {
-        super.viewDidLoad()
-    }
-    override func setupViews() {
-        navBar.title = "中英互译"
-        navBar.rightView.setImage(UIImage(named: "help_icon"), for: .normal)
-        
-        
-        tableView.backgroundColor = .clear
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.estimatedRowHeight = 60
-        tableView.separatorStyle = .none
-        tableView.register(TranslateCell.self, forCellReuseIdentifier: TranslateCell.reuseID)
-        view.addSubview(tableView)
-        view.addSubview(toolBar)
-        
-    }
-    override func setupLayout() {
-        toolBar.snp.makeConstraints { make in
-            make.width.centerX.equalToSuperview()
-            make.height.equalTo(120)
-            make.bottom.equalToSuperview().inset(20)
-        }
-        tableView.snp.makeConstraints { make in
-            make.top.equalToSuperview().inset(80)
-            make.left.right.equalToSuperview()
-            make.bottom.equalTo(toolBar.snp.top)
-        }
-    }
-    override func navRightViewTapped() {
-        let tip = RecordTipsView(type: .chinese2english)
-        tip.show()
-    }
-    func scrollToBottom(){
-        if dataList.count > 0 {
-            tableView.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true)
-        }
-    }
-}
-extension Chinese2EnglishVC:UITableViewDelegate,UITableViewDataSource {
-    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return dataList.count
-    }
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell = TranslateCell.cell(withTableView: tableView, indexPath: indexPath)
-        //        cell.data = dataList[indexPath.row]
-        return cell
-    }
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        
-    }
-}
index 018aaaf..bc6c279 100644 (file)
@@ -24,6 +24,7 @@ class FieldRecordBar: BaseView {
     let rightItem = RecordBarButton()
     var state:RecordSate = .stop
     var delegate:FieldRecordBarDelegate?
+    var hasRightItem:Bool = true
     
     override func setupViews() {
         backgroundColor = .white
@@ -81,8 +82,12 @@ class FieldRecordBar: BaseView {
         rightItem.state = .start
         rightItem.isHidden = !recordBtn.isSelected
         
+        if hasRightItem == false{
+            rightItem.isHidden = true
+        }
+        
         if recordBtn.isSelected {
-            leftItem.alpha = 0.5
+            leftItem.alpha = 0.3
         }
         else{
             leftItem.alpha = 1
index 75a807a..dc2c896 100644 (file)
@@ -59,7 +59,7 @@ class FieldRecordingVC:BaseVC{
             try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
             try AVAudioSession.sharedInstance().setActive(true)
         } catch {
-            print(error)
+            Logger.debug(error)
         }
     }
     func scrollToBottom(){
index 03c9012..1ffbbde 100644 (file)
@@ -5,11 +5,21 @@
 //  Created by liangshi on 2025/8/27.
 //
 
+enum RecordBarSate:Int{
+    case start
+    case stop
+}
+
+protocol RecordBarDelegate {
+//    func recordBar(_ bar:RecordBar,languageChange language:AiSupportLanguage)
+    func recordBar(_ bar:RecordBar,stateChange state:RecordBarSate)
+}
+
 class RecordBar: BaseView {
-    let recordBtn = UIButton()
+    let recordBtn = LoadingButton()
     let leftItem = RecordBarItem()
     let rightItem = RecordBarItem()
-
+    var delegate:RecordBarDelegate?
     
     override func setupViews() {
         backgroundColor = .white
@@ -20,11 +30,14 @@ class RecordBar: BaseView {
             v.setImage(UIImage(named: "btn_record_stop"), for: .selected)
             v.addTarget(self, action: #selector(recordBtnAction), for: .touchUpInside)
         }
-        leftItem.do {v in
-//            v.backgroundColor = .green
+        leftItem.do { (v) in
+            v.language = AiSupportLanguage.chinse
+            v.yc.addTap(target: self, action: #selector(leftAction))
         }
-        rightItem.do {v in
-//            v.backgroundColor = .yellow
+        rightItem.do { (v) in
+            
+            v.language = AiSupportLanguage.english
+            v.yc.addTap(target: self, action: #selector(rightAction))
         }
     }
     
@@ -34,12 +47,12 @@ class RecordBar: BaseView {
             make.center.equalToSuperview()
         }
         leftItem.snp.makeConstraints { make in
-            make.size.equalTo(56)
+            make.height.equalTo(56)
             make.centerY.equalTo(recordBtn)
             make.right.equalToSuperview().offset(-(kScreenWid/2 + 60))
         }
         rightItem.snp.makeConstraints { make in
-            make.size.equalTo(56)
+            make.height.equalTo(56)
             make.centerY.equalTo(recordBtn)
             make.left.equalToSuperview().offset(kScreenWid/2 + 60)
         }
@@ -47,6 +60,56 @@ class RecordBar: BaseView {
     
     @objc func recordBtnAction(){
         recordBtn.isSelected = !recordBtn.isSelected
+        if recordBtn.isSelected {
+            delegate?.recordBar(self, stateChange: .start)
+        }
+        else{
+            delegate?.recordBar(self, stateChange: .stop)
+        }
+        
+        if recordBtn.isSelected {
+            leftItem.alpha = 0.3
+            rightItem.alpha = 0.3
+        }
+        else{
+            leftItem.alpha = 1
+            rightItem.alpha = 1
+        }
+    }
+    
+    @objc func leftAction(){
+        if recordBtn.isSelected {
+            return
+        }
+        let v = LanguagePickerView(languages: AiSupportLanguage.translate,isLeft: true,left: leftItem.language,right: rightItem.language)
+        v.selectedIndex = v.list.firstIndex(where: {$0.title == leftItem.language.title}) ?? 0
+        v.show()
+        v.didSelected = {[weak self] (index,value) in
+            guard let self = self else { return  }
+            if index == 0 {
+                leftItem.language = value
+            }
+            else{
+                rightItem.language = value
+            }
+        }
+    }
+    @objc func rightAction(){
+        if recordBtn.isSelected {
+            return
+        }
+        let v = LanguagePickerView(languages: AiSupportLanguage.translate,isLeft: false,left: leftItem.language,right: rightItem.language)
+        v.selectedIndex = v.list.firstIndex(where: {$0.title == rightItem.language.title}) ?? 0
+        v.show()
+        v.didSelected = {[weak self] (index,value) in
+            guard let self = self else { return  }
+            if index == 0 {
+                leftItem.language = value
+            }
+            else{
+                rightItem.language = value
+            }
+        }
     }
     
     class RecordBarItem: BaseView {
@@ -54,17 +117,21 @@ class RecordBar: BaseView {
         let titleLabel = UILabel()
         let valueLabel = UILabel()
         
+        var language:AiSupportLanguage = AiSupportLanguage.chinse{
+            didSet{
+                titleLabel.text = language.title
+            }
+        }
+        
         override func setupViews() {
 //            backgroundColor = .red
             addSubviews([titleLabel,valueLabel,icon])
             icon.do { v in
-                v.image = UIImage(named: "")
-                v.backgroundColor = .black
+                v.image = UIImage(named: "polygon")
             }
             titleLabel.do { v in
                 v.textColor = .rgb(0x121212)
                 v.font = .bold(16)
-                v.text = "中文"
             }
             valueLabel.do { v in
                 v.textColor = .rgb(0x666666)
@@ -82,6 +149,7 @@ class RecordBar: BaseView {
             titleLabel.snp.makeConstraints { make in
                 make.right.equalTo(icon.snp.left).offset(-5)
                 make.centerY.equalTo(icon)
+                make.left.equalToSuperview()
             }
             valueLabel.snp.makeConstraints { make in
                 make.right.equalTo(titleLabel)
index 867562c..479fdd5 100644 (file)
@@ -71,7 +71,7 @@ class RecordDetailVC:BaseVC{
             try AVAudioSession.sharedInstance().setCategory(.playback, options: [options])
             try AVAudioSession.sharedInstance().setActive(true)
         } catch {
-            print(error)
+            Logger.debug(error)
         }
     }
     override func navRightViewTapped() {
index 52b2cc2..86e9c8d 100644 (file)
@@ -7,28 +7,52 @@
 
 
 import UIKit
-
+import JoyGemAI
+import AVFoundation
 class RecordTranslateVC:BaseVC{
     let toolBar = RecordBar()
-    let tableView = UITableView(frame: CGRectZero, style: .plain)
-    var dataList = [1,2,3]
+    let textView = PlaceHolderTextView()
+    let translateTextView = PlaceHolderTextView()
+    var messageList : [(String,UInt)] = []
+    var translateList : [(String,UInt)] = []
+    var recordFilePath : String?
+    
     override func viewDidLoad() {
         super.viewDidLoad()
     }
     override func setupViews() {
         navBar.title = "同传听译"
         navBar.rightView.setImage(UIImage(named: "help_icon"), for: .normal)
+        view.addSubviews([toolBar,textView,translateTextView])
         
+        toolBar.delegate = self
         
-        tableView.backgroundColor = .clear
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.estimatedRowHeight = 60
-        tableView.separatorStyle = .none
-        tableView.register(TranslateCell.self, forCellReuseIdentifier: TranslateCell.reuseID)
-        view.addSubview(tableView)
-        view.addSubview(toolBar)
-        
+        textView.do { v in
+            v.isEditable = false
+            v.font = .regular(14)
+            v.text = ""
+            v.textColor = .hexString("#121212")
+            v.contentInset = UIEdgeInsets(top: 0, left: 18, bottom: 0, right: 18)
+        }
+        textView.do { v in
+            v.isEditable = false
+            v.font = .regular(14)
+            v.text = ""
+            v.textColor = .hexString("#121212")
+            v.contentInset = UIEdgeInsets(top: 0, left: 18, bottom: 0, right: 18)
+            v.yc.setBorder(width: 1, color: .black)
+        }
+        translateTextView.do { v in
+            v.isEditable = false
+            v.font = .regular(14)
+            v.text = ""
+            v.textColor = .hexString("#121212")
+//            v.yc.addgradientLayer(colors: [.hexString("#0092E1").withAlphaComponent(0.1),.white], direction: .top2down,rect: CGRect(x: 0, y: 0, width: kScreenWid, height: (kScreenHei - kNavBtm - 120 - 10)/2))
+//            v.contentInset = UIEdgeInsets(top: 0, left: 18, bottom: 0, right: 18)
+            v.yc.setBorder(width: 1, color: .black)
+//            v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: (kScreenHei - kNavBtm - 120 - 10)/2), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 20, height: 20))
+
+        }
     }
     override func setupLayout() {
         toolBar.snp.makeConstraints { make in
@@ -36,33 +60,152 @@ class RecordTranslateVC:BaseVC{
             make.height.equalTo(120)
             make.bottom.equalToSuperview().inset(20)
         }
-        tableView.snp.makeConstraints { make in
+        textView.snp.makeConstraints { make in
             make.top.equalToSuperview().inset(80)
             make.left.right.equalToSuperview()
+            make.height.equalTo((kScreenHei - kNavBtm - 120 - 10)/2)
+        }
+        translateTextView.snp.makeConstraints { make in
+            make.top.equalTo(textView.snp.bottom).offset(10)
+            make.left.right.equalToSuperview()
             make.bottom.equalTo(toolBar.snp.top)
         }
     }
+    override func setupData() {
+        JoyGemSIManager.shared().delegate = self
+        
+        PcmSound.sharedInstance().delegate = self;
+        do {
+            try AVAudioSession.sharedInstance().setCategory(.playback)
+            try AVAudioSession.sharedInstance().setActive(true)
+        } catch {
+            Logger.debug(error)
+        }
+        PcmSound.sharedInstance().setup(16000, withchannels: 1)
+    }
     override func navRightViewTapped() {
         let tip = RecordTipsView(type: .tongchuan)
         tip.show()
     }
     func scrollToBottom(){
-        if dataList.count > 0 {
-            tableView.scrollToRow(at: IndexPath(row: dataList.count - 1, section: 0), at: .none, animated: true)
-        }
+        let range = NSMakeRange(textView.text.count - 1, 1)
+        textView.scrollRangeToVisible(range)
     }
 }
-extension RecordTranslateVC:UITableViewDelegate,UITableViewDataSource {
-    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return dataList.count
+
+extension RecordTranslateVC:RecordBarDelegate{
+
+    func recordBar(_ bar: RecordBar, stateChange state: RecordBarSate) {
+        textView.text = "123"
+        
+//        if state == .start {
+//            messageList.removeAll()
+//            translateList.removeAll()
+//            textView.text = nil
+//            translateTextView.text = nil
+//            
+//            if Thread.isMainThread {
+//                do {
+//                    try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
+//                    try AVAudioSession.sharedInstance().setActive(true)
+//                } catch let error as NSError {
+//                    Logger.debug("An error occurred setting the audio session category: \(error.localizedDescription)")
+//                }
+//            } else {
+//                DispatchQueue.main.sync {
+//                    do {
+//                        try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
+//                        try AVAudioSession.sharedInstance().setActive(true)
+//                    } catch let error as NSError {
+//                        Logger.debug("An error occurred setting the audio session category: \(error.localizedDescription)")
+//                    }
+//                }
+//            }
+//            JoyGemSIManager.shared().originalLanguage = toolBar.leftItem.language.value
+//            JoyGemSIManager.shared().targetLanguage = toolBar.rightItem.language.value
+//            JoyGemSIManager.shared().start()
+//        }
+//        else if state == .stop{
+//            JoyGemSIManager.shared().stop()
+//            bar.recordBtn.startAnimating {[weak self] in
+//                guard let self = self else{return}
+//                //                toolBar.recordBtn.stopCli()
+//                let v = PopTextField()
+//                v.show()
+//                v.cancelTap = {
+//                    
+//                }
+//                v.okTap = {
+//                    
+//                }
+//            }
+//        }
+    }
+}
+
+extension RecordTranslateVC : JoyGemSIManagerDelegate {
+    func siManagerStopped(_ manager: JoyGemSIManager, reason code: JoyGemRecordStopCode) {
+        if (code == .actively) {
+            YLprogressHUD.showAutoHiden("用户主动结束")
+        } else {
+            YLprogressHUD.showAutoHiden("用户被动结束")
+        }
     }
     
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell = TranslateCell.cell(withTableView: tableView, indexPath: indexPath)
-        //        cell.data = dataList[indexPath.row]
-        return cell
+    func siManager(_ manager: JoyGemSIManager, didUpdateRaw model: JoyGemAsrModel) {
+        debugPrint("text: \(model.text),index: \(model.index)")
+        let msg = messageList.firstIndex (where: { (str,idx) in
+            return idx == model.index;
+        })
+        if (msg == nil) {
+            messageList.append((model.text,model.index))
+        } else {
+            messageList[msg!] = (model.text,model.index)
+        }
+        
+        textView.text = messageList.compactMap({ (str,idx) in
+            return str
+        }).joined(separator: "\n")
     }
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    
+    func siManager(_ manager: JoyGemSIManager, didUpdateTranslate model: JoyGemAsrModel) {
+        debugPrint("translate text: \(model.text),index: \(model.index)")
+        let msg = translateList.firstIndex (where: { (str,idx) in
+            return idx == model.index;
+        })
+        if (msg == nil) {
+            translateList.append((model.text,model.index))
+        } else {
+            translateList[msg!] = (model.text,model.index)
+        }
         
+        translateTextView.text = translateList.compactMap({ (str,idx) in
+            return str
+        }).joined(separator: "\n")
+    }
+    
+    
+    func siManager(_ manager: JoyGemSIManager, saveFile path: String) {
+        debugPrint("path: \(path)")
+        recordFilePath = path
+    }
+    
+    func siManager(_ manager: JoyGemSIManager, stateChange code: JoyGemStateCode) {
+        debugPrint("code: \(code)")
+    }
+    
+    func siManager(_ manager: JoyGemSIManager, didUpdateAudioData data: Data) {
+        PcmSound.sharedInstance().feed(data)
+    }
+    
+    func siManager(_ manager: JoyGemSIManager, onError code: JoyGemErrorCode) {
+        
+    }
+}
+
+extension RecordTranslateVC : PcmSoundDelegate {
+    
+    func remaining(_ frames: UInt) {
+        debugPrint("[frame:\(frames)]");
     }
 }
index e68a558..eb10eb3 100644 (file)
@@ -37,7 +37,7 @@ class QrVC: LBXScanViewController {
         
         for result: LBXScanResult in arrayResult {
             if let str = result.strScanned {
-                print(str)
+                Logger.debug(str)
             }
         }
         
index e9b1d90..9edb7d6 100644 (file)
@@ -12,7 +12,7 @@ class App{
     
     func topVC()->UIViewController!{
         guard let vc = window?.rootViewController else{
-            print("页面异常!!!")
+            Logger.debug("页面异常!!!")
             return UIViewController()
         }
         return getTopViewController(from: vc)
index 2a0ce84..68882d2 100644 (file)
@@ -50,10 +50,10 @@ class LogVC: BaseVC {
         let data = self.textView.text.data(using:.utf8)
         do {
             try data?.write(to: url, options:.atomic)
-            print(filePath)
+            Logger.debug(filePath)
             self.saveFile(withFilePath: filePath)
         } catch {
-            print(error)
+            Logger.debug(error)
         }
     }
     
diff --git a/ShenYin/ShenYin/UI/common/PlaceHolderTextView.swift b/ShenYin/ShenYin/UI/common/PlaceHolderTextView.swift
new file mode 100644 (file)
index 0000000..1662bc5
--- /dev/null
@@ -0,0 +1,66 @@
+//
+//  PlaceHolderTextView.swift
+//  ShenYin
+//
+//  Created by liangshi on 2025/9/13.
+//
+
+import UIKit
+
+extension UITextView {
+    @objc dynamic var observedText: String {
+        return text
+    }
+}
+
+class PlaceHolderTextView: UITextView {
+    let label = UILabel()
+    
+    var placeHolde:String = ""{
+        didSet{
+            label.text = placeHolde
+        }
+    }
+
+    
+    override init(frame: CGRect, textContainer: NSTextContainer?) {
+        super.init(frame: frame, textContainer: textContainer)
+        
+        self.addObserver(self, forKeyPath: "observedText", options: [.new,.old], context: nil)
+
+        
+        label.do { v in
+            v.text = "此处将显示原文"
+            v.textAlignment = .center
+            v.textColor = .hexString("#666666")
+            v.font = .regular(16)
+        }
+        addSubview(label)
+        label.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
+        if keyPath == "observedText", let textView = object as? UITextView {
+            if let newText = change?[.newKey] as? String {
+                Logger.debug("Text changed to: \(newText)")
+                if newText.isNotEmpty {
+                    label.isHidden = true
+                }
+                else{
+                    label.isHidden = false
+                }
+            }
+            else{
+                label.isHidden = false
+            }
+        }
+    }
+
+
+}
index 589a3f0..a89d4d5 100644 (file)
@@ -91,6 +91,8 @@ class LanguagePickerView: BasePresentView {
         let language = segView.currentLanguage
         selectedIndex = list.firstIndex(where: {$0 == language})!
         tableView.reloadData()
+        didSelected?(0 ,segView.leftLabel.language)
+        didSelected?(1 ,segView.rightLabel.language)
     }
 }
 extension LanguagePickerView:UITableViewDelegate,UITableViewDataSource {
index 07d9e51..6f7df53 100644 (file)
@@ -18,7 +18,7 @@ class PopTextField: BasePresentView2 {
     var okTap:(()->Void)?
     
     init() {
-        super.init()
+        super.init(backgroundEnabled: false)
     }
     
     required init?(coder: NSCoder) {
index dbdf37d..4ae8ed7 100644 (file)
@@ -106,7 +106,7 @@ class RecordTipsView: BasePresentView {
             m.left.right.equalToSuperview().inset(30)
         }
         actionbtn.snp.makeConstraints { (m) in
-            m.top.equalTo(desLabel2.snp.bottom).offset(40)
+            m.bottom.equalToSuperview().inset(30)
             m.left.right.equalToSuperview().inset(52)
             m.height.equalTo(46)
         }
@@ -169,6 +169,6 @@ class RecordTipsView: BasePresentView {
         hide()
     }
     @objc func btnAction(){
-        
+        hide()
     }
 }