Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ plugins {
object Version {
private const val MAJOR = 1
private const val MINOR = 4
private const val PATCH = 2
private const val PATCH = 3

const val CODE = MAJOR * 10000 + MINOR * 100 + PATCH
const val NAME = "$MAJOR.$MINOR.$PATCH"
Expand Down Expand Up @@ -104,11 +104,6 @@ dependencies {
androidTestImplementation(libs.androidx.test.extJunit)
}

ksp {
arg("room.incremental", "true")
arg("room.generateKotlin", "true")
}

room {
schemaDirectory("$projectDir/schemas")
}
2 changes: 1 addition & 1 deletion app/src/main/java/ru/spbu/depnav/data/db/DatabaseModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ object DatabaseModule {
DB_ASSET
)
.createFromAsset(DB_ASSET)
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigration(false)
.build()

@Provides
Expand Down
32 changes: 12 additions & 20 deletions app/src/main/java/ru/spbu/depnav/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
Expand All @@ -47,27 +46,20 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)

setContent {
CompositionLocalProvider(
// Fix for https://issuetracker.google.com/issues/336842920 -- should be removed as
// soon as Compose UI 1.7.0 becomes stable
androidx.lifecycle.compose.LocalLifecycleOwner provides
androidx.compose.ui.platform.LocalLifecycleOwner.current
) {
val themeMode by prefs.themeModeFlow.collectAsStateWithLifecycle()
val darkTheme = when (themeMode) {
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
ThemeMode.SYSTEM -> isSystemInDarkTheme()
}

LaunchedEffect(darkTheme) {
val style =
SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT) { darkTheme }
enableEdgeToEdge(style, style)
}
val themeMode by prefs.themeModeFlow.collectAsStateWithLifecycle()
val darkTheme = when (themeMode) {
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
ThemeMode.SYSTEM -> isSystemInDarkTheme()
}

DepNavTheme(darkTheme = darkTheme) { MapScreen(prefs) }
LaunchedEffect(darkTheme) {
val style =
SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT) { darkTheme }
enableEdgeToEdge(style, style)
}

DepNavTheme(darkTheme = darkTheme) { MapScreen(prefs) }
}
}
}
131 changes: 61 additions & 70 deletions app/src/main/java/ru/spbu/depnav/ui/component/MapSearchBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
Expand All @@ -50,23 +48,25 @@ import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import ovh.plrapps.mapcompose.utils.lerp
import ru.spbu.depnav.R
import ru.spbu.depnav.ui.theme.DEFAULT_PADDING
import ru.spbu.depnav.ui.theme.ON_MAP_SURFACE_ALPHA
import ru.spbu.depnav.ui.viewmodel.SearchResults

// These are basically copied from SearchBar implementation
private val ACTIVATION_ENTER_SPEC = tween<Float>(
private val EXPANSION_ENTER_SPEC = tween<Float>(
durationMillis = 600,
delayMillis = 100,
easing = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1.0f)
)
private val ACTIVATION_EXIT_SPEC = tween<Float>(
private val EXPANSION_EXIT_SPEC = tween<Float>(
durationMillis = 350,
delayMillis = 100,
easing = CubicBezierEasing(0.0f, 1.0f, 0.0f, 1.0f)
Expand All @@ -76,106 +76,97 @@ private val ACTIVATION_EXIT_SPEC = tween<Float>(
* Search bar for querying map markers on [ru.spbu.depnav.ui.screen.MapScreen].
*/
@Composable
@Suppress(
"LongMethod", // No point in further shrinking
"LongParameterList" // Considered OK for a composable
)
@Suppress("LongParameterList") // Considered OK for a composable
@OptIn(ExperimentalMaterial3Api::class)
fun MapSearchBar(
query: String,
onQueryChange: (String) -> Unit,
mapTitle: String,
active: Boolean,
onActiveChange: (Boolean) -> Unit,
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
results: SearchResults,
onResultClick: (Int) -> Unit,
onMenuClick: () -> Unit,
modifier: Modifier = Modifier
) {
val activationAnimationProgress by animateFloatAsState(
targetValue = if (active) 1f else 0f,
animationSpec = if (active) ACTIVATION_ENTER_SPEC else ACTIVATION_EXIT_SPEC,
val expansionAnimationProgress by animateFloatAsState(
targetValue = if (expanded) 1f else 0f,
animationSpec = if (expanded) EXPANSION_ENTER_SPEC else EXPANSION_EXIT_SPEC,
label = "Map search bar activation animation progress"
)

val (insetsStartPadding, insetsEndPadding) = with(WindowInsets.safeDrawing.asPaddingValues()) {
val layoutDirection = LocalLayoutDirection.current
calculateStartPadding(layoutDirection) to calculateEndPadding(layoutDirection)
}

val outerStartPadding = insetsStartPadding * (1 - activationAnimationProgress)
val outerEndPadding = insetsEndPadding * (1 - activationAnimationProgress)
val innerStartPadding = insetsStartPadding * activationAnimationProgress
val innerEndPadding = insetsEndPadding * activationAnimationProgress

val focusManager = LocalFocusManager.current

val containerColorAlpha =
ON_MAP_SURFACE_ALPHA + (1 - ON_MAP_SURFACE_ALPHA) * activationAnimationProgress

SearchBar(
query = query,
onQueryChange = onQueryChange,
onSearch = { focusManager.clearFocus() },
active = active,
onActiveChange = onActiveChange,
modifier = Modifier
.run {
if (active) padding(start = outerStartPadding, end = outerEndPadding)
else windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal))
}
.then(modifier),
placeholder = {
Text(
stringResource(R.string.search_on_map, mapTitle),
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
},
leadingIcon = {
AnimatedLeadingIcon(
active,
onMenuClick = onMenuClick,
modifier = Modifier.padding(start = innerStartPadding),
onNavigateBackClick = { onActiveChange(false) }
)
},
trailingIcon = {
AnimatedTrailingIcon(
active,
query.isEmpty(),
onClearClick = { onQueryChange("") },
modifier = Modifier.padding(end = innerEndPadding)
inputField = {
SearchBarDefaults.InputField(
query = query,
onQueryChange = onQueryChange,
onSearch = with (LocalFocusManager.current) { { clearFocus() } },
expanded = expanded,
onExpandedChange = onExpandedChange,
modifier = Modifier.windowInsetsPadding(
WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal) *
expansionAnimationProgress
),
placeholder = {
Text(
stringResource(R.string.search_on_map, mapTitle),
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
},
leadingIcon = {
AnimatedLeadingIcon(
expanded,
onMenuClick = onMenuClick,
onNavigateBackClick = { onExpandedChange(false) }
)
},
trailingIcon = {
AnimatedTrailingIcon(
expanded,
queryEmpty = query.isEmpty(),
onClearClick = { onQueryChange("") }
)
}
)
},
expanded = expanded,
onExpandedChange = onExpandedChange,
modifier = modifier,
colors = SearchBarDefaults.colors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(
alpha = containerColorAlpha
alpha = lerp(ON_MAP_SURFACE_ALPHA, 1f, expansionAnimationProgress)
)
)
),
) {
val keyboard = LocalSoftwareKeyboardController.current

SearchResultsView(
results,
onScroll = { onTop -> keyboard?.apply { if (onTop) show() else hide() } },
onResultClick = {
onActiveChange(false)
onExpandedChange(false)
onResultClick(it)
},
modifier = Modifier
.windowInsetsPadding(WindowInsets.safeDrawing)
.padding(horizontal = DEFAULT_PADDING * 1.5f)
.padding(
start = innerStartPadding,
end = innerEndPadding,
bottom = WindowInsets.safeDrawing
.asPaddingValues()
.calculateBottomPadding()
)
)
}
}

@Composable
private operator fun WindowInsets.times(num: Float): WindowInsets {
val paddings = asPaddingValues(LocalDensity.current)
val layoutDirection = LocalLayoutDirection.current
return WindowInsets(
paddings.calculateLeftPadding(layoutDirection) * num,
paddings.calculateTopPadding() * num,
paddings.calculateRightPadding(layoutDirection) * num,
paddings.calculateBottomPadding() * num
)
}

@Composable
private fun AnimatedLeadingIcon(
searchBarActive: Boolean,
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/ru/spbu/depnav/ui/screen/MapScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,12 @@ private fun BoxScope.AnimatedSearchBar(
onResultClick: (Int) -> Unit,
onMenuClick: () -> Unit
) {
var searchBarActive by rememberSaveable { mutableStateOf(false) }
var searchBarExpanded by rememberSaveable { mutableStateOf(false) }
if (!visible) {
searchBarActive = false
searchBarExpanded = false
}

if (!searchBarActive && query.isNotEmpty()) {
if (!searchBarExpanded && query.isNotEmpty()) {
onQueryChange("")
}

Expand All @@ -236,16 +236,16 @@ private fun BoxScope.AnimatedSearchBar(
exit = slideOutVertically(targetOffsetY = { -it }) + fadeOut()
) {
val horizontalPadding by animateDpAsState(
if (searchBarActive) 0.dp else DEFAULT_PADDING,
if (searchBarExpanded) 0.dp else DEFAULT_PADDING,
label = "Map search bar horizontal padding"
)

MapSearchBar(
query = query,
onQueryChange = onQueryChange,
mapTitle = mapTitle,
active = searchBarActive,
onActiveChange = { searchBarActive = it },
expanded = searchBarExpanded,
onExpandedChange = { searchBarExpanded = it },
results = searchResults,
onResultClick = onResultClick,
onMenuClick = onMenuClick,
Expand Down
20 changes: 10 additions & 10 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[versions]

kotlin = "2.0.20"
kspPlugin = "2.0.20-1.0.24"
hilt = "2.52"
lifecycle = "2.8.4"
room = "2.6.1"
kotlin = "2.1.20"
kspPlugin = "2.1.20-2.0.0"
hilt = "2.56.2"
lifecycle = "2.8.7"
room = "2.7.0"


[libraries]
Expand All @@ -20,15 +20,15 @@ androidx-room-compiler = { group = "androidx.room", name = "room-compiler", vers
google-dagger-hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
google-dagger-hiltCompiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }

androidx-compose-bom = "androidx.compose:compose-bom:2024.08.00"
androidx-compose-bom = "androidx.compose:compose-bom:2025.04.00"
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
androidx-compose-ui = { module = "androidx.compose.ui:ui" }
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }

androidx-core-ktx = "androidx.core:core-ktx:1.13.1"
androidx-activity-compose = "androidx.activity:activity-compose:1.9.1"
plrapps-mapcompose = "ovh.plrapps:mapcompose:2.12.6"
androidx-core-ktx = "androidx.core:core-ktx:1.16.0"
androidx-activity-compose = "androidx.activity:activity-compose:1.10.1"
plrapps-mapcompose = "ovh.plrapps:mapcompose:2.16.2"

junit = "junit:junit:4.13.2"
androidx-test-runner = "androidx.test:runner:1.6.2"
Expand All @@ -38,7 +38,7 @@ androidx-test-extJunit = "androidx.test.ext:junit:1.2.1"

[plugins]

android-application = { id = "com.android.application", version = "8.5.2" }
android-application = { id = "com.android.application", version = "8.9.1" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
jetbrains-kotlin-plugin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
google-dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Tue Aug 27 22:36:14 CEST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading