Thank you for your interest in contributing to Essentials! This guide details the development setup, architectural conventions, state management patterns, UI component reuse guidelines, service decoupling practices, and pull request workflows.
- Android Studio: Use the latest stable release of Android Studio.
- JDK: Use JDK 17 or higher.
- Clone Repository:
git clone https://github.com/sameerasw/essentials.git
- Target Branch: Ensure all branches and pull requests are based on and targeted to merge back into
develop. - Shizuku / Root: Many privileged features require Shizuku or Root for testing on your device or emulator.
- Complete End-to-End Pipeline: Ensure any new UI control or
FeatureRegistry.ktentry is backed by a complete state flow:- Provide typed getter and setter methods in
SettingsRepository. - Expose reactive state (
mutableStateOf) and mutator functions in the corresponding ViewModel (e.g.MainViewModel,NetworksViewModel). - Connect the UI composable and
FeatureRegistry.onToggledirectly to these ViewModel methods.
- Provide typed getter and setter methods in
- Centralized Preference Keys: Define all preference keys and helper accessors inside
SettingsRepositoryto keep keys uniform and discoverable. - Database & Persistent Properties: Maintain clean migrations for persistent properties to preserve built-in configuration export and import integrity.
- Preserve Shared Services: Keep shared background services (such as
ScreenOffAccessibilityService) lightweight and focused on their core responsibilities. - Use Dedicated Handlers & Controllers:
- Encapsulate feature-specific listeners (e.g. connectivity changes, sensor observers, audio events) in dedicated controllers or handlers under
domain/controller/orservices/handlers/. - Connect external events to shared services through clean adapters or listeners to maintain clear separation of concerns.
- Encapsulate feature-specific listeners (e.g. connectivity changes, sensor observers, audio events) in dedicated controllers or handlers under
- Transparent Execution: When executing shell commands (
ShellUtils.runCommand), system APIs, or Shizuku binders:- Check command return codes and handle permission exceptions gracefully.
- Provide clear UI feedback (such as guidance sheets, permission cards, or status indicators) if privileged execution cannot be completed.
- Pre-Flight Permission Checks: Verify required permissions (
WRITE_SECURE_SETTINGS, Shizuku, Root, Accessibility) before initiating restricted actions.
Leverage the rich design system components in app/src/main/java/com/sameerasw/essentials/ui/core/ to maintain a consistent Material 3 Expressive interface:
- Containers (
ui/core/containers/):RoundedCardContainer: Use for grouping related settings items.RoundedCardLazyContainer: Use for scrolling list containers.
- Cards & Settings Items (
ui/core/cards/):IconToggleItem: Use for standard toggle rows with an icon, title, description, and switch. Always supplyindexandcountfor seamless shape morphing.ConfigPickerItem: Use for settings rows opening picker dialogs or bottom sheets.FeatureCard: Use for highlighted feature banners using pastel background palettes (ColorUtil.getPastelColorFor) and vibrant icons (ColorUtil.getVibrantColorFor).PermissionCard: Use for consistent permission status displays and action triggers.
- Pickers (
ui/core/pickers/):SegmentedPicker,MultiSegmentedPicker: Use for connected button groups with built-in tactile feedback.
- Bottom Sheets (
ui/core/sheets/):EssentialsBottomSheet,PermissionsBottomSheet,FeatureHelpBottomSheet: Use for modal sheets and feature guidance.
Tip
Always check ui/core/ before creating custom cards, list items, or containers to ensure visual harmony and maintainability.
- Top-Level Package Imports: Place all class and symbol imports at the top of the file and reference items by their simple names.
- Structured Grouping: Group related settings into
RoundedCardContainerblocks to maintain visual hierarchy. - Material 3 Expressive Theming:
- Use
surfaceContainerfor outer card containers andsurfaceContainerHighfor modal bottom sheets. - Ensure compatibility with Dynamic Color and Pitch Black (pure
#000000AMOLED) token palettes.
- Use
- Supportive Disabled States: When a feature is inactive or missing requirements, use
enabled = falsepaired withonDisabledClickto present an explanatory guidance sheet.
- String Resources: Place all user-visible text in
app/src/main/res/values/strings.xmland access them viastringResource(R.string...)orcontext.getString(R.string...). Check existing entries first to avoid duplicates. - Drawable Resources: Use rounded drawable resources (
R.drawable.rounded_*) across UI elements and Quick Settings tiles.
- Interactive UI Feedback: Integrate appropriate haptic responses on buttons, switches, sliders, segment pickers, and tiles using
HapticUtil(performUIHaptic,performVirtualKeyHaptic,performHeavyHaptic,performLightHaptic). - Background & Tile Actions: Use
HapticUtil.performHapticForService(context)inside background services and QS tile interactions. - Feature Haptic Preferences: Respect user-configured haptic profiles when available.
- Follow the step-by-step developer guide in ADD_QS_TILE.md when adding new tiles.
- Declare the service in
AndroidManifest.xml, register inQsTileRegistry.kt, support headless execution inQsTileActionRouter.kt, list inQuickSettingsTilesSettingsUI.kt, and test on the Favorite QS Tiles Glance Widget.
- Register configurable settings in
FeatureRegistry.ktusingSearchSetting(...)entries. - Attach
Modifier.highlight(highlightSetting == "key")to composables so universal search can smoothly navigate to and highlight target items.
- Write clean, concise, and idiomatic Kotlin.
- Use clear, technical comments where complex architecture, system settings, or low-level hardware interactions benefit from explanation.
| Area | Recommended Pattern | Context |
|---|---|---|
| ViewModel State | Expose reactive states via SettingsRepository and ViewModel methods |
Ensures clean compilation, predictable state flow, and working search toggles. |
| Background Logic | Encapsulate features in modular handlers under domain/controller/ |
Keeps shared services (e.g. accessibility service) clean and isolated. |
| Import Hygiene | Place all package imports at the top of the file | Keeps code readable and conforms to project styling conventions. |
| Preferences | Store and access keys through constants in SettingsRepository |
Prevents typos and centralizes data contracts. |
| Privilege Feedback | Validate permissions and provide clear UI feedback on failures | Keeps users informed when elevated permissions are needed. |
| UI Components | Use RoundedCardContainer, IconToggleItem, and ui/core/ composables |
Preserves design consistency and built-in shape morphing across all screens. |
- Branching: Create a feature or fix branch from
develop(e.g.feature/my-featureorfix/issue-description). - Target: Point all pull requests to the
developbranch. - Focused Scope: Keep changes cohesive and centered around a single feature or bug fix.
- Local Verification: Verify the build compiles smoothly (
./gradlew assembleDebug) and test functionality on a physical device or emulator. - PR Description: Include a clear summary of changes, rationale, and screenshots/recordings for any UI updates.