Skip to content

arthursz/JumpChatGPT

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JumpChatGPT

An Android ChatGPT client with text and voice chat capabilities, built with Jetpack Compose.

Setup

1. Clone the repository

git clone https://github.com/your-username/JumpChatGPT.git
cd JumpChatGPT

2. Configure the OpenAI API key

The app requires an OpenAI API key to use chat, online transcription, and TTS features.

Add your key to the local.properties file in the project root (this file is git-ignored and will never be committed):

# local.properties
OPENAI_API_KEY=sk-proj-your-key-here

Note: If the key is missing or empty, the app will show an error message at runtime instead of crashing. Offline features (VOSK transcription, audio import) will still work without a key.

3. Build and run

Open the project in Android Studio and run on a device or emulator (API 26+).

Requirements

  • Android Studio Ladybug or newer
  • JDK 17
  • Android SDK 36 (compileSdk)
  • Min SDK 26 (Android 8.0)

Features

  • Text chat with streaming responses via OpenAI Chat Completions API (gpt-4o-mini)
  • Voice chat with real-time recording, transcription, and spoken AI responses
  • Online transcription using OpenAI Whisper API
  • Offline transcription using VOSK on-device model (downloaded automatically on first use, ~40 MB)
  • Audio file import — transcribe MP3, WAV, M4A, AAC, OGG, FLAC files
  • Conversation history with search, stored locally via Room
  • Offline support — graceful degradation with connectivity feedback

Tech Stack

  • Kotlin, Jetpack Compose, Material 3
  • Hilt (DI), Room (persistence), OkHttp (networking)
  • OpenAI APIs (Chat Completions, Whisper, TTS)
  • VOSK (on-device speech recognition)
  • Android TextToSpeech (local TTS fallback)

Architecture

The app follows a layered architecture with clear separation between UI, domain, and data. Dependencies flow inward: UI and data depend on the domain layer, which stays framework-agnostic.

Layers

Layer Role
UI Jetpack Compose screens, ViewModels, navigation (AppRoute), and reusable components. ViewModels depend only on use cases (and infra such as NetworkMonitor, StringProvider), never on repositories or data types directly.
Domain Models (Conversation, Message, ChatToken, etc.), repository interfaces, and use cases (one per business action). Use cases orchestrate repositories and other use cases; they contain no Android or network/DB specifics.
Data Implementations of domain repository interfaces: Room (conversations, messages), OpenAiRepository (chat, Whisper, TTS). Entity-to-domain mapping lives in EntityMappers.kt.

Typical flow: ScreenViewModel (exposes StateFlow) → Use caseRepository(ies). Reactive data is exposed as Flow from repositories and collected in ViewModels.

Patterns

  • MVVM — ViewModels hold UI state in StateFlow; Compose screens observe state and call ViewModel methods (e.g. sendMessage(), retryFromError()).
  • Repository — Each data source has an interface in domain/repository/ and an implementation in data/. One implementation can satisfy multiple interfaces (e.g. OpenAiRepository implements ChatCompletionRepository, TranscriptionRepository, SpeechSynthesisRepository).
  • Use cases — Each significant action has an interface and an implementation that coordinates repositories and other use cases. Injected via Hilt; ViewModels depend on these interfaces only.
  • DI (Dagger Hilt) — Modules: AppModule (DB, HTTP, repositories, dispatchers), UseCaseModule (use case bindings), InfraModule (network, transcription). Qualifiers: @IoDispatcher, @MainDispatcher. ViewModels use @HiltViewModel and @Inject constructor.

Project Structure

app/src/main/java/com/arthurzettler/jump_chatgpt/
├── data/
│   ├── local/                  # Room: AppDatabase, Entities, DAOs
│   ├── OpenAiRepository.kt     # OpenAI API (chat, Whisper, TTS) — implements 3 repo interfaces
│   ├── ConversationRepositoryImpl.kt
│   ├── MessageRepositoryImpl.kt
│   └── EntityMappers.kt        # Entity → domain model mapping
├── di/                         # Hilt: AppModule, InfraModule, UseCaseModule, Qualifiers
├── domain/
│   ├── model/                  # Conversation, Message, ChatToken, enums (MessageRole, MessageSource)
│   ├── repository/             # ChatCompletionRepository, TranscriptionRepository, SpeechSynthesisRepository,
│   │                           # ConversationRepository, MessageRepository
│   └── usecase/                # SendTextMessage, StreamAiResponse, ProcessVoiceTurn, TranscribeAudioPcm,
│                               # SpeakText (TTS), RetryFromError, CreateConversation, MessageQuery, etc.
├── network/                    # NetworkMonitor (connectivity state)
├── transcription/             # OnDeviceTranscriptionManager (VOSK)
├── ui/                         # ChatApp, ChatScreen, VoiceChatScreen, HistoryScreen, ViewModels, AppComponents, Theme
├── util/                       # StringProvider, MarkdownUtils, AudioUriToFileHelper
├── MainActivity.kt
├── ChatGPTApplication.kt
└── Theme.kt

app/src/test/.../jump_chatgpt/       # Unit tests (JVM)
├── data/                       # OpenAiRepositoryTest
├── domain/usecase/             # Use case tests (StreamAiResponse, SpeakText, TranscribeAudioPcm, etc.)
├── network/                    # NetworkMonitorImplTest
├── ui/                         # ChatViewModelTest, HistoryViewModelTest, VoiceViewModelTest
├── util/                       # MainCoroutineRule, *UtilsTest, *HelperTest
└── ...

app/src/androidTest/.../jump_chatgpt/   # Instrumented tests (device/emulator)
├── ui/ChatScreenUiTest.kt      # Compose UI tests (navigation, drawer, send)
└── HiltTestRunner.kt           # Hilt test Application runner

License

This project is part of the Jump challenge.

About

Jump challenge

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages