# mateusrodcosta/savelocally architecture

> Architecture diagram of the GitHub repository mateusrodcosta/savelocally, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-18). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mateusrodcosta/savelocally
- Repository: https://github.com/mateusrodcosta/savelocally

## Overview

Save Locally is an Android app for saving shared files or text to local storage. The main flow receives shared content, gathers details or selection when needed, lets the user choose a destination, and dispatches saving through a foreground service; the native file picker and a configured default location support destination selection. The app also provides settings, about, and media-preview UI. Source excerpts establish several app-to-feature and service-to-use-case links; internals of unsampled use cases and some feature wiring are not verified.

Main entry points: [`app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt`](https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt) (Main activity), [`features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt`](https://github.com/mateusrodcosta/savelocally/blob/dev/features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt) (Settings), [`app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt`](https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt) (Share handling), [`features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens`](https://github.com/mateusrodcosta/savelocally/tree/dev/features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens) (File details and selection)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_entry["App entry and sharing"]
  node_main_activity["Main activity<br/>[MainActivity.kt]"]
  node_details_activity["Share handling<br/>[DetailsActivity.kt]"]
  node_navigation["Navigation routes<br/>[Routes.kt]"]
  node_save_service["Save service"]
end

subgraph group_features["User-facing features"]
  node_main_screen["Main screen<br/>[MainScreen.kt]"]
  node_details_views["File details and selection"]
  node_details_vm["Details view model"]
  node_settings["Settings<br/>[SettingsScreen.kt]"]
  node_settings_vm["Settings view model"]
  node_about["About screen<br/>[AboutScreen.kt]"]
end

subgraph group_domain["Save domain"]
  node_save_usecases["Save and target use cases"]
  node_metadata_usecase["File metadata use case"]
  node_uri_data["File metadata model<br/>[UriData.kt]"]
  node_file_repo["File repository contract<br/>[FileRepository.kt]"]
  node_preferences_contract["Preferences contract"]
  node_storage_error["Insufficient storage error"]
end

subgraph group_data["Persistence and files"]
  node_file_storage["File operations"]
  node_preferences_storage[("Saved preferences")]
end

subgraph group_ui["Shared UI"]
  node_thumbnails["Thumbnail fetching"]
  node_thumbnail_model["Thumbnail model<br/>[MediaThumbnail.kt]"]
  node_section_header["Section header<br/>[SectionHeader.kt]"]
  node_theme_colors["Theme colors<br/>[Color.kt]"]
  node_app_constants["App constants<br/>[AppConstants.kt]"]
end

node_user(("Android user"))
node_share(("Android share menu"))

node_user -->|"shares content"| node_share
node_share -->|"opens share flow"| node_details_activity
node_user -.->|"opens app"| node_main_activity
node_main_activity -->|"shows"| node_main_screen
node_main_activity -->|"routes to"| node_settings
node_main_activity -->|"routes to"| node_about
node_main_activity -->|"uses routes"| node_navigation
node_details_activity -->|"shows"| node_details_views
node_details_activity -->|"reads state"| node_details_vm
node_details_activity -->|"dispatches saves"| node_save_service
node_save_service -->|"invokes saving"| node_save_usecases
node_details_views -->|"observes state"| node_details_vm
node_settings -->|"uses state"| node_settings_vm
node_settings -->|"reads preferences"| node_preferences_contract
node_settings -->|"renders"| node_section_header
node_file_storage -->|"implements"| node_file_repo
node_preferences_storage -->|"implements"| node_preferences_contract
node_preferences_storage -.->|"uses preferences helper"| node_file_storage
node_file_storage -->|"produces metadata"| node_uri_data
node_details_vm -.->|"uses metadata"| node_metadata_usecase
node_thumbnails -->|"creates thumbnails"| node_thumbnail_model
node_details_views -.->|"previews media"| node_thumbnails
node_about -->|"uses colors"| node_theme_colors
node_settings -->|"uses colors"| node_theme_colors
node_details_views -->|"displays file data"| node_uri_data
node_save_service -->|"handles storage failure"| node_storage_error

click node_main_activity "https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt"
click node_details_activity "https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt"
click node_navigation "https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/navigation/Routes.kt"
click node_save_service "https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/service/SaveLocallyService.kt"
click node_main_screen "https://github.com/mateusrodcosta/savelocally/blob/dev/features/main/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/main/MainScreen.kt"
click node_details_views "https://github.com/mateusrodcosta/savelocally/tree/dev/features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens"
click node_details_vm "https://github.com/mateusrodcosta/savelocally/blob/dev/features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens/DetailsViewModel.kt"
click node_settings "https://github.com/mateusrodcosta/savelocally/blob/dev/features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt"
click node_settings_vm "https://github.com/mateusrodcosta/savelocally/blob/dev/features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsViewModel.kt"
click node_about "https://github.com/mateusrodcosta/savelocally/blob/dev/features/about/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/about/AboutScreen.kt"
click node_save_usecases "https://github.com/mateusrodcosta/savelocally/tree/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/usecases"
click node_metadata_usecase "https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/usecases/GetFileMetadataUseCase.kt"
click node_uri_data "https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/entity/UriData.kt"
click node_file_repo "https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/repository/FileRepository.kt"
click node_preferences_contract "https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/repository/PreferencesRepository.kt"
click node_file_storage "https://github.com/mateusrodcosta/savelocally/blob/dev/data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/FileRepositoryImpl.kt"
click node_preferences_storage "https://github.com/mateusrodcosta/savelocally/blob/dev/data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/PreferencesRepositoryImpl.kt"
click node_thumbnails "https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/media/ThumbnailFetcher.kt"
click node_thumbnail_model "https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/model/MediaThumbnail.kt"
click node_section_header "https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/components/SectionHeader.kt"
click node_theme_colors "https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/theme/Color.kt"
click node_app_constants "https://github.com/mateusrodcosta/savelocally/blob/dev/core/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/AppConstants.kt"
click node_storage_error "https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/exception/InsufficientStorageException.kt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main_activity,node_details_activity,node_navigation,node_save_service,node_user toneBlue
class node_main_screen,node_details_views,node_details_vm,node_settings,node_settings_vm,node_about toneAmber
class node_save_usecases,node_metadata_usecase,node_uri_data,node_file_repo,node_preferences_contract,node_storage_error toneMint
class node_file_storage,node_preferences_storage toneRose
class node_thumbnails,node_thumbnail_model,node_section_header,node_theme_colors,node_app_constants,node_share toneIndigo
```

## Components

### App entry and sharing

- [Main activity](https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt): `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt`
- [Share handling](https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt): `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt`
- [Navigation routes](https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/navigation/Routes.kt): `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/navigation/Routes.kt`
- [Save service](https://github.com/mateusrodcosta/savelocally/blob/dev/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/service/SaveLocallyService.kt): `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/service/SaveLocallyService.kt`

### User-facing features

- [Main screen](https://github.com/mateusrodcosta/savelocally/blob/dev/features/main/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/main/MainScreen.kt): `features/main/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/main/MainScreen.kt`
- [File details and selection](https://github.com/mateusrodcosta/savelocally/tree/dev/features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens): `features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens`
- [Details view model](https://github.com/mateusrodcosta/savelocally/blob/dev/features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens/DetailsViewModel.kt): `features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens/DetailsViewModel.kt`
- [Settings](https://github.com/mateusrodcosta/savelocally/blob/dev/features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt): `features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt`
- [Settings view model](https://github.com/mateusrodcosta/savelocally/blob/dev/features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsViewModel.kt): `features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsViewModel.kt`
- [About screen](https://github.com/mateusrodcosta/savelocally/blob/dev/features/about/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/about/AboutScreen.kt): `features/about/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/about/AboutScreen.kt`

### Save domain

- [Save and target use cases](https://github.com/mateusrodcosta/savelocally/tree/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/usecases): `domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/usecases`
- [File metadata use case](https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/usecases/GetFileMetadataUseCase.kt): `domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/usecases/GetFileMetadataUseCase.kt`
- [File metadata model](https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/entity/UriData.kt): `domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/entity/UriData.kt`
- [File repository contract](https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/repository/FileRepository.kt): `domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/repository/FileRepository.kt`
- [Preferences contract](https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/repository/PreferencesRepository.kt): `domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/repository/PreferencesRepository.kt`
- [Insufficient storage error](https://github.com/mateusrodcosta/savelocally/blob/dev/domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/exception/InsufficientStorageException.kt): `domain/src/main/kotlin/com/mateusrodcosta/apps/share2storage/domain/exception/InsufficientStorageException.kt`

### Persistence and files

- [File operations](https://github.com/mateusrodcosta/savelocally/blob/dev/data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/FileRepositoryImpl.kt): `data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/FileRepositoryImpl.kt`
- [Saved preferences](https://github.com/mateusrodcosta/savelocally/blob/dev/data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/PreferencesRepositoryImpl.kt): `data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/PreferencesRepositoryImpl.kt`

### Shared UI

- [Thumbnail fetching](https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/media/ThumbnailFetcher.kt): `core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/media/ThumbnailFetcher.kt`
- [Thumbnail model](https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/model/MediaThumbnail.kt): `core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/model/MediaThumbnail.kt`
- [Section header](https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/components/SectionHeader.kt): `core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/components/SectionHeader.kt`
- [Theme colors](https://github.com/mateusrodcosta/savelocally/blob/dev/core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/theme/Color.kt): `core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/theme/Color.kt`
- [App constants](https://github.com/mateusrodcosta/savelocally/blob/dev/core/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/AppConstants.kt): `core/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/AppConstants.kt`

### Other components

- **Android user**
- **Android share menu**

## Connections

- Android user → Android share menu: shares content
- Android share menu → Share handling: opens share flow
- Android user → Main activity: opens app
- Main activity → Main screen: shows (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt`)
- Main activity → Settings: routes to (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt`)
- Main activity → About screen: routes to (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt`)
- Main activity → Navigation routes: uses routes (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt`)
- Share handling → File details and selection: shows (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt`)
- Share handling → Details view model: reads state (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt`)
- Share handling → Save service: dispatches saves (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt`)
- Save service → Save and target use cases: invokes saving (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/service/SaveLocallyService.kt`)
- File details and selection → Details view model: observes state (evidence: `features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens/MultiDetailsScreen.kt`)
- Settings → Settings view model: uses state (evidence: `features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt`)
- Settings → Preferences contract: reads preferences (evidence: `features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt`)
- Settings → Section header: renders (evidence: `features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt`)
- File operations → File repository contract: implements (evidence: `data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/FileRepositoryImpl.kt`)
- Saved preferences → Preferences contract: implements (evidence: `data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/PreferencesRepositoryImpl.kt`)
- Saved preferences → File operations: uses preferences helper
- File operations → File metadata model: produces metadata (evidence: `data/src/main/kotlin/com/mateusrodcosta/apps/share2storage/data/repository/FileRepositoryImpl.kt`)
- Details view model → File metadata use case: uses metadata (evidence: `features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens/DetailsViewModel.kt`)
- Thumbnail fetching → Thumbnail model: creates thumbnails (evidence: `core/ui/src/main/kotlin/com/mateusrodcosta/apps/share2storage/core/ui/media/ThumbnailFetcher.kt`)
- File details and selection → Thumbnail fetching: previews media
- About screen → Theme colors: uses colors (evidence: `features/about/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/about/AboutScreen.kt`)
- Settings → Theme colors: uses colors (evidence: `features/settings/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/settings/SettingsScreen.kt`)
- File details and selection → File metadata model: displays file data (evidence: `features/details/src/main/kotlin/com/mateusrodcosta/apps/share2storage/features/details/screens/MultiDetailsScreen.kt`)
- Save service → Insufficient storage error: handles storage failure (evidence: `app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/service/SaveLocallyService.kt`)
