Skip to content

feat: Conversation Mode — real-time two-way translation #71

Description

@2sem

Summary

Build a Conversation Mode as a sheet presented from TranslationScreen. This is the app's hero differentiator — a face-to-face translation flow with alternating speaker bubbles.

Entry Point

Add a pill button in the language row between the two LanguagePickerButton components:

[ EN  ▾ ]  [ Conversation ]  [ ⇄ ]  [ KO  ▾ ]

Tapping it presents ConversationView as a .sheet with .presentationDetents([.large]).

ConversationView Layout

Sheet handle
Title: "Conversation"  |  [EN • KO pill]  |  [✕]

ScrollView (auto-scrolls to bottom)
  ConversationBubble — Person A (left-aligned, normal orientation)
  ConversationBubble — Person B (right-aligned, rotated 180°)
  ...

[Empty state: bubble icon + "Tap mic or type to begin"]

──────────────────────────────────
[🎙]  [text field: "Speak or type..."]  [➤]
      [ Person A ]  [ Person B ]   ← speaker toggle
──────────────────────────────────

ConversationBubble Spec

  • Source text: .caption, .secondary — above the translated text
  • Translated text: .body, .primary
  • Language flag badge: 16pt circle in the top corner
  • Person A bubble: accent color at 15% opacity
  • Person B bubble: neutral Color.appInputOutputBackground, rotated 180°: .rotationEffect(.degrees(180))
  • Max width: 75% of screen width
  • Corner radii: 16pt, tail corner reduced to 4pt (UnevenRoundedRectangle, iOS 17+)
  • Timestamp: shown in .caption2, .tertiaryLabel when >60s gap between bubbles

Behaviour

  • Active speaker's language is used for speech recognition
  • On recognition finish → auto-translate → append both source + translated bubbles
  • No manual "Translate" button in conversation mode
  • ScrollViewReader auto-scrolls to the latest bubble (.easeOut(duration: 0.3))
  • Speaker toggle: tappable pill pair with haptic feedback (.impactOccurred(intensity: 0.6))
  • On dismiss with ≥2 bubbles: confirm "Leave conversation?" alert. If history is implemented, offer "Save to History" option.

Also

  • Remove or raise the hardcoded 100-character limit (TranslationViewModel.maxTextLength) — it breaks real conversation use

Files

  • Projects/App/Sources/Screens/TranslationScreen.swift
  • Projects/App/Sources/ViewModels/TranslationViewModel.swift
  • Projects/App/Sources/Screens/SpeechRecognitionScreen.swift

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions