Skip to content

Commit

Permalink
Upgrade to android 35 and various version updates and changes (#1640)
Browse files Browse the repository at this point in the history
* android-agp = "8.7.2"

* Android 35 upgrade

* Resolved broken Account object

* androidx-core = "1.15.0"

* androidx-work = "2.10.0"

* mapsCompose = "6.2.1"

* Updated ical4android version

* Revert "Updated ical4android version"

This reverts commit 67b88b4.

* Update JtxContract.kt

* agp upgrade
android-agp = "8.7.3"

* fixed broken android tests

* Replaced deprecated methods

* Adapted widget color handling for Android 35 compatibility. Removed warning from UI.

* Replaced GoDaddy Colorpicker with Colorpicker-Compose
Closes #1481

* Show selected color in color picker

* Fixed lint error by removing FixedColorProvider

* compose-bom = "2024.12.01"

* compose-bom = "2024.12.01"

* uiTextGoogleFonts = "1.7.6"

* android-agp = "8.8.0-rc01"
  • Loading branch information
patrickunterwegs authored Dec 15, 2024
1 parent ccb9a3b commit 0375fce
Show file tree
Hide file tree
Showing 29 changed files with 397 additions and 365 deletions.
6 changes: 3 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ plugins {

android {
namespace = "at.techbee.jtx"
compileSdk = 34
compileSdk = 35
defaultConfig {
applicationId = "at.techbee.jtx"
buildConfigField("long", "buildTime", "${System.currentTimeMillis()}L")
minSdk = 23
targetSdk = 34
targetSdk = 35
versionCode = 209040003
versionName = "2.09.04" // keep -release as a suffix also for release, build flavor adds the suffix e.g. .gplay (e.g. 1.00.00-rc0.gplay)
buildConfigField("String", "versionCodename", "\"Pride is a protest \uD83C\uDF08\"")
Expand Down Expand Up @@ -210,7 +210,7 @@ dependencies {

// third-party libs
implementation(libs.mikepenz.aboutLibraries)
implementation(libs.godaddy.colorpicker) // Compose Color Picker
implementation(libs.colorpicker.compose) // Compose Color Picker
implementation(libs.markdowntext) // Markdown support
implementation(libs.osmdroid.android) //Open Street Maps
implementation (libs.calendar.compose)
Expand Down
10 changes: 7 additions & 3 deletions app/src/androidTest/java/at/techbee/jtx/FileCleanupJobTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.work.*
import androidx.work.Configuration
import androidx.work.Constraints
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -57,7 +61,7 @@ class FileCleanupJobTest {
testDriver?.setAllConstraintsMet(request.id)
val workInfo = workManager.getWorkInfoById(request.id).get()

assertEquals(WorkInfo.State.RUNNING, workInfo.state)
assertTrue(workInfo?.state in listOf(WorkInfo.State.RUNNING, WorkInfo.State.SUCCEEDED))

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ import at.techbee.jtx.contract.JtxContract
import at.techbee.jtx.contract.JtxContract.asSyncAdapter
import at.techbee.jtx.database.ICalDatabase
import at.techbee.jtx.database.TABLE_NAME_ICALOBJECT
import at.techbee.jtx.database.properties.*
import at.techbee.jtx.database.properties.Alarm
import at.techbee.jtx.database.properties.Reltype
import org.junit.After
import org.junit.Assert.*
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.util.*
import java.util.UUID


@RunWith(AndroidJUnit4::class)
Expand Down Expand Up @@ -722,7 +725,7 @@ class SyncContentProviderTest {

@Test(expected = java.lang.IllegalArgumentException::class)
fun getAccountFromUri_empty() {
val account = Account(null, null)
val account = Account("", "")
val uri = JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(account)
SyncContentProvider().getAccountFromUri(uri)
}
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/at/techbee/jtx/MainActivity2.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package at.techbee.jtx

import android.accounts.Account
import android.app.Activity
import android.content.Context
import android.content.Intent
Expand Down Expand Up @@ -173,7 +172,7 @@ class MainActivity2 : AppCompatActivity() {
if(settingsStateHolder.settingSyncOnStart.value) {
lifecycleScope.launch(Dispatchers.IO) {
val remoteCollections = ICalDatabase.getInstance(applicationContext).iCalDatabaseDao().getAllRemoteCollections()
SyncUtil.syncAccounts(remoteCollections.map { Account(it.accountName, it.accountType) }.toSet())
SyncUtil.syncAccounts(remoteCollections.map { it.getAccount() }.toSet())
}
}

Expand Down
17 changes: 14 additions & 3 deletions app/src/main/java/at/techbee/jtx/contract/JtxContract.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ import net.fortuna.ical4j.model.parameter.XParameter
import net.fortuna.ical4j.model.property.XProperty
import org.json.JSONObject
import java.util.logging.Level
import java.util.logging.Logger


@Suppress("unused")
object JtxContract {

private val logger
get() = Logger.getLogger(javaClass.name)

/**
* URI parameter to signal that the caller is a sync adapter.
*/
Expand All @@ -42,7 +47,7 @@ object JtxContract {
const val AUTHORITY = "at.techbee.jtx.provider"

/** The version of this SyncContentProviderContract */
const val VERSION = 7
const val VERSION = 8

/** Constructs an Uri for the Jtx Sync Adapter with the given Account
* @param [account] The account that should be appended to the Base Uri
Expand Down Expand Up @@ -100,7 +105,7 @@ object JtxContract {
}
}
} catch (e: NullPointerException) {
Ical4Android.log.log(Level.WARNING, "Error parsing x-property-list $string", e)
logger.log(Level.WARNING, "Error parsing x-property-list $string", e)
}
return propertyList
}
Expand Down Expand Up @@ -163,7 +168,7 @@ object JtxContract {
try {
longList.add(it.toLong())
} catch (e: NumberFormatException) {
Ical4Android.log.log(Level.WARNING, "String could not be cast to Long ($it)")
logger.log(Level.WARNING, "String could not be cast to Long ($it)")
return@forEach
}
}
Expand Down Expand Up @@ -1211,6 +1216,12 @@ object JtxContract {
*/
const val LAST_SYNC = "lastsync"

/**
* Purpose: This column/property stores a sync_id for the given collection
* See https://github.com/TechbeeAT/jtxBoard/issues/1635
* Type: [Long]
*/
const val SYNC_ID = "sync_id"
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,5 @@ data class ICalCollection(
/**
* @return The account of the given collection as [Account]
*/
fun getAccount(): Account = Account(accountName, accountType)
fun getAccount(): Account = Account(accountName?:"", accountType?: LOCAL_ACCOUNT_TYPE)
}
3 changes: 1 addition & 2 deletions app/src/main/java/at/techbee/jtx/ui/GlobalStateHolder.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package at.techbee.jtx.ui

import android.accounts.Account
import android.content.ContentResolver
import android.content.Context
import android.util.Log
Expand Down Expand Up @@ -42,7 +41,7 @@ class GlobalStateHolder(context: Context) {
init {
try {
ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE) {
isSyncInProgress.value = SyncUtil.isJtxSyncRunningFor(remoteCollections.value.map { Account(it.accountName, it.accountType) }.toSet())
isSyncInProgress.value = SyncUtil.isJtxSyncRunningFor(remoteCollections.value.map { it.getAccount() }.toSet())
}
} catch(e: NullPointerException) { // especially necessary as ContentResolver is not available in preview (would cause exception)
Log.d(TAG, e.stackTraceToString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

package at.techbee.jtx.ui.collections

import android.accounts.Account
import android.net.Uri
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand Down Expand Up @@ -269,7 +268,7 @@ fun CollectionCard(
text = { Text(stringResource(R.string.menu_collection_popup_show_in_sync_app, syncApp.appName)) },
leadingIcon = { Icon(Icons.Outlined.Sync, null) },
onClick = {
SyncUtil.openSyncAppAccountActivity(syncApp, Account(collection.accountName, collection.accountType), context)
SyncUtil.openSyncAppAccountActivity(syncApp, collection.toICalCollection().getAccount(), context)
menuExpanded = false
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fun CollectionsScreenContent(
onDeleteAccount: (Account) -> Unit
) {

val grouped = collections.groupBy { Account(it.accountName, it.accountType) }
val grouped = collections.groupBy { it.toICalCollection().getAccount() }
val showProgressIndicator by isProcessing.observeAsState(false)

val foundAccounts = mutableSetOf<Account>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ class CollectionsViewModel(application: Application) : AndroidViewModel(applicat
when(collectionsExportMimetype) {
CollectionsExportMimetype.ICS -> {
val collection = collectionsToExport.value?.first() ?: throw IOException("Collections to export are empty")
Ical4androidUtil.getICSFormatForCollectionFromProvider(Account(collection.accountName, collection.accountType), getApplication(), collection.collectionId)?.let { ics ->
Ical4androidUtil.getICSFormatForCollectionFromProvider(collection.toICalCollection().getAccount(), getApplication(), collection.collectionId)?.let { ics ->
outputStream.write(ics.toByteArray())
}
}
CollectionsExportMimetype.ZIP -> {
val bos = BufferedOutputStream(outputStream)
ZipOutputStream(bos).use { zos ->
collectionsToExport.value?.forEach { collection ->
Ical4androidUtil.getICSFormatForCollectionFromProvider(Account(collection.accountName, collection.accountType), getApplication(), collection.collectionId)
Ical4androidUtil.getICSFormatForCollectionFromProvider(collection.toICalCollection().getAccount(), getApplication(), collection.collectionId)
?.let { ics ->
zos.putNextEntry(ZipEntry("${collection.displayName ?: collection.collectionId.toString()}.ics"))
zos.write(ics.toByteArray())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

package at.techbee.jtx.ui.detail

import android.accounts.Account
import android.content.ContentResolver
import android.widget.Toast
import androidx.compose.animation.AnimatedVisibility
Expand Down Expand Up @@ -68,11 +67,11 @@ import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.LocalLifecycleOwner
import at.techbee.jtx.R
import at.techbee.jtx.database.ICalCollection
import at.techbee.jtx.database.ICalCollection.Factory.LOCAL_ACCOUNT_TYPE
Expand Down Expand Up @@ -126,7 +125,7 @@ fun DetailBottomAppBar(
null
else {
ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE) {
isSyncInProgress = SyncUtil.isJtxSyncRunningFor(setOf(Account(collection.accountName, collection.accountType)))
isSyncInProgress = SyncUtil.isJtxSyncRunningFor(setOf(collection.getAccount()))
}
}
onDispose {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fun DetailsCardCollections(

if (showColorPicker) {
ColorPickerDialog(
initialColor = color.value,
initialColorInt = color.value,
onColorChanged = { newColor ->
color.value = newColor
iCalObject?.color = newColor
Expand Down
48 changes: 39 additions & 9 deletions app/src/main/java/at/techbee/jtx/ui/detail/DetailsCardLocation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,44 @@ import android.os.Build
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.OpenInNew
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material.icons.outlined.ArrowDropDown
import androidx.compose.material.icons.outlined.Clear
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.Contacts
import androidx.compose.material.icons.outlined.EditLocation
import androidx.compose.material.icons.outlined.Map
import androidx.compose.material.icons.outlined.MyLocation
import androidx.compose.material.icons.outlined.Place
import androidx.compose.material3.AssistChip
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
Expand All @@ -45,7 +72,6 @@ import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import androidx.room.ColumnInfo
import at.techbee.jtx.BuildFlavor
import at.techbee.jtx.R
Expand All @@ -59,9 +85,13 @@ import at.techbee.jtx.ui.reusable.dialogs.LocationPickerDialog
import at.techbee.jtx.ui.reusable.dialogs.RequestPermissionDialog
import at.techbee.jtx.ui.reusable.elements.HeadlineWithIcon
import at.techbee.jtx.util.UiUtil
import com.google.accompanist.permissions.*
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.shouldShowRationale
import java.net.URLEncoder
import java.util.*
import java.util.Locale
import kotlin.math.roundToInt


Expand Down Expand Up @@ -154,7 +184,7 @@ fun DetailsCardLocation(
text = stringResource(id = R.string.geofence_request_permission_dialog_message),
onConfirm = {
if(geofencePermissionState?.shouldShowRationale == true)
startActivity(context, openPermissionsIntent, null)
context.startActivity(openPermissionsIntent)
else
geofencePermissionState?.launchMultiplePermissionRequest()
showRequestGeofencePermissionsDialog = false
Expand Down Expand Up @@ -500,7 +530,7 @@ fun DetailsCardLocation(
modifier = Modifier.weight(1f)
)
TextButton(
onClick = { startActivity(context, openPermissionsIntent, null) }
onClick = { context.startActivity(openPermissionsIntent) }
) {
Text(stringResource(id = R.string.permissions))
}
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/at/techbee/jtx/ui/list/ListSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class ListSettings {

var widgetHeader: MutableState<String> = mutableStateOf("") //widgetOnly
var checkboxPosition: MutableState<CheckboxPosition> = mutableStateOf(CheckboxPosition.START) // widget only
var widgetAlpha: MutableState<Float> = mutableFloatStateOf(1F) // widget only
var widgetAlphaEntries: MutableState<Float> = mutableFloatStateOf(1F) // widget only
@Deprecated("alpha is now in widgetColor") var widgetAlpha: MutableState<Float> = mutableFloatStateOf(1F) // widget only
@Deprecated("alpha is now in widgetColorEntries") var widgetAlphaEntries: MutableState<Float> = mutableFloatStateOf(1F) // widget only
var widgetColor: MutableState<Int?> = mutableStateOf(null) // widget only
var widgetColorEntries: MutableState<Int?> = mutableStateOf(null) // widget only
var showDescription: MutableState<Boolean> = mutableStateOf(true) // widget only
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/java/at/techbee/jtx/ui/list/ListViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

package at.techbee.jtx.ui.list

import android.accounts.Account
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
Expand Down Expand Up @@ -442,7 +441,7 @@ open class ListViewModel(application: Application, val module: Module) : Android
fun syncAccounts() {
viewModelScope.launch(Dispatchers.IO) {
val collections = databaseDao.getAllRemoteCollections()
SyncUtil.syncAccounts(collections.map { Account(it.accountName, it.accountType) }.toSet())
SyncUtil.syncAccounts(collections.map { it.getAccount() }.toSet())
}
SyncUtil.showSyncRequestedToast(_application)
}
Expand Down
Loading

0 comments on commit 0375fce

Please sign in to comment.