Compare commits

...

24 Commits

Author SHA1 Message Date
Ricki Hirner
281837b4c2 Refactor DI modules and qualifiers
- Move `ColorSchemeScopes` to `ColorSchemeQualifiers`
- Rename `CustomCertManagerModule` to `Cert4AndroidModule`
- Move `CoroutineScopes` to `CoroutineQualifiers`
- Add `ApplicationScope` qualifier to `CoroutineQualifiers`
- Remove redundant DI module declarations
- Add new `CoreSettingsProvidersModule`
- Add new `StartupPluginsModule`
- Add new `UncaughtExceptionHandlerModule`
- Add new `AuthorizationServiceModule`
- Add new `AppLicenseInfoProviderModule`
- Add new `IntroPageFactoryModule`
- Add new `LoginTypesProviderModule`
- Add new `AccountsDrawerHandlerModule`
2026-02-06 15:02:48 +01:00
Ricki Hirner
a30dc63714 Update AndroidManifest to set install location to internal only (again) 2026-02-06 14:36:19 +01:00
Ricki Hirner
93431ee6d5 Remove build.gradle.kts and update settings.gradle.kts
- Remove `build.gradle.kts` file
- Update `settings.gradle.kts` to use `gradlePluginPortal` for plugins
- Set `repositoriesMode` to `PREFER_SETTINGS`
- Add comments for clarity in `settings.gradle.kts`
2026-02-06 14:30:28 +01:00
Ricki Hirner
31c4eb6380 Update package references and permissions
- Update references from `com.davx5.ose.App` to `at.bitfire.davdroid.CoreApp`
- Enable archive naming in `app-ose/build.gradle.kts`
- Remove redundant permission declarations in `core/src/main/AndroidManifest.xml`
2026-02-06 14:14:23 +01:00
Ricki Hirner
6b6c340844 Refactor App Initialization
- Introduce `CoreApp` for common initialization logic
- Refactor `App` to extend `CoreApp` and handle WorkManager configuration
2026-02-06 14:04:11 +01:00
Ricki Hirner
e1a58ef576 Don't run app-ose tests yet because there are none 2026-02-06 11:18:49 +01:00
Ricki Hirner
ec00cc6a3f Move WorkManagerInitializer from core to app-ose AndroidManifest 2026-02-06 11:11:48 +01:00
Ricki Hirner
2ce9b83356 Fix core instrumentation tests 2026-02-06 10:57:01 +01:00
Ricki Hirner
47b4ecd705 Add OpenID AppAuth library 2026-02-05 20:06:37 +01:00
Ricki Hirner
bced7e5ee5 Update test configuration
- Add managed device for testing
- Set device to "Pixel 3" with API level 34
- Use AOSP system image source
2026-02-05 20:00:17 +01:00
Ricki Hirner
360c2249cf Update test workflows 2026-02-05 19:55:42 +01:00
Ricki Hirner
53791871c6 Split core and app-ose 2026-02-05 18:16:35 +01:00
Ricki Hirner
9bddf4e8d4 Rename "app" subproject to core 2026-02-05 17:30:18 +01:00
Ricki Hirner
eab054d1c3 Move OSE code to separate package (#1974)
- Move DebugInfoCrashHandler.kt to com.davx5.ose
- Move StandardLoginTypePage.kt to com.davx5.ose.ui.setup
- Move StandardLoginTypesProvider.kt to com.davx5.ose.ui.setup
- Move CustomCertManagerModule.kt to com.davx5.ose.di
- Move OseIntroPageFactory.kt to com.davx5.ose.ui.intro
- Move OseColorSchemesModule.kt to com.davx5.ose.di
- Move OseFlavorModule.kt to com.davx5.ose.di
- Move OpenSourceLicenseInfoProvider.kt to com.davx5.ose.ui.about
- Move OseTheme.kt to com.davx5.ose.ui
2026-02-05 17:21:57 +01:00
Ricki Hirner
5e84648fb4 Replace BuildConfig.allowCustomCerts by DI (#1971)
* Update IntroScreen colors

- Replace M3ColorScheme with MaterialTheme.colorScheme
- Update background and icon colors to use MaterialTheme

* Update color scheme references

- Replace `M3ColorScheme.primaryLight` with `MaterialTheme.colorScheme.primary` in `WelcomePage.kt` and `AccountsDrawerHandler.kt`.

* Update AppTheme to accept custom color schemes

- Add `lightColorScheme` and `darkColorScheme` parameters
- Replace hardcoded color schemes with the new parameters

* Add color scheme dependency injection

- Add `LightColorScheme` and `DarkColorScheme` qualifiers
- Create `OseColorSchemes` module for providing color schemes
- Update `AppTheme` to use injected color schemes

* Update glance material dependency to material3

- Update `androidx.glance.material` to `androidx.glance.material3`
- Adjust imports and usage in `IconSyncButtonWidget.kt` and `LabeledSyncButtonWidget.kt` to use `GlanceTheme` and `ColorProviders` for color schemes
- Replace deprecated `ColorProvider` with `GlanceTheme.colors` for primary and onPrimary colors

* Refactor widget receivers and widgets to use dependency injection more properly

- Update `LabeledSyncButtonWidgetReceiver` and `IconSyncButtonWidgetReceiver` to use Hilt for dependency injection.
- Inject `SyncWidgetModel`, `LightColorScheme`, and `DarkColorScheme` into both widget receivers.
- Remove the use of `EntryPoint` and `EntryPointAccessors` from `LabeledSyncButtonWidget` and `IconSyncButtonWidget`.
- Pass injected dependencies directly to the widget constructors.

* Rename ThemeColors to OseTheme

- Update imports and references to use OseTheme
- Rename object M3ColorScheme to OseTheme

* Move AppTheme to ui.composable package because it's a reusable Composable

* Update AboutApp to use dynamic version info instead of BuildConfig

- Pass versionName and versionCode from AboutModel to AboutApp
- Remove dependency on BuildConfig in AboutApp
- Update AboutApp_Preview with sample version info

* Update URI statistics parameters

- Update `withStatParams` to include package name and version
- Replace `BuildConfig.APPLICATION_ID` with `context.packageName`
- Add context parameter to `withStatParams` in various activities

* Don't depend on BuildConfig for application name and version

- Introduce `ProductIds` for managing product IDs and User-Agent
- Update various classes to use `ProductIds` for product ID generation
- Move `TextTable` class from `at.bitfire.davdroid` to `at.bitfire.davdroid.util`

* Refactor OAuth classes for dependency injection

- Convert `OAuthFastmail` and `OAuthGoogle` to injectable classes
- Update `FastmailLoginModel` and `GoogleLoginModel` to use injected instances
- Move `redirectUri` initialization to `OAuthIntegration` constructor

* Adapt DI

- Move CustomCertManagerModule to ose configuration
- Move coroutine scopes to scope package

* minor changes

* Remove custom certificate build config

- Remove `allowCustomCerts` build config field
- Replace `@Singleton` with `@Reusable` in CustomCertManagerModule

* Update imports and LogcatHandler initialization

- Update imports to use scoped dispatchers
- Replace BuildConfig.APPLICATION_ID with javaClass.name in LogcatHandler initialization
2026-02-05 13:59:31 +01:00
Ricki Hirner
490abcb88a Reduce BuildConfig dependencies (#1969)
* Update IntroScreen colors

- Replace M3ColorScheme with MaterialTheme.colorScheme
- Update background and icon colors to use MaterialTheme

* Update color scheme references

- Replace `M3ColorScheme.primaryLight` with `MaterialTheme.colorScheme.primary` in `WelcomePage.kt` and `AccountsDrawerHandler.kt`.

* Update AppTheme to accept custom color schemes

- Add `lightColorScheme` and `darkColorScheme` parameters
- Replace hardcoded color schemes with the new parameters

* Add color scheme dependency injection

- Add `LightColorScheme` and `DarkColorScheme` qualifiers
- Create `OseColorSchemes` module for providing color schemes
- Update `AppTheme` to use injected color schemes

* Update glance material dependency to material3

- Update `androidx.glance.material` to `androidx.glance.material3`
- Adjust imports and usage in `IconSyncButtonWidget.kt` and `LabeledSyncButtonWidget.kt` to use `GlanceTheme` and `ColorProviders` for color schemes
- Replace deprecated `ColorProvider` with `GlanceTheme.colors` for primary and onPrimary colors

* Refactor widget receivers and widgets to use dependency injection more properly

- Update `LabeledSyncButtonWidgetReceiver` and `IconSyncButtonWidgetReceiver` to use Hilt for dependency injection.
- Inject `SyncWidgetModel`, `LightColorScheme`, and `DarkColorScheme` into both widget receivers.
- Remove the use of `EntryPoint` and `EntryPointAccessors` from `LabeledSyncButtonWidget` and `IconSyncButtonWidget`.
- Pass injected dependencies directly to the widget constructors.

* Rename ThemeColors to OseTheme

- Update imports and references to use OseTheme
- Rename object M3ColorScheme to OseTheme

* Move AppTheme to ui.composable package because it's a reusable Composable

* Update AboutApp to use dynamic version info instead of BuildConfig

- Pass versionName and versionCode from AboutModel to AboutApp
- Remove dependency on BuildConfig in AboutApp
- Update AboutApp_Preview with sample version info

* Update URI statistics parameters

- Update `withStatParams` to include package name and version
- Replace `BuildConfig.APPLICATION_ID` with `context.packageName`
- Add context parameter to `withStatParams` in various activities

* Don't depend on BuildConfig for application name and version

- Introduce `ProductIds` for managing product IDs and User-Agent
- Update various classes to use `ProductIds` for product ID generation
- Move `TextTable` class from `at.bitfire.davdroid` to `at.bitfire.davdroid.util`

* Refactor OAuth classes for dependency injection

- Convert `OAuthFastmail` and `OAuthGoogle` to injectable classes
- Update `FastmailLoginModel` and `GoogleLoginModel` to use injected instances
- Move `redirectUri` initialization to `OAuthIntegration` constructor
2026-02-05 12:20:21 +01:00
Ricki Hirner
cca12e79d8 [UI] Properly provide color schemes over DI (#1966)
* Update IntroScreen colors

- Replace M3ColorScheme with MaterialTheme.colorScheme
- Update background and icon colors to use MaterialTheme

* Update color scheme references

- Replace `M3ColorScheme.primaryLight` with `MaterialTheme.colorScheme.primary` in `WelcomePage.kt` and `AccountsDrawerHandler.kt`.

* Update AppTheme to accept custom color schemes

- Add `lightColorScheme` and `darkColorScheme` parameters
- Replace hardcoded color schemes with the new parameters

* Add color scheme dependency injection

- Add `LightColorScheme` and `DarkColorScheme` qualifiers
- Create `OseColorSchemes` module for providing color schemes
- Update `AppTheme` to use injected color schemes

* Update glance material dependency to material3

- Update `androidx.glance.material` to `androidx.glance.material3`
- Adjust imports and usage in `IconSyncButtonWidget.kt` and `LabeledSyncButtonWidget.kt` to use `GlanceTheme` and `ColorProviders` for color schemes
- Replace deprecated `ColorProvider` with `GlanceTheme.colors` for primary and onPrimary colors

* Refactor widget receivers and widgets to use dependency injection more properly

- Update `LabeledSyncButtonWidgetReceiver` and `IconSyncButtonWidgetReceiver` to use Hilt for dependency injection.
- Inject `SyncWidgetModel`, `LightColorScheme`, and `DarkColorScheme` into both widget receivers.
- Remove the use of `EntryPoint` and `EntryPointAccessors` from `LabeledSyncButtonWidget` and `IconSyncButtonWidget`.
- Pass injected dependencies directly to the widget constructors.

* Rename ThemeColors to OseTheme

- Update imports and references to use OseTheme
- Rename object M3ColorScheme to OseTheme

* Move AppTheme to ui.composable package because it's a reusable Composable

* Always use Light Color Scheme for certain intro UI

- Inject `lightColorScheme` in `IntroActivity`
- Pass `lightColorScheme` to `IntroScreen`
- Use `lightColorScheme` for background and color in `IntroScreen` and `WelcomePage`

* Minor syntax
2026-02-05 11:43:55 +01:00
Ricki Hirner
915cf73027 Update version to 4.5.9 2026-02-04 10:58:57 +01:00
Ricki Hirner
53773eaf83 Go back to 4.5.9-rc.2 (4.5.9 with version code 405090003 was never released) 2026-02-03 16:00:55 +01:00
Ricki Hirner
9cd685982d Update synctools to correctly process tel: URIs in vCards (#1963) 2026-02-03 15:59:46 +01:00
Sunik Kupfer
d4902e84ce [synctools] Tasks rewrite: Use reader/writer (#1959)
* Update synctools; Use writer/reader

Signed-off-by: Sunik Kupfer <kupfer@bitfire.at>

* Update synctools

Signed-off-by: Sunik Kupfer <kupfer@bitfire.at>

---------

Signed-off-by: Sunik Kupfer <kupfer@bitfire.at>
2026-02-03 15:22:15 +01:00
dependabot[bot]
ec485fcfa5 Bump the app-dependencies group with 8 updates (#1961)
Bumps the app-dependencies group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| gradle-wrapper | `9.3.0` | `9.3.1` |
| androidx.activity:activity-compose | `1.12.2` | `1.12.3` |
| androidx.compose:compose-bom | `2026.01.00` | `2026.01.01` |
| androidx.paging:paging-runtime-ktx | `3.3.6` | `3.4.0` |
| androidx.paging:paging-compose | `3.3.6` | `3.4.0` |
| androidx.work:work-runtime-ktx | `2.11.0` | `2.11.1` |
| androidx.work:work-testing | `2.11.0` | `2.11.1` |
| [com.google.devtools.ksp](https://github.com/google/ksp) | `2.3.4` | `2.3.5` |


Updates `gradle-wrapper` from 9.3.0 to 9.3.1

Updates `androidx.activity:activity-compose` from 1.12.2 to 1.12.3

Updates `androidx.compose:compose-bom` from 2026.01.00 to 2026.01.01

Updates `androidx.paging:paging-runtime-ktx` from 3.3.6 to 3.4.0

Updates `androidx.paging:paging-compose` from 3.3.6 to 3.4.0

Updates `androidx.paging:paging-compose` from 3.3.6 to 3.4.0

Updates `androidx.work:work-runtime-ktx` from 2.11.0 to 2.11.1

Updates `androidx.work:work-testing` from 2.11.0 to 2.11.1

Updates `androidx.work:work-testing` from 2.11.0 to 2.11.1

Updates `com.google.devtools.ksp` from 2.3.4 to 2.3.5
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](https://github.com/google/ksp/compare/2.3.4...2.3.5)

---
updated-dependencies:
- dependency-name: gradle-wrapper
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: app-dependencies
- dependency-name: androidx.activity:activity-compose
  dependency-version: 1.12.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: app-dependencies
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2026.01.01
  dependency-type: direct:production
  dependency-group: app-dependencies
- dependency-name: androidx.paging:paging-runtime-ktx
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: app-dependencies
- dependency-name: androidx.paging:paging-compose
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: app-dependencies
- dependency-name: androidx.paging:paging-compose
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: app-dependencies
- dependency-name: androidx.work:work-runtime-ktx
  dependency-version: 2.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: app-dependencies
- dependency-name: androidx.work:work-testing
  dependency-version: 2.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: app-dependencies
- dependency-name: androidx.work:work-testing
  dependency-version: 2.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: app-dependencies
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.3.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: app-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-03 14:57:10 +01:00
Ricki Hirner
5709aaa2e5 Bump version to 4.5.9 2026-02-03 12:12:05 +01:00
Ricki Hirner
a19c397ef6 Sync files with davx5 repo (#1958)
* Sync changes with davx5 repo

* Remove unnecessary test launcher icons
2026-02-02 12:30:04 +01:00
546 changed files with 1143 additions and 548 deletions

View File

@@ -49,10 +49,10 @@ jobs:
# Cache configurations for the other jobs (including assemble for CodeQL)
- name: Populate configuration cache
run: |
./gradlew --dry-run app:assembleDebug
./gradlew --dry-run app:lintOseDebug
./gradlew --dry-run app:testOseDebugUnitTest
./gradlew --dry-run app:virtualOseDebugAndroidTest
./gradlew --dry-run core:assembleDebug app:assembleDebug
./gradlew --dry-run core:lintDebug app:lintOseDebug
./gradlew --dry-run core:testDebugUnitTest
./gradlew --dry-run core:virtualDebugAndroidTest
unit_tests:
needs: compile
@@ -76,10 +76,10 @@ jobs:
key: android-${{ hashFiles('app/build.gradle.kts') }}
- name: Lint checks
run: ./gradlew app:lintOseDebug
run: ./gradlew core:lintDebug app:lintOseDebug
- name: Unit tests
run: ./gradlew app:testOseDebugUnitTest
run: ./gradlew core:testDebugUnitTest
instrumented_tests:
needs: compile
@@ -126,7 +126,7 @@ jobs:
sudo udevadm trigger --name-match=kvm
- name: Instrumented tests
run: ./gradlew app:virtualOseDebugAndroidTest
run: ./gradlew core:virtualDebugAndroidTest
- name: Cache AVD
uses: actions/cache/save@v5

126
app-ose/build.gradle.kts Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.hilt)
alias(libs.plugins.ksp)
}
android {
compileSdk = 36
defaultConfig {
minSdk = 24 // Android 7.0
targetSdk = 36 // Android 16
applicationId = "at.bitfire.davdroid"
versionCode = 405090005
versionName = "4.5.9"
base.archivesName = "davx5-$versionCode-$versionName"
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
buildFeatures {
compose = true
}
// Java namespace for our classes (not to be confused with Android package ID)
namespace = "com.davx5.ose"
flavorDimensions += "distribution"
productFlavors {
create("ose") {
dimension = "distribution"
versionNameSuffix = "-ose"
}
}
androidResources {
generateLocaleConfig = true
}
buildTypes {
getByName("release") {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules-release.pro")
isShrinkResources = true
signingConfig = signingConfigs.findByName("bitfire")
}
}
signingConfigs {
create("bitfire") {
storeFile = file(System.getenv("ANDROID_KEYSTORE") ?: "/dev/null")
storePassword = System.getenv("ANDROID_KEYSTORE_PASSWORD")
keyAlias = System.getenv("ANDROID_KEY_ALIAS")
keyPassword = System.getenv("ANDROID_KEY_PASSWORD")
}
}
@Suppress("UnstableApiUsage")
testOptions {
managedDevices {
localDevices {
create("virtual") {
device = "Pixel 3"
// TBD: API level 35 and higher causes network tests to fail sometimes, see https://github.com/bitfireAT/davx5-ose/issues/1525
// Suspected reason: https://developer.android.com/about/versions/15/behavior-changes-all#background-network-access
apiLevel = 34
systemImageSource = "aosp-atd"
}
}
}
}
}
dependencies {
// include core subproject (manages its own dependencies itself, however from same version catalog)
implementation(project(":core"))
// Kotlin / Android
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines)
coreLibraryDesugaring(libs.android.desugaring)
// Hilt
implementation(libs.hilt.android.base)
ksp(libs.androidx.hilt.compiler)
ksp(libs.hilt.android.compiler)
// support libs
implementation(libs.androidx.core)
implementation(libs.androidx.hilt.work)
implementation(libs.androidx.lifecycle.viewmodel.base)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.work.base)
// Jetpack Compose
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.material3)
debugImplementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.compose.ui.toolingPreview)
// own libraries
implementation(libs.bitfire.cert4android)
// third-party libs
implementation(libs.guava)
implementation(libs.okhttp.base)
implementation(libs.openid.appauth)
}

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="internalOnly">
<application android:name=".App">
<!-- Required for Hilt/WorkManager integration. See
- https://developer.android.com/develop/background-work/background-tasks/persistent/configuration/custom-configuration#remove-default
- https://developer.android.com/training/dependency-injection/hilt-jetpack#workmanager
However, we must not disable AndroidX startup completely, as it's needed by other libraries like okhttp. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
</application>
</manifest>

View File

@@ -0,0 +1,30 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package com.davx5.ose
import androidx.work.Configuration
import at.bitfire.davdroid.CoreApp
import dagger.hilt.android.HiltAndroidApp
/**
* Actual implementation of Application, used for Hilt. Delegates to [CoreApp].
*/
@HiltAndroidApp
class App: CoreApp(), Configuration.Provider {
/**
* Required for Hilt/WorkManager integration, see:
* https://developer.android.com/training/dependency-injection/hilt-jetpack#workmanager
*
* This requires to remove the androidx.work.WorkManagerInitializer from App Startup
* in the AndroidManifest, see:
* https://developer.android.com/develop/background-work/background-tasks/persistent/configuration/custom-configuration#remove-default
*/
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}

View File

@@ -1,8 +1,8 @@
/***************************************************************************************************
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
**************************************************************************************************/
*/
package at.bitfire.davdroid
package com.davx5.ose
import android.content.Context
import at.bitfire.davdroid.ui.DebugInfoActivity

View File

@@ -0,0 +1,19 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package com.davx5.ose.di
import at.bitfire.davdroid.ui.AccountsDrawerHandler
import at.bitfire.davdroid.ui.OseAccountsDrawerHandler
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
@Module
@InstallIn(ActivityComponent::class)
interface AccountsDrawerHandlerModule {
@Binds
fun accountsDrawerHandler(impl: OseAccountsDrawerHandler): AccountsDrawerHandler
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package com.davx5.ose.di
import at.bitfire.davdroid.ui.about.AboutActivity
import com.davx5.ose.ui.about.OpenSourceLicenseInfoProvider
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
@Module
@InstallIn(ViewModelComponent::class)
interface AppLicenseInfoProviderModule {
@Binds
fun appLicenseInfoProvider(impl: OpenSourceLicenseInfoProvider): AboutActivity.AppLicenseInfoProvider
}

View File

@@ -2,63 +2,60 @@
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.di
package com.davx5.ose.di
import android.content.Context
import at.bitfire.cert4android.CustomCertManager
import at.bitfire.cert4android.CustomCertStore
import at.bitfire.cert4android.SettingsProvider
import at.bitfire.davdroid.BuildConfig
import at.bitfire.davdroid.settings.Settings
import at.bitfire.davdroid.settings.SettingsManager
import at.bitfire.davdroid.ui.ForegroundTracker
import dagger.Module
import dagger.Provides
import dagger.Reusable
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.internal.tls.OkHostnameVerifier
import java.util.Optional
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
/**
* cert4android integration module
*/
class CustomCertManagerModule {
@Module
@InstallIn(SingletonComponent::class)
class Cert4AndroidModule {
@Provides
@Singleton
fun customCertStore(@ApplicationContext context: Context): Optional<CustomCertStore> =
Optional.of(CustomCertStore.getInstance(context))
@Provides
@Reusable
fun customCertManager(
@ApplicationContext context: Context,
customCertStore: Optional<CustomCertStore>,
settings: SettingsManager
): Optional<CustomCertManager> =
if (BuildConfig.allowCustomCerts)
Optional.of(CustomCertManager(
certStore = CustomCertStore.getInstance(context),
settings = object : SettingsProvider {
Optional.of(
CustomCertManager(
certStore = customCertStore.get(),
settings = object : SettingsProvider {
override val appInForeground: Boolean
get() = ForegroundTracker.inForeground.value
override val appInForeground: Boolean
get() = ForegroundTracker.inForeground.value
override val trustSystemCerts: Boolean
get() = !settings.getBoolean(Settings.DISTRUST_SYSTEM_CERTIFICATES)
override val trustSystemCerts: Boolean
get() = !settings.getBoolean(Settings.DISTRUST_SYSTEM_CERTIFICATES)
}
))
else
Optional.empty()
}
))
@Provides
@Singleton
@Reusable
fun customHostnameVerifier(
customCertManager: Optional<CustomCertManager>
): Optional<CustomCertManager.HostnameVerifier> =
if (BuildConfig.allowCustomCerts && customCertManager.isPresent) {
val hostnameVerifier = customCertManager.get().HostnameVerifier(OkHostnameVerifier)
Optional.of(hostnameVerifier)
} else
Optional.empty()
Optional.of(customCertManager.get().HostnameVerifier(OkHostnameVerifier))
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package com.davx5.ose.di
import androidx.compose.material3.ColorScheme
import at.bitfire.davdroid.di.qualifier.DarkColorScheme
import at.bitfire.davdroid.di.qualifier.LightColorScheme
import at.bitfire.davdroid.ui.OseTheme
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
class ColorSchemesModule {
@Provides
@LightColorScheme
fun lightColorScheme(): ColorScheme = OseTheme.lightScheme
@Provides
@DarkColorScheme
fun darkColorScheme(): ColorScheme = OseTheme.darkScheme
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package com.davx5.ose.di
import at.bitfire.davdroid.ui.intro.IntroPageFactory
import com.davx5.ose.ui.intro.OseIntroPageFactory
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface Global {
@Binds
fun introPageFactory(impl: OseIntroPageFactory): IntroPageFactory
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package com.davx5.ose.di
import at.bitfire.davdroid.ui.setup.LoginTypesProvider
import at.bitfire.davdroid.ui.setup.StandardLoginTypesProvider
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface LoginTypesProviderModule {
@Binds
fun loginTypesProvider(impl: StandardLoginTypesProvider): LoginTypesProvider
}

View File

@@ -2,9 +2,9 @@
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.about
package com.davx5.ose.ui.about
import android.app.Application
import android.content.Context
import android.text.Spanned
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -14,13 +14,16 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.text.HtmlCompat
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import at.bitfire.davdroid.di.qualifier.IoDispatcher
import at.bitfire.davdroid.ui.UiUtils.toAnnotatedString
import at.bitfire.davdroid.ui.about.AboutActivity
import com.google.common.io.CharStreams
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -40,13 +43,16 @@ class OpenSourceLicenseInfoProvider @Inject constructor(): AboutActivity.AppLice
@HiltViewModel
class Model @Inject constructor(app: Application): AndroidViewModel(app) {
class Model @Inject constructor(
@ApplicationContext private val context: Context,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
): ViewModel() {
var gpl by mutableStateOf<Spanned?>(null)
init {
viewModelScope.launch(Dispatchers.IO) {
app.resources.assets.open("gplv3.html").use { inputStream ->
viewModelScope.launch(ioDispatcher) {
context.resources.assets.open("gplv3.html").use { inputStream ->
val raw = CharStreams.toString(inputStream.bufferedReader())
gpl = HtmlCompat.fromHtml(raw, HtmlCompat.FROM_HTML_MODE_LEGACY)
}

View File

@@ -2,8 +2,15 @@
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.intro
package com.davx5.ose.ui.intro
import at.bitfire.davdroid.ui.intro.BackupsPage
import at.bitfire.davdroid.ui.intro.BatteryOptimizationsPage
import at.bitfire.davdroid.ui.intro.IntroPageFactory
import at.bitfire.davdroid.ui.intro.OpenSourcePage
import at.bitfire.davdroid.ui.intro.PermissionsIntroPage
import at.bitfire.davdroid.ui.intro.TasksIntroPage
import at.bitfire.davdroid.ui.intro.WelcomePage
import javax.inject.Inject
class OseIntroPageFactory @Inject constructor(

1
app/src/.gitignore vendored
View File

@@ -1 +0,0 @@
espressoTest

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,22 +0,0 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid
import at.bitfire.synctools.icalendar.ical4jVersion
import ezvcard.Ezvcard
/**
* Brand-specific constants like (non-theme) colors, homepage URLs etc.
*/
object Constants {
const val DAVDROID_GREEN_RGBA = 0xFF8bc34a.toInt()
// product IDs for iCalendar/vCard
val iCalProdId = "DAVx5/${BuildConfig.VERSION_NAME} ical4j/$ical4jVersion"
const val vCardProdId = "+//IDN bitfire.at//DAVx5/${BuildConfig.VERSION_NAME} ez-vcard/${Ezvcard.VERSION}"
}

View File

@@ -1,12 +0,0 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.widget
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
class IconSyncButtonWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = IconSyncButtonWidget()
}

View File

@@ -1,12 +0,0 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.ui.widget
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
class LabeledSyncButtonWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = LabeledSyncButtonWidget()
}

View File

@@ -1,12 +0,0 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.mikepenz.aboutLibraries.android) apply false
}

View File

View File

@@ -3,7 +3,7 @@
*/
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.android.library)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.hilt)
alias(libs.plugins.kotlin.serialization)
@@ -16,18 +16,7 @@ android {
compileSdk = 36
defaultConfig {
applicationId = "at.bitfire.davdroid"
versionCode = 405090002
versionName = "4.5.9-rc.1"
base.archivesName = "davx5-ose-$versionName"
minSdk = 24 // Android 7.0
targetSdk = 36 // Android 16
// whether the build supports and allows to use custom certificates
buildConfigField("boolean", "allowCustomCerts", "true")
testInstrumentationRunner = "at.bitfire.davdroid.HiltTestRunner"
}
@@ -53,37 +42,9 @@ android {
// Java namespace for our classes (not to be confused with Android package ID)
namespace = "at.bitfire.davdroid"
flavorDimensions += "distribution"
productFlavors {
create("ose") {
dimension = "distribution"
versionNameSuffix = "-ose"
}
}
sourceSets {
getByName("androidTest") {
assets.srcDir("$projectDir/schemas")
}
}
signingConfigs {
create("bitfire") {
storeFile = file(System.getenv("ANDROID_KEYSTORE") ?: "/dev/null")
storePassword = System.getenv("ANDROID_KEYSTORE_PASSWORD")
keyAlias = System.getenv("ANDROID_KEY_ALIAS")
keyPassword = System.getenv("ANDROID_KEY_PASSWORD")
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules-release.pro")
isShrinkResources = true
signingConfig = signingConfigs.findByName("bitfire")
isMinifyEnabled = false
}
}
@@ -91,10 +52,6 @@ android {
disable += arrayOf("GoogleAppIndexingWarning", "ImpliedQuantity", "MissingQuantity", "MissingTranslation", "ExtraTranslation", "RtlEnabled", "RtlHardcoded", "Typos")
}
androidResources {
generateLocaleConfig = true
}
packaging {
resources {
// multiple (test) dependencies have LICENSE files at same location
@@ -102,6 +59,12 @@ android {
}
}
sourceSets {
getByName("androidTest") {
assets.srcDir("$projectDir/schemas")
}
}
@Suppress("UnstableApiUsage")
testOptions {
managedDevices {
@@ -130,7 +93,7 @@ aboutLibraries {
}
dependencies {
// core
// Kotlin / Android
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines)
coreLibraryDesugaring(libs.android.desugaring)
@@ -167,7 +130,7 @@ dependencies {
// Glance Widgets
implementation(libs.androidx.glance.base)
implementation(libs.androidx.glance.material)
implementation(libs.androidx.glance.material3)
// Jetpack Room
implementation(libs.androidx.room.runtime)

View File

View File

@@ -10,7 +10,6 @@ import android.os.Build
import android.os.Bundle
import androidx.test.runner.AndroidJUnitRunner
import at.bitfire.davdroid.di.TestCoroutineDispatchersModule
import at.bitfire.davdroid.test.BuildConfig
import at.bitfire.synctools.log.LogcatHandler
import dagger.hilt.android.testing.HiltTestApplication
import java.util.logging.Level
@@ -29,7 +28,7 @@ class HiltTestRunner : AndroidJUnitRunner() {
val rootLogger = Logger.getLogger("")
rootLogger.level = Level.ALL
rootLogger.handlers.forEach { rootLogger.removeHandler(it) }
rootLogger.addHandler(LogcatHandler(BuildConfig.APPLICATION_ID))
rootLogger.addHandler(LogcatHandler(javaClass.name))
// MockK requirements
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)

View File

@@ -0,0 +1,28 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.di
import at.bitfire.cert4android.CustomCertManager
import at.bitfire.cert4android.CustomCertStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import java.util.Optional
@Module
@InstallIn(SingletonComponent::class)
class Cert4AndroidModule {
@Provides
fun customCertManager(): Optional<CustomCertManager> = Optional.empty()
@Provides
fun customHostnameVerifier(): Optional<CustomCertManager.HostnameVerifier> = Optional.empty()
@Provides
fun customCertStore(): Optional<CustomCertStore> = Optional.empty()
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.di
import androidx.compose.material3.ColorScheme
import at.bitfire.davdroid.di.qualifier.DarkColorScheme
import at.bitfire.davdroid.di.qualifier.LightColorScheme
import at.bitfire.davdroid.ui.OseTheme
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
class ColorSchemesModule {
@Provides
@LightColorScheme
fun lightColorScheme(): ColorScheme = OseTheme.lightScheme
@Provides
@DarkColorScheme
fun darkColorScheme(): ColorScheme = OseTheme.darkScheme
}

View File

@@ -5,6 +5,10 @@
package at.bitfire.davdroid.di
import at.bitfire.davdroid.di.TestCoroutineDispatchersModule.standardTestDispatcher
import at.bitfire.davdroid.di.qualifier.DefaultDispatcher
import at.bitfire.davdroid.di.qualifier.IoDispatcher
import at.bitfire.davdroid.di.qualifier.MainDispatcher
import at.bitfire.davdroid.di.qualifier.SyncDispatcher
import dagger.Module
import dagger.Provides
import dagger.hilt.components.SingletonComponent

View File

@@ -7,9 +7,9 @@ package at.bitfire.davdroid.di
import at.bitfire.davdroid.ui.AccountsDrawerHandler
import at.bitfire.davdroid.ui.OseAccountsDrawerHandler
import at.bitfire.davdroid.ui.about.AboutActivity
import at.bitfire.davdroid.ui.about.OpenSourceLicenseInfoProvider
import at.bitfire.davdroid.ui.about.FakeAppLicenseInfoProvider
import at.bitfire.davdroid.ui.intro.FakeIntroPageFactory
import at.bitfire.davdroid.ui.intro.IntroPageFactory
import at.bitfire.davdroid.ui.intro.OseIntroPageFactory
import at.bitfire.davdroid.ui.setup.LoginTypesProvider
import at.bitfire.davdroid.ui.setup.StandardLoginTypesProvider
import dagger.Binds
@@ -35,7 +35,7 @@ interface OseModules {
@InstallIn(ViewModelComponent::class)
interface ForViewModels {
@Binds
fun appLicenseInfoProvider(impl: OpenSourceLicenseInfoProvider): AboutActivity.AppLicenseInfoProvider
fun appLicenseInfoProvider(impl: FakeAppLicenseInfoProvider): AboutActivity.AppLicenseInfoProvider
@Binds
fun loginTypesProvider(impl: StandardLoginTypesProvider): LoginTypesProvider
@@ -45,7 +45,7 @@ interface OseModules {
@InstallIn(SingletonComponent::class)
interface Global {
@Binds
fun introPageFactory(impl: OseIntroPageFactory): IntroPageFactory
fun introPageFactory(impl: FakeIntroPageFactory): IntroPageFactory
}
}

Some files were not shown because too many files have changed in this diff Show More