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
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ android {
applicationId = "com.anod.appwatcher"
minSdk = 31
targetSdk = 36
versionCode = 17000
versionCode = 17001
versionName = "1.7.0"
}

Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/com/anod/appwatcher/AppWatcherActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ class AppWatcherActivity : BaseComposeActivity(), KoinComponent {
val wideLayout by foldableDevice.layout.collectAsState()
HistoryListScreenScene(
wideLayout = wideLayout,
navigateBack = { backStack.removeLastOrNull() }
navigateBack = { backStack.removeLastOrNull() },
navigateTo = { backStack.add(it) }
)
}
entry<SceneNavKey.UserLog>(
Expand Down Expand Up @@ -240,6 +241,7 @@ class AppWatcherActivity : BaseComposeActivity(), KoinComponent {
InstalledListScreenScene(
showAction = key.importMode,
navigateBack = { backStack.removeLastOrNull() },
navigateTo = { backStack.add(it) }
)
}
entry<SceneNavKey.WishList>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContract
import info.anodsplace.framework.content.ScreenCommonAction
import info.anodsplace.framework.content.ShowDialogData

sealed interface AccountSelectionResult {
class Success(val account: Account) : AccountSelectionResult
data object Canceled : AccountSelectionResult
class Error(val errorMessage: String) : AccountSelectionResult
}

data class AccountSelectionDialogData(
val currentAccount: Account?
) : ShowDialogData

fun showAccountSelectionAction(
currentAccount: Account?
): ScreenCommonAction = ScreenCommonAction.ShowDialog(
AccountSelectionDialogData(currentAccount)
)

class AccountSelectionRequest : ActivityResultContract<Account?, AccountSelectionResult>() {

override fun createIntent(context: Context, input: Account?): Intent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ private fun DetailsScreenContent(
val result =
snackBarHostState.showSnackbar(TagSnackbar.Visuals(action.appInfo, context))
if (result == SnackbarResult.ActionPerformed) {
showTagList = action.appInfo
showTagList = action.appInfo.app
}
}

Expand Down
17 changes: 10 additions & 7 deletions app/src/main/java/com/anod/appwatcher/details/DetailsViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.annotation.StringRes
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.core.net.toUri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
Expand All @@ -26,6 +27,7 @@ import com.anod.appwatcher.database.AppsDatabase
import com.anod.appwatcher.database.entities.App
import com.anod.appwatcher.database.entities.AppChange
import com.anod.appwatcher.database.entities.Tag
import com.anod.appwatcher.tags.TagSnackbarAppInfo
import com.anod.appwatcher.utils.AppIconLoader
import com.anod.appwatcher.utils.BaseFlowViewModel
import com.anod.appwatcher.utils.androidVersions
Expand All @@ -36,8 +38,9 @@ import finsky.api.DfeApi
import finsky.api.Document
import finsky.api.toDocument
import info.anodsplace.applog.AppLog
import info.anodsplace.framework.content.ShowToastActionDefaults
import info.anodsplace.framework.content.InstalledApps
import info.anodsplace.framework.content.ShowToastActionDefaults
import info.anodsplace.framework.content.StartActivityAction
import info.anodsplace.framework.content.forAppInfo
import info.anodsplace.framework.content.forUninstall
import info.anodsplace.framework.text.Html
Expand All @@ -52,8 +55,6 @@ import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.net.URLEncoder
import java.util.Locale
import androidx.core.net.toUri
import info.anodsplace.framework.content.StartActivityAction

typealias TagMenuItem = Pair<Tag, Boolean>

Expand Down Expand Up @@ -115,7 +116,7 @@ data class AppVersionInfo(

sealed interface DetailsAction {
class StartActivity(override val intent: Intent) : DetailsAction, StartActivityAction
class ShowTagSnackbar(val appInfo: App) : DetailsAction
class ShowTagSnackbar(val appInfo: TagSnackbarAppInfo) : DetailsAction
object Dismiss : DetailsAction
class Share(val app: App, val recentChange: AppChange) : DetailsAction
class ShowToast(@param:StringRes override val resId: Int) : ShowToastActionDefaults(resId), DetailsAction
Expand Down Expand Up @@ -405,9 +406,11 @@ class DetailsViewModel(
AppListTable.ERROR_ALREADY_ADDED -> emitAction(action = showToastAction(resId = R.string.app_already_added))
else -> emitAction(
DetailsAction.ShowTagSnackbar(
appInfo = App(
document!!,
uploadDateParserCache
appInfo = TagSnackbarAppInfo(
app = App(
document!!,
uploadDateParserCache
)
)
)
)
Expand Down
42 changes: 14 additions & 28 deletions app/src/main/java/com/anod/appwatcher/history/HistoryListScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
Expand All @@ -32,27 +31,28 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.NavKey
import androidx.paging.LoadState
import androidx.paging.PagingData
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import com.anod.appwatcher.R
import com.anod.appwatcher.compose.SearchTopBar
import com.anod.appwatcher.database.entities.App
import com.anod.appwatcher.navigation.SceneNavKey
import com.anod.appwatcher.navigation.asNavKey
import com.anod.appwatcher.search.ListItem
import com.anod.appwatcher.search.MarketAppItem
import com.anod.appwatcher.search.RetryButton
import com.anod.appwatcher.tags.TagSelectionDialog
import com.anod.appwatcher.tags.TagSnackbar
import com.anod.appwatcher.utils.AppIconLoader
import info.anodsplace.framework.app.FoldableDeviceLayout
import info.anodsplace.framework.content.ScreenCommonAction
import info.anodsplace.framework.content.onScreenCommonAction
import kotlinx.coroutines.flow.Flow
import org.koin.java.KoinJavaComponent

@Composable
fun HistoryListScreenScene(wideLayout: FoldableDeviceLayout, navigateBack: () -> Unit) {
fun HistoryListScreenScene(wideLayout: FoldableDeviceLayout, navigateBack: () -> Unit, navigateTo: (NavKey) -> Unit) {
val viewModel: HistoryListViewModel = viewModel(
factory = HistoryListViewModel.Factory(
wideLayout = wideLayout,
Expand All @@ -65,7 +65,8 @@ fun HistoryListScreenScene(wideLayout: FoldableDeviceLayout, navigateBack: () ->
onEvent = viewModel::handleEvent,
pagingDataFlow = viewModel.pagingData,
viewActions = viewModel.viewActions,
navigateBack = navigateBack
navigateBack = navigateBack,
navigateTo = navigateTo,
)
}

Expand All @@ -74,8 +75,9 @@ fun HistoryListScreen(
screenState: HistoryListState,
pagingDataFlow: Flow<PagingData<ListItem>>,
onEvent: (HistoryListEvent) -> Unit,
viewActions: Flow<HistoryListAction>,
viewActions: Flow<ScreenCommonAction>,
navigateBack: () -> Unit = {},
navigateTo: (NavKey) -> Unit = {},
appIconLoader: AppIconLoader = KoinJavaComponent.getKoin().get(),
) {
val context = LocalContext.current
Expand Down Expand Up @@ -134,31 +136,15 @@ fun HistoryListScreen(
}
}

var showTagList: App? by remember { mutableStateOf(null) }
LaunchedEffect(key1 = viewActions) {
viewActions.collect { action ->
when (action) {
is HistoryListAction.ShowTagSnackbar -> {
val result = snackbarHostState.showSnackbar(TagSnackbar.Visuals(action.info, context))
if (result == SnackbarResult.ActionPerformed) {
showTagList = action.info
}
}

HistoryListAction.OnBackPress -> navigateBack()
}
context.onScreenCommonAction(
action = action,
navigateBack = navigateBack,
navigateTo = { navigateTo(it.asNavKey) },
)
}
}

if (showTagList != null) {
TagSelectionDialog(
appId = showTagList!!.appId,
appTitle = showTagList!!.title,
onDismissRequest = {
showTagList = null
}
)
}
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.anod.appwatcher.accounts.toAndroidAccount
import com.anod.appwatcher.database.AppsDatabase
import com.anod.appwatcher.database.entities.App
import com.anod.appwatcher.database.observePackages
import com.anod.appwatcher.navigation.SceneNavKey
import com.anod.appwatcher.search.ListItem
import com.anod.appwatcher.search.updateRowId
import com.anod.appwatcher.utils.BaseFlowViewModel
Expand All @@ -26,6 +27,7 @@ import finsky.api.FilterComposite
import finsky.api.FilterPredicate
import info.anodsplace.framework.app.FoldableDeviceLayout
import info.anodsplace.framework.content.InstalledApps
import info.anodsplace.framework.content.ScreenCommonAction
import info.anodsplace.playstore.AppNameFilter
import info.anodsplace.playstore.PaidHistoryFilter
import kotlinx.coroutines.flow.Flow
Expand All @@ -42,22 +44,16 @@ data class HistoryListState(
val authToken: String = "",
val nameFilter: String = "",
val wideLayout: FoldableDeviceLayout = FoldableDeviceLayout(),
val selectedApp: App? = null,
)

sealed interface HistoryListAction {
data object OnBackPress : HistoryListAction
class ShowTagSnackbar(val info: App) : HistoryListAction
}

sealed interface HistoryListEvent {
data object OnBackPress : HistoryListEvent
class OnNameFilter(val query: String) : HistoryListEvent
class SelectApp(val app: App?) : HistoryListEvent
class SelectApp(val app: App) : HistoryListEvent
class SetWideLayout(val wideLayout: FoldableDeviceLayout) : HistoryListEvent
}

class HistoryListViewModel(wideLayout: FoldableDeviceLayout) : BaseFlowViewModel<HistoryListState, HistoryListEvent, HistoryListAction>(), KoinComponent {
class HistoryListViewModel(wideLayout: FoldableDeviceLayout) : BaseFlowViewModel<HistoryListState, HistoryListEvent, ScreenCommonAction>(), KoinComponent {

class Factory(
private val wideLayout: FoldableDeviceLayout
Expand Down Expand Up @@ -117,11 +113,9 @@ class HistoryListViewModel(wideLayout: FoldableDeviceLayout) : BaseFlowViewModel

override fun handleEvent(event: HistoryListEvent) {
when (event) {
HistoryListEvent.OnBackPress -> emitAction(HistoryListAction.OnBackPress)
HistoryListEvent.OnBackPress -> emitAction(ScreenCommonAction.NavigateBack)
is HistoryListEvent.OnNameFilter -> viewState = viewState.copy(nameFilter = event.query)
is HistoryListEvent.SelectApp -> {
viewState = viewState.copy(selectedApp = event.app)
}
is HistoryListEvent.SelectApp -> emitAction(ScreenCommonAction.NavigateTo(SceneNavKey.AppDetails(event.app)))
is HistoryListEvent.SetWideLayout -> {
viewState = viewState.copy(wideLayout = event.wideLayout)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.NavKey
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import com.anod.appwatcher.R
import com.anod.appwatcher.model.Filters
import com.anod.appwatcher.navigation.SceneNavKey
import com.anod.appwatcher.navigation.asNavKey
import com.anod.appwatcher.preferences.Preferences
import com.anod.appwatcher.watchlist.WatchListPage
import com.anod.appwatcher.watchlist.WatchListPagingSource
Expand All @@ -35,7 +37,8 @@ import info.anodsplace.framework.content.onScreenCommonAction
@Composable
fun InstalledListScreenScene(
showAction: Boolean,
navigateBack: () -> Unit
navigateBack: () -> Unit,
navigateTo: (NavKey) -> Unit
) {
val context = LocalContext.current
val viewModel: InstalledListViewModel = viewModel(
Expand Down Expand Up @@ -64,7 +67,7 @@ fun InstalledListScreenScene(

LaunchedEffect(true) {
viewModel.viewActions.collect { action ->
context.onScreenCommonAction(action, navigateBack)
context.onScreenCommonAction(action, navigateBack, navigateTo = { navigateTo(it.asNavKey) })
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.anod.appwatcher.accounts.AuthTokenBlocking
import com.anod.appwatcher.accounts.CheckTokenError
import com.anod.appwatcher.accounts.CheckTokenResult
import com.anod.appwatcher.accounts.toAndroidAccount
import com.anod.appwatcher.database.entities.App
import com.anod.appwatcher.navigation.SceneNavKey
import com.anod.appwatcher.utils.BaseFlowViewModel
import com.anod.appwatcher.utils.PackageChangedReceiver
import com.anod.appwatcher.utils.SelectionState
Expand All @@ -41,7 +41,6 @@ data class InstalledListState(
val selectionMode: Boolean = false,
val titleFilter: String = "",
val wideLayout: FoldableDeviceLayout = FoldableDeviceLayout(isWideLayout = false, hinge = Rect()),
val selectedApp: App? = null,
val importStatus: ImportStatus = ImportStatus.NotStarted,
val selection: SelectionState = SelectionState(),
val packageChanged: String = "",
Expand All @@ -57,7 +56,6 @@ sealed interface InstalledListEvent {
class ChangeSort(val sortId: Int) : InstalledListEvent
class SwitchImportMode(val selectionMode: Boolean) : InstalledListEvent
class SetSelection(val all: Boolean) : InstalledListEvent
class SelectApp(val app: App?) : InstalledListEvent
class AuthTokenError(val error: CheckTokenError) : InstalledListEvent
object Import : InstalledListEvent
}
Expand Down Expand Up @@ -114,7 +112,7 @@ class InstalledListViewModel(
viewState = viewState.copy(sortId = event.sortId)
}
is InstalledListEvent.FilterByTitle -> viewState = viewState.copy(titleFilter = event.query)
InstalledListEvent.OnBackPressed -> onBackPressed()
InstalledListEvent.OnBackPressed -> emitAction(ScreenCommonAction.NavigateBack)
is InstalledListEvent.SwitchImportMode -> {
switchImportMode(event.selectionMode)
}
Expand All @@ -123,10 +121,6 @@ class InstalledListViewModel(
viewState = viewState.copy(selection = viewState.selection.selectAll(event.all))
}

is InstalledListEvent.SelectApp -> {
viewState = viewState.copy(selectedApp = event.app)
}

InstalledListEvent.Import -> import()
is InstalledListEvent.AuthTokenError -> {
if (event.error is CheckTokenError.RequiresInteraction) {
Expand Down Expand Up @@ -156,18 +150,6 @@ class InstalledListViewModel(
}
}

private fun onBackPressed() {
if (viewState.wideLayout.isWideLayout) {
if (viewState.selectedApp != null) {
handleEvent(InstalledListEvent.SelectApp(app = null))
} else {
emitAction(ScreenCommonAction.NavigateBack)
}
} else {
emitAction(ScreenCommonAction.NavigateBack)
}
}

private fun handleListEvent(listEvent: WatchListEvent) {
when (listEvent) {
is WatchListEvent.AppClick -> {
Expand All @@ -176,7 +158,7 @@ class InstalledListViewModel(
togglePackage(listEvent.app.packageName)
}
} else {
viewState = viewState.copy(selectedApp = listEvent.app)
emitAction(ScreenCommonAction.NavigateTo(SceneNavKey.AppDetails(selectedApp = listEvent.app)))
}
}
is WatchListEvent.AppLongClick -> {
Expand Down
Loading
Loading