### Overview The app uses SharedPreferences for local data persistence approach to manage different data scopes. For different platforms (ios, android, desktops) this storage has different naming. All these implementation are covered under one umbrella of flutter library [shared\_preferences](https://pub.dev/packages/shared_preferences).  This document describes the architecture, data flow, categorisation, and naming convention.
### Architecture #### Core Components 1\. **PreferencesStorage** - Low-level wrapper around SharedPreferences 2\. **MultiUserPreferencesStorage** - Helper for multi-user data storage 3\. **SettingsRepository** - Repository layer for accessing settings 4\. **Use Cases** - Business logic layer (GetUserSettingUseCase, SaveUserSettingUseCase) 5\. **BLoCs** - Presentation layer that uses Use Cases #### #### Data Flow ```txt BLoC/Service ↓ (uses) Use Case (GetUserSettingUseCase/SaveUserSettingUseCase) ↓ (gets current userId) UserRepository ↓ (passes userId to) SettingsRepository ↓ (uses) MultiUserPreferencesStorage ↓ (uses) PreferencesStorage (SharedPreferences wrapper) ``` ### ### Data Categories Currently preferences are organised into four categories based on their scope and lifecycle: #### 1\. Multi-User Preferences **Scope**: Per-user data **Lifecycle**: Persists across logout (for user switching support) **Storage Format**: \`{"userId1": data1, "userId2": data2}\` **Access**: Via Use Cases (GetUserSettingUseCase/SaveUserSettingUseCase) #### 2\. App-Level Preferences **Scope**: Application-wide settings **Lifecycle**: Persists across all sessions and users **Storage Format**: Direct key-value pairs **Access**: Direct repository access (no Use Cases needed) #### 3\. Instance-Level Preferences **Scope**: OpenProject server configuration **Lifecycle**: Persists until instance is changed **Storage Format**: Direct key-value pairs **Access**: Via InstanceConfigurationRepository #### 4\. _Legacy Preferences_ _**Scope**: Deprecated keys pending migration_ _**Lifecycle**: Various_ _**Status**: Should not be used in new code_
### Preference Keys Reference #### Multi-User Preferences

Key

Type

Description

Used In

multi_user_bottom_bar_configs

BottomBarConfiguration

Bottom navigation bar customization per user

BottomBarConfigurationRepository

multi_user_timers

Timer

Active time tracking timers per user

TimeEntriesRepository

multi_user_work_package_settings

WorkPackageSettings

Work package display preferences (sorting, filtering, activities display)

SettingsRepository

multi_user_local_notification_settings

LocalNotificationsSettings

Local notification preferences (enabled/disabled, participants, weekdays)

SettingsRepository

multi_user_home_widgets

HomeDashboardWidgets

Home dashboard widget configuration and visibility

SettingsRepository

multi_user_push_enabled

bool

Push notification toggle per user

PreferencesStorage (direct)

multi_user_projects_last_sync

int (timestamp)

Last project sync timestamp for incremental sync

ProjectsSyncPreferences

multi_user_default_page

int

Default launch page index (which tab opens on startup)

SettingsRepository

#### App-Level Preferences

Key

Type

Description

Used In

app_theme

String (ThemeMode)

App theme mode: light, dark, or system

SettingsRepository

app_locale

String

User's selected language code (e.g., "en", "de")

LocaleRepository

app_developer_settings

DeveloperSettings

Developer mode settings and feature toggles

SettingsRepository

app_feature_flags

FeatureFlags

Feature flags configuration (experimental features)

SettingsRepository

#### Instance-Level Preferences

Key

Type

Description

Used In

instance_base_url

String

OpenProject instance base URL

InstanceConfigurationRepository

instance_client_id

String

OAuth client ID for the instance

InstanceConfigurationRepository

instance_instances_map

Map<String, String>

Map of instance URLs to client IDs for multi-instance support

InstanceConfigurationRepository

#### Legacy Preferences (need to be reviewed)

Key

Type

Description

Status

unreadNotificationsIdsPrefKey

List<int>

IDs of unread notifications

Used in background service, needs migration

## ### Naming Convention Follow the naming convention for new keys: \- Multi-user: `multi_user_` \- App-level: `app_` \- Instance-level: `instance_`