Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First steps in Jetpack Compose (reimplement parts of the user screen) #5607

Merged
merged 35 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4dfe3f3
add compose dependencies
westnordost Apr 18, 2024
a29bee7
add basic compose theme
westnordost Apr 18, 2024
c43c97b
rather use other variant of defining per-theme colors
westnordost Apr 18, 2024
099fb18
kotlin up
westnordost Apr 18, 2024
84b6577
composable for DatesActiveDrawable
westnordost Apr 19, 2024
a332c1e
lint
westnordost Apr 19, 2024
54abc0c
add preview for on DatesActive
westnordost Apr 19, 2024
695a7f8
follow guideline that custom composables should always hand down the …
westnordost Apr 19, 2024
9148c5d
break old laurel wreath
westnordost Apr 19, 2024
40ad1c6
move into normal directory
westnordost Apr 20, 2024
ff2c3bf
implement profile screen
westnordost Apr 23, 2024
78603b7
Merge branch 'master' into compose1
westnordost Apr 24, 2024
d949acd
rename styles to be similar to equivalent m3 styles for easier migrat…
westnordost Apr 24, 2024
77e4d29
even smoother laurel wreath growing animation
westnordost Apr 24, 2024
01d5d4a
implement links in compose
westnordost Apr 25, 2024
fc1620e
remove todo
westnordost Apr 25, 2024
439ec2b
fix layout for land layout
westnordost Apr 26, 2024
ea0183e
implement achievements screen
westnordost Apr 26, 2024
b5334e0
create new achievements dialog (wip)
westnordost Apr 27, 2024
bd545b3
slower shine animation
westnordost Apr 27, 2024
e94afcf
Merge branch 'master' into compose1
westnordost Apr 28, 2024
4de00d6
add some max width for the dates active table
westnordost Apr 29, 2024
cdcc926
actually show dialog
westnordost Apr 29, 2024
de860d5
put composable that decides whether to show it as portrait or landsca…
westnordost Apr 29, 2024
f3757da
rewire achievements dialog
westnordost Apr 29, 2024
7c4635f
disable minify for debug builds
westnordost Apr 29, 2024
3b59730
no shine animation in achievements screen
westnordost Apr 29, 2024
77afc13
remove unused code
westnordost Apr 29, 2024
690ac2d
implement RTL support
westnordost Apr 29, 2024
95d8a93
shorten it a bit
westnordost Apr 29, 2024
733e3e2
formatting
westnordost Apr 29, 2024
78f854e
put LazyAchievementsGrid into own file
westnordost Apr 29, 2024
87b75f9
refine some colors
westnordost Apr 29, 2024
afb3da5
add todos that should be revisited once compose animation 1.7 is stable
westnordost May 4, 2024
b085594
Merge branch 'master' into compose1
westnordost May 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 18 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.util.Properties
plugins {
id("com.android.application")
kotlin("android")
kotlin("plugin.serialization") version "1.9.22"
kotlin("plugin.serialization") version "1.9.23"
}

android {
Expand Down Expand Up @@ -52,6 +52,7 @@ android {
buildConfigField("boolean", "IS_GOOGLE_PLAY", "false")
}
getByName("debug") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
applicationIdSuffix = ".debug"
buildConfigField("boolean", "IS_GOOGLE_PLAY", "false")
Expand All @@ -65,6 +66,11 @@ android {
buildFeatures {
viewBinding = true
buildConfig = true
compose = true
}

composeOptions {
kotlinCompilerExtensionVersion = "1.5.12"
}

bundle {
Expand Down Expand Up @@ -140,7 +146,18 @@ dependencies {
implementation("androidx.viewpager:viewpager:1.0.0")
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")

// Jetpack Compose
val composeBom = platform("androidx.compose:compose-bom:2024.04.01")
implementation(composeBom)
androidTestImplementation(composeBom)
implementation("androidx.compose.material:material")
// Jetpack Compose Previews
implementation("androidx.compose.ui:ui-tooling-preview")
debugImplementation("androidx.compose.ui:ui-tooling")


implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
// photos
implementation("androidx.exifinterface:exifinterface:1.3.7")

Expand Down
3 changes: 0 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,6 @@
<activity
android:name="de.westnordost.streetcomplete.screens.settings.debug.ShowQuestFormsActivity"
android:configChanges="orientation|screenSize|uiMode" />
<activity
android:name="de.westnordost.streetcomplete.screens.settings.debug.ShowLinksActivity"
android:configChanges="orientation|screenSize|uiMode" />
<activity
android:name="de.westnordost.streetcomplete.screens.user.UserActivity"
android:screenOrientation="portrait"
Expand Down
5 changes: 0 additions & 5 deletions app/src/main/java/de/westnordost/streetcomplete/Prefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ object Prefs {
const val ACTIVE_DATES_RANGE = "active_days_range"
const val IS_SYNCHRONIZING_STATISTICS = "is_synchronizing_statistics"

const val LAST_SHOWN_USER_GLOBAL_RANK = "last_shown.user_global_rank"
const val LAST_SHOWN_USER_LOCAL_RANK = "last_shown.user_local_rank"
const val LAST_SHOWN_USER_GLOBAL_RANK_CURRENT_WEEK = "last_shown.user_global_rank_current_week"
const val LAST_SHOWN_USER_LOCAL_RANK_CURRENT_WEEK = "last_shown.user_local_rank_current_week"

enum class Autosync {
ON,
WIFI,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ private val typeAliases = listOf(
"ShopsOverlay" to PlacesOverlay::class.simpleName!!,
)

private val links = listOf(
/** this is only public so that it can be previewed in compose */
val links = listOf(

/* ---------------------------------------- Intro ----------------------------------------*/
Link(
Expand Down Expand Up @@ -495,7 +496,8 @@ private val links = listOf(

private val linksById = links.associateBy { it.id }

private val achievements = listOf(
/** this is only public so that it can be previewed in compose */
val achievements = listOf(

Achievement(
"first_edit",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class AboutFragment : TwoPaneListFragment(), HasTitle {
binding.imageView.setImageResource(with.iconId)
binding.textView.text = with.title
binding.root.setOnClickListener { openUri(with.url) }
TextViewCompat.setTextAppearance(binding.textView, R.style.TextAppearance_Title)
TextViewCompat.setTextAppearance(binding.textView, R.style.TextAppearance_TitleLarge)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package de.westnordost.streetcomplete.screens.main.messages

import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.fragment.app.Fragment
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.messages.Message
Expand All @@ -10,15 +15,33 @@ import de.westnordost.streetcomplete.data.messages.OsmUnreadMessagesMessage
import de.westnordost.streetcomplete.data.messages.QuestSelectionHintMessage
import de.westnordost.streetcomplete.screens.about.WhatsNewDialog
import de.westnordost.streetcomplete.screens.settings.SettingsActivity
import de.westnordost.streetcomplete.screens.user.achievements.AchievementInfoFragment
import de.westnordost.streetcomplete.screens.user.achievements.AchievementDialog
import de.westnordost.streetcomplete.ui.util.composableContent
import kotlinx.coroutines.flow.MutableStateFlow

/** A fragment that contains any fragments that would show messages.
* Usually, messages are shown as dialogs, however there is currently one exception which
* makes this necessary as a fragment */
class MessagesContainerFragment : Fragment(R.layout.fragment_messages_container) {
class MessagesContainerFragment : Fragment() {

private val shownMessage = MutableStateFlow<Message?>(null)

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = composableContent {
val message by shownMessage.collectAsState()

val msg = message
if (msg is NewAchievementMessage) {
AchievementDialog(
msg.achievement,
msg.level,
onDismissRequest = { shownMessage.value = null }
)
}
}

fun showMessage(message: Message) {
val ctx = context ?: return
shownMessage.value = message
when (message) {
is OsmUnreadMessagesMessage -> {
OsmUnreadMessagesFragment
Expand All @@ -30,8 +53,7 @@ class MessagesContainerFragment : Fragment(R.layout.fragment_messages_container)
.show()
}
is NewAchievementMessage -> {
val f: Fragment = childFragmentManager.findFragmentById(R.id.achievement_info_fragment)!!
(f as AchievementInfoFragment).showNew(message.achievement, message.level)
shownMessage.value = message
}
is QuestSelectionHintMessage -> {
AlertDialog.Builder(ctx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.databinding.DialogDeleteCacheBinding
import de.westnordost.streetcomplete.screens.HasTitle
import de.westnordost.streetcomplete.screens.TwoPaneListFragment
import de.westnordost.streetcomplete.screens.settings.debug.ShowLinksActivity
import de.westnordost.streetcomplete.screens.settings.debug.ShowQuestFormsActivity
import de.westnordost.streetcomplete.util.ktx.format
import de.westnordost.streetcomplete.util.ktx.observe
Expand Down Expand Up @@ -70,11 +69,6 @@ class SettingsFragment : TwoPaneListFragment(), HasTitle {
startActivity(Intent(context, ShowQuestFormsActivity::class.java))
true
}

findPreference<Preference>("debug.links")?.setOnPreferenceClickListener {
startActivity(Intent(context, ShowLinksActivity::class.java))
true
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package de.westnordost.streetcomplete.screens.settings

import de.westnordost.streetcomplete.screens.settings.debug.ShowLinksActivityViewModel
import de.westnordost.streetcomplete.screens.settings.debug.ShowLinksActivityViewModelImpl
import de.westnordost.streetcomplete.screens.settings.debug.ShowQuestFormsViewModel
import de.westnordost.streetcomplete.screens.settings.debug.ShowQuestFormsViewModelImpl
import de.westnordost.streetcomplete.screens.settings.questselection.QuestPresetsViewModel
Expand All @@ -19,5 +17,4 @@ val settingsModule = module {
viewModel<QuestSelectionViewModel> { QuestSelectionViewModelImpl(get(), get(), get(), get(), get(named("CountryBoundariesLazy")), get()) }
viewModel<QuestPresetsViewModel> { QuestPresetsViewModelImpl(get(), get(), get(), get()) }
viewModel<ShowQuestFormsViewModel> { ShowQuestFormsViewModelImpl(get(), get()) }
viewModel<ShowLinksActivityViewModel> { ShowLinksActivityViewModelImpl(get(named("Links"))) }
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package de.westnordost.streetcomplete.screens.user

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import de.westnordost.streetcomplete.ui.theme.hint
import de.westnordost.streetcomplete.ui.theme.titleLarge

@Composable
fun CenteredLargeTitleHint(text: String, modifier: Modifier = Modifier) {
Box(
modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
text = text,
modifier = Modifier.padding(64.dp),
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colors.hint,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.osm.edits.EditType
import de.westnordost.streetcomplete.data.user.achievements.Achievement
import de.westnordost.streetcomplete.screens.FragmentContainerActivity
import de.westnordost.streetcomplete.screens.HasTitle
import de.westnordost.streetcomplete.screens.user.achievements.AchievementInfoFragment
import de.westnordost.streetcomplete.screens.user.achievements.AchievementsFragment
import de.westnordost.streetcomplete.screens.user.login.LoginFragment
import de.westnordost.streetcomplete.screens.user.statistics.CountryInfoFragment
import de.westnordost.streetcomplete.screens.user.statistics.EditStatisticsFragment
Expand All @@ -24,11 +21,10 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
* This activity coordinates quite a number of fragments, which all call back to this one. In order
* of appearance:
* The LoginFragment, the UserFragment (which contains the viewpager with more
* fragments) and the "fake" dialogs AchievementInfoFragment and QuestTypeInfoFragment.
* fragments) and the "fake" dialog QuestTypeInfoFragment.
* */
class UserActivity :
FragmentContainerActivity(R.layout.activity_user),
AchievementsFragment.Listener,
EditStatisticsFragment.Listener {

private val viewModel by viewModel<UserViewModel>()
Expand All @@ -39,9 +35,6 @@ class UserActivity :
private val editTypeDetailsFragment get() =
supportFragmentManager.findFragmentById(R.id.editTypeDetailsFragment) as EditTypeInfoFragment?

private val achievementDetailsFragment get() =
supportFragmentManager.findFragmentById(R.id.achievementDetailsFragment) as AchievementInfoFragment?

private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentStarted(fragmentManager: FragmentManager, fragment: Fragment) {
if (fragment.id == R.id.fragment_container && fragment is HasTitle) {
Expand Down Expand Up @@ -86,12 +79,6 @@ class UserActivity :
}
}

/* ---------------------------- AchievementsFragment.Listener ------------------------------- */

override fun onClickedAchievement(achievement: Achievement, level: Int, achievementBubbleView: View) {
achievementDetailsFragment?.show(achievement, level, achievementBubbleView)
}

/* --------------------------- QuestStatisticsFragment.Listener ----------------------------- */

override fun onClickedEditType(editType: EditType, editCount: Int, questBubbleView: View) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import org.koin.dsl.module

val userScreenModule = module {
factory<ProfileViewModel> { ProfileViewModelImpl(
get(), get(), get(), get(), get(), get(), get(named("AvatarsCacheDirectory")), get()
get(), get(), get(), get(), get(), get(), get(named("AvatarsCacheDirectory"))
) }

factory<LoginViewModel> { LoginViewModelImpl(get(), get(), get(), get()) }
Expand Down