ソースを参照

Add copy button and inline loading overlay to language translator.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 1 ヶ月 前
コミット
712c6764fa

+ 6 - 0
gramora/ViewModels/LanguageTranslatorViewModel.swift

@@ -152,4 +152,10 @@ final class LanguageTranslatorViewModel: ObservableObject {
         guard targetLanguage == sourceLanguage else { return }
         targetLanguage = TranslationLanguage.all.first { $0 != sourceLanguage } ?? .defaultTarget
     }
+
+    func copyTranslatedText() {
+        guard !translatedText.isEmpty else { return }
+        NSPasteboard.general.clearContents()
+        NSPasteboard.general.setString(translatedText, forType: .string)
+    }
 }

+ 35 - 9
gramora/Views/LanguageTranslatorView.swift

@@ -179,18 +179,26 @@ struct LanguageTranslatorView: View {
 
     private var targetPanel: some View {
         VStack(alignment: .leading, spacing: 12) {
-            LanguagePicker(
-                title: "To",
-                selection: $viewModel.targetLanguage,
-                languages: viewModel.targetLanguageOptions
-            )
+            HStack(spacing: 8) {
+                LanguagePicker(
+                    title: "To",
+                    selection: $viewModel.targetLanguage,
+                    languages: viewModel.targetLanguageOptions
+                )
+
+                ToolbarButton(title: "Copy", iconName: "doc.on.doc") {
+                    viewModel.copyTranslatedText()
+                }
+                .disabled(viewModel.translatedText.isEmpty || viewModel.isTranslating)
+                .opacity(viewModel.translatedText.isEmpty || viewModel.isTranslating ? 0.55 : 1)
+
+                Spacer()
+            }
 
-            ZStack(alignment: .topLeading) {
+            ZStack {
                 ThinCaretTextEditor(
                     text: $viewModel.translatedText,
-                    placeholder: viewModel.isTranslating
-                        ? "Translating..."
-                        : "Translation will appear here...",
+                    placeholder: "Translation will appear here...",
                     isEditable: false
                 )
                 .font(.system(size: 14))
@@ -203,6 +211,24 @@ struct LanguageTranslatorView: View {
                     RoundedRectangle(cornerRadius: AppTheme.inputCornerRadius)
                         .stroke(AppTheme.inputBorder, lineWidth: 1)
                 )
+
+                if viewModel.isTranslating {
+                    VStack(spacing: 12) {
+                        ProgressView()
+                            .controlSize(.regular)
+
+                        Text("Loading...")
+                            .font(.system(size: 16, weight: .semibold))
+                            .foregroundStyle(AppTheme.textPrimary)
+
+                        Text("Translating your content")
+                            .font(.system(size: 14))
+                            .foregroundStyle(AppTheme.textSecondary)
+                    }
+                    .frame(maxWidth: .infinity, maxHeight: .infinity)
+                    .background(Color.white.opacity(0.92))
+                    .clipShape(RoundedRectangle(cornerRadius: AppTheme.inputCornerRadius))
+                }
             }
             .frame(maxHeight: .infinity)
         }