Skip to content
This repository has been archived by the owner on Sep 23, 2024. It is now read-only.

Commit

Permalink
Fixing rotation issue (#584)
Browse files Browse the repository at this point in the history
Fixing issue where rotating the screen would navigate to the initial
screen

---------

Co-authored-by: John Oberhauser <j.git-global@obez.io>
  • Loading branch information
JohnOberhauser and John Oberhauser committed Jun 13, 2024
1 parent f524a97 commit 5db7422
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 104 deletions.
55 changes: 55 additions & 0 deletions app/src/main/kotlin/social/firefly/IntentHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package social.firefly

import android.content.Intent
import android.net.Uri
import android.os.Parcelable
import social.firefly.core.datastore.UserPreferencesDatastoreManager
import social.firefly.core.navigation.Event
import social.firefly.core.navigation.EventRelay
import social.firefly.core.share.ShareInfo

class IntentHandler(
private val eventRelay: EventRelay,
private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager,
) {

fun handleIntent(intent: Intent) {
if (!userPreferencesDatastoreManager.isLoggedInToAtLeastOneAccount) return
when {
intent.action == Intent.ACTION_SEND -> {
when {
intent.type == "text/plain" -> {
handleSendTextIntentReceived(intent)
}
intent.type?.contains("image") == true -> {
handleSendImageIntentReceived(intent)
}
intent.type?.contains("video") == true -> {
handleSendVideoIntentReceived(intent)
}
}
}
}
}

private fun handleSendTextIntentReceived(intent: Intent) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { sharedText ->
ShareInfo.sharedText = sharedText
eventRelay.emitEvent(Event.ChooseAccountForSharing)
}
}

private fun handleSendImageIntentReceived(intent: Intent) {
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { sharedUri ->
ShareInfo.sharedImageUri = sharedUri
eventRelay.emitEvent(Event.ChooseAccountForSharing)
}
}

private fun handleSendVideoIntentReceived(intent: Intent) {
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { sharedUri ->
ShareInfo.sharedVideoUri = sharedUri
eventRelay.emitEvent(Event.ChooseAccountForSharing)
}
}
}
15 changes: 3 additions & 12 deletions app/src/main/kotlin/social/firefly/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.core.content.ContextCompat
Expand All @@ -21,14 +20,14 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.annotation.KoinExperimentalAPI
import social.firefly.core.analytics.AppAnalytics
import social.firefly.core.designsystem.theme.FfTheme
import social.firefly.core.designsystem.theme.ThemeOption
import social.firefly.core.ui.common.FfSurface
import social.firefly.core.workmanager.DatabasePurgeWorker
import social.firefly.ui.MainActivityScreen

class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModel()
private val analytics: AppAnalytics by inject()
private val intentHandler: IntentHandler by inject()

private val notificationsRequestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
Expand All @@ -40,9 +39,7 @@ class MainActivity : ComponentActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false)

setContent {
val themeOption by viewModel.themeOption.collectAsStateWithLifecycle(
initialValue = ThemeOption.SYSTEM
)
val themeOption by viewModel.themeOption.collectAsStateWithLifecycle()

FfTheme(
themeOption = themeOption,
Expand All @@ -53,12 +50,6 @@ class MainActivity : ComponentActivity() {
}
}
}

// initialize the view model in the setContent block so that initialize is called
// again when the layout inspector starts
LaunchedEffect(Unit) {
viewModel.initialize(intent)
}
}

DatabasePurgeWorker.setupPurgeWork(this, lifecycleScope)
Expand All @@ -77,7 +68,7 @@ class MainActivity : ComponentActivity() {

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
viewModel.handleIntent(intent)
intentHandler.handleIntent(intent)
}

private fun askNotificationPermission() {
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/kotlin/social/firefly/MainModule.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package social.firefly

import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
import social.firefly.core.analytics.analyticsModule
import social.firefly.core.datastore.dataStoreModule
import social.firefly.core.navigation.navigationModule
import social.firefly.core.usecase.mastodon.mastodonUsecaseModule
import social.firefly.splash.SplashViewModel

val mainModule = module {
includes(
Expand All @@ -16,4 +18,6 @@ val mainModule = module {
)

viewModelOf(::MainViewModel)
viewModelOf(::SplashViewModel)
singleOf(::IntentHandler)
}
83 changes: 7 additions & 76 deletions app/src/main/kotlin/social/firefly/MainViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
package social.firefly

import android.content.Intent
import android.net.Uri
import android.os.Parcelable
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.stateIn
import social.firefly.core.datastore.AppPreferences
import social.firefly.core.datastore.AppPreferencesDatastore
import social.firefly.core.datastore.UserPreferencesDatastoreManager
import social.firefly.core.designsystem.theme.ThemeOption
import social.firefly.core.navigation.Event
import social.firefly.core.navigation.EventRelay
import social.firefly.core.navigation.NavigationDestination
import social.firefly.core.navigation.usecases.NavigateTo
import social.firefly.core.repository.mastodon.TimelineRepository
import social.firefly.core.share.ShareInfo
import social.firefly.core.usecase.mastodon.auth.UpdateAllLoggedInAccounts
import social.firefly.ui.AppState

class MainViewModel(
private val navigateTo: NavigateTo,
private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager,
private val timelineRepository: TimelineRepository,
private val eventRelay: EventRelay,
private val updateAllLoggedInAccounts: UpdateAllLoggedInAccounts,
appPreferencesDatastore: AppPreferencesDatastore,
) : ViewModel() {

Expand All @@ -37,62 +21,9 @@ class MainViewModel(
AppPreferences.ThemeType.DARK -> ThemeOption.DARK
else -> ThemeOption.SYSTEM
}
}

fun initialize(intent: Intent) {
viewModelScope.launch {
// Do any cleanup necessary before navigating away from the splash screen
timelineRepository.deleteHomeTimeline()

AppState.navigationCollectionCompletable.await()

if (userPreferencesDatastoreManager.isLoggedInToAtLeastOneAccount) {
navigateTo(NavigationDestination.Tabs)
handleIntent(intent)
updateAllLoggedInAccounts()
} else {
navigateTo(NavigationDestination.Auth)
}
}
}

fun handleIntent(intent: Intent) {
if (!userPreferencesDatastoreManager.isLoggedInToAtLeastOneAccount) return
when {
intent.action == Intent.ACTION_SEND -> {
when {
intent.type == "text/plain" -> {
handleSendTextIntentReceived(intent)
}
intent.type?.contains("image") == true -> {
handleSendImageIntentReceived(intent)
}
intent.type?.contains("video") == true -> {
handleSendVideoIntentReceived(intent)
}
}
}
}
}

private fun handleSendTextIntentReceived(intent: Intent) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { sharedText ->
ShareInfo.sharedText = sharedText
eventRelay.emitEvent(Event.ChooseAccountForSharing)
}
}

private fun handleSendImageIntentReceived(intent: Intent) {
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { sharedUri ->
ShareInfo.sharedImageUri = sharedUri
eventRelay.emitEvent(Event.ChooseAccountForSharing)
}
}

private fun handleSendVideoIntentReceived(intent: Intent) {
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { sharedUri ->
ShareInfo.sharedVideoUri = sharedUri
eventRelay.emitEvent(Event.ChooseAccountForSharing)
}
}
}.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = ThemeOption.SYSTEM,
)
}
7 changes: 2 additions & 5 deletions app/src/main/kotlin/social/firefly/navigation/MainNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package social.firefly.navigation

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import social.firefly.common.utils.ffFadeIn
import social.firefly.common.utils.ffFadeOut
import social.firefly.feature.account.accountScreen
Expand All @@ -21,6 +19,7 @@ import social.firefly.feature.settings.settingsFlow
import social.firefly.feature.thread.threadScreen
import social.firefly.feature.post.newPostScreen
import social.firefly.feature.search.searchScreen
import social.firefly.splash.splashScreen
import social.firefly.ui.AppState
import social.firefly.ui.bottombar.Routes
import social.firefly.ui.bottombar.bottomTabScreen
Expand Down Expand Up @@ -58,6 +57,4 @@ fun MainNavHost(
}
}

fun NavGraphBuilder.splashScreen() {
composable(route = Routes.SPLASH) {}
}

26 changes: 26 additions & 0 deletions app/src/main/kotlin/social/firefly/splash/SplashScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package social.firefly.splash

import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import org.koin.androidx.compose.koinViewModel
import social.firefly.ui.bottombar.Routes

fun NavGraphBuilder.splashScreen() {
composable(route = Routes.SPLASH) {
SplashScreen()
}
}

@Composable
private fun SplashScreen(
viewModel: SplashViewModel = koinViewModel()
) {
val activity = LocalContext.current as? ComponentActivity
LaunchedEffect(Unit) {
viewModel.initialize(activity?.intent)
}
}
39 changes: 39 additions & 0 deletions app/src/main/kotlin/social/firefly/splash/SplashViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package social.firefly.splash

import android.content.Intent
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import social.firefly.IntentHandler
import social.firefly.core.datastore.UserPreferencesDatastoreManager
import social.firefly.core.navigation.NavigationDestination
import social.firefly.core.navigation.usecases.NavigateTo
import social.firefly.core.repository.mastodon.TimelineRepository
import social.firefly.core.usecase.mastodon.auth.UpdateAllLoggedInAccounts
import social.firefly.ui.AppState

class SplashViewModel(
private val navigateTo: NavigateTo,
private val userPreferencesDatastoreManager: UserPreferencesDatastoreManager,
private val timelineRepository: TimelineRepository,
private val updateAllLoggedInAccounts: UpdateAllLoggedInAccounts,
private val intentHandler: IntentHandler,
) : ViewModel() {

fun initialize(intent: Intent?) {
viewModelScope.launch {
// Do any cleanup necessary before navigating away from the splash screen
timelineRepository.deleteHomeTimeline()

AppState.navigationCollectionCompletable.await()

if (userPreferencesDatastoreManager.isLoggedInToAtLeastOneAccount) {
navigateTo(NavigationDestination.Tabs)
intent?.let { intentHandler.handleIntent(intent) }
updateAllLoggedInAccounts()
} else {
navigateTo(NavigationDestination.Auth)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package social.firefly.core.ui.htmlcontent

import android.graphics.Typeface
import android.os.Build
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.widget.TextView
Expand Down Expand Up @@ -53,16 +52,14 @@ fun HtmlContent(
TextView(context).apply {
textSize = textStyle.fontSize.value
setTextColor(textColor.toArgb())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
typeface =
textStyle.fontWeight?.let { fontWeight ->
Typeface.create(
typeface,
fontWeight.weight,
false,
)
}
}
typeface =
textStyle.fontWeight?.let { fontWeight ->
Typeface.create(
typeface,
fontWeight.weight,
false,
)
}

if (clickableLinks) {
movementMethod = HtmlContentMovementMethod
Expand Down

0 comments on commit 5db7422

Please sign in to comment.