compose: favourite: Initial migration
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -27,6 +27,7 @@ import com.aurora.store.compose.ui.commons.PermissionRationaleScreen
|
|||||||
import com.aurora.store.compose.ui.details.AppDetailsScreen
|
import com.aurora.store.compose.ui.details.AppDetailsScreen
|
||||||
import com.aurora.store.compose.ui.dev.DevProfileScreen
|
import com.aurora.store.compose.ui.dev.DevProfileScreen
|
||||||
import com.aurora.store.compose.ui.downloads.DownloadsScreen
|
import com.aurora.store.compose.ui.downloads.DownloadsScreen
|
||||||
|
import com.aurora.store.compose.ui.favourite.FavouriteScreen
|
||||||
import com.aurora.store.compose.ui.search.SearchScreen
|
import com.aurora.store.compose.ui.search.SearchScreen
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,6 +115,15 @@ fun NavDisplay(startDestination: NavKey) {
|
|||||||
entry<Screen.About> {
|
entry<Screen.About> {
|
||||||
AboutScreen(onNavigateUp = { onNavigateUp() })
|
AboutScreen(onNavigateUp = { onNavigateUp() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entry<Screen.Favourite> {
|
||||||
|
FavouriteScreen(
|
||||||
|
onNavigateUp = { onNavigateUp() },
|
||||||
|
onNavigateToAppDetails = { packageName ->
|
||||||
|
backstack.add(Screen.AppDetails(packageName))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,7 @@ sealed class Screen : NavKey, Parcelable {
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object About : Screen()
|
data object About : Screen()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object Favourite : Screen()
|
||||||
}
|
}
|
||||||
|
|||||||
20
app/src/main/java/com/aurora/store/compose/preview/Paging.kt
Normal file
20
app/src/main/java/com/aurora/store/compose/preview/Paging.kt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 The Calyx Institute
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.aurora.store.compose.preview
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.compose.LazyPagingItems
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty lazy paging item flow for optional methods
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun <T: Any> emptyPagingItems(): LazyPagingItems<T> {
|
||||||
|
return flowOf(PagingData.empty<T>()).collectAsLazyPagingItems()
|
||||||
|
}
|
||||||
@@ -49,6 +49,7 @@ import com.aurora.store.compose.composables.TopAppBarComposable
|
|||||||
import com.aurora.store.compose.composables.details.ReviewComposable
|
import com.aurora.store.compose.composables.details.ReviewComposable
|
||||||
import com.aurora.store.compose.preview.ReviewPreviewProvider
|
import com.aurora.store.compose.preview.ReviewPreviewProvider
|
||||||
import com.aurora.store.compose.preview.coilPreviewProvider
|
import com.aurora.store.compose.preview.coilPreviewProvider
|
||||||
|
import com.aurora.store.compose.preview.emptyPagingItems
|
||||||
import com.aurora.store.viewmodel.details.AppDetailsViewModel
|
import com.aurora.store.viewmodel.details.AppDetailsViewModel
|
||||||
import com.aurora.store.viewmodel.details.ReviewViewModel
|
import com.aurora.store.viewmodel.details.ReviewViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -87,7 +88,7 @@ fun ReviewScreen(
|
|||||||
private fun ScreenContent(
|
private fun ScreenContent(
|
||||||
topAppBarTitle: String? = null,
|
topAppBarTitle: String? = null,
|
||||||
onNavigateUp: () -> Unit = {},
|
onNavigateUp: () -> Unit = {},
|
||||||
reviews: LazyPagingItems<Review>,
|
reviews: LazyPagingItems<Review> = emptyPagingItems(),
|
||||||
onFilter: (filter: Review.Filter) -> Unit = {},
|
onFilter: (filter: Review.Filter) -> Unit = {},
|
||||||
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
|
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.paging.LoadState
|
import androidx.paging.LoadState
|
||||||
import androidx.paging.PagingData
|
|
||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.paging.compose.LazyPagingItems
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import androidx.paging.compose.itemKey
|
import androidx.paging.compose.itemKey
|
||||||
@@ -35,11 +34,11 @@ import com.aurora.store.compose.composables.DownloadComposable
|
|||||||
import com.aurora.store.compose.composables.ErrorComposable
|
import com.aurora.store.compose.composables.ErrorComposable
|
||||||
import com.aurora.store.compose.composables.ProgressComposable
|
import com.aurora.store.compose.composables.ProgressComposable
|
||||||
import com.aurora.store.compose.composables.TopAppBarComposable
|
import com.aurora.store.compose.composables.TopAppBarComposable
|
||||||
|
import com.aurora.store.compose.preview.emptyPagingItems
|
||||||
import com.aurora.store.compose.ui.downloads.menu.DownloadsMenu
|
import com.aurora.store.compose.ui.downloads.menu.DownloadsMenu
|
||||||
import com.aurora.store.compose.ui.downloads.menu.MenuItem
|
import com.aurora.store.compose.ui.downloads.menu.MenuItem
|
||||||
import com.aurora.store.data.room.download.Download
|
import com.aurora.store.data.room.download.Download
|
||||||
import com.aurora.store.viewmodel.downloads.DownloadsViewModel
|
import com.aurora.store.viewmodel.downloads.DownloadsViewModel
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DownloadsScreen(
|
fun DownloadsScreen(
|
||||||
@@ -85,7 +84,7 @@ fun DownloadsScreen(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ScreenContent(
|
private fun ScreenContent(
|
||||||
downloads: LazyPagingItems<Download> = flowOf(PagingData.empty<Download>()).collectAsLazyPagingItems(),
|
downloads: LazyPagingItems<Download> = emptyPagingItems(),
|
||||||
onNavigateUp: () -> Unit = {},
|
onNavigateUp: () -> Unit = {},
|
||||||
onNavigateToAppDetails: (packageName: String) -> Unit = {},
|
onNavigateToAppDetails: (packageName: String) -> Unit = {},
|
||||||
onCancel: (packageName: String) -> Unit = {},
|
onCancel: (packageName: String) -> Unit = {},
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 The Calyx Institute
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.aurora.store.compose.ui.favourite
|
||||||
|
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.dimensionResource
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
|
import androidx.paging.LoadState
|
||||||
|
import androidx.paging.compose.LazyPagingItems
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import androidx.paging.compose.itemKey
|
||||||
|
import com.aurora.Constants.JSON_MIME_TYPE
|
||||||
|
import com.aurora.extensions.toast
|
||||||
|
import com.aurora.store.R
|
||||||
|
import com.aurora.store.compose.composables.ErrorComposable
|
||||||
|
import com.aurora.store.compose.composables.FavouriteComposable
|
||||||
|
import com.aurora.store.compose.composables.ProgressComposable
|
||||||
|
import com.aurora.store.compose.composables.TopAppBarComposable
|
||||||
|
import com.aurora.store.compose.preview.emptyPagingItems
|
||||||
|
import com.aurora.store.compose.ui.favourite.menu.FavouriteMenu
|
||||||
|
import com.aurora.store.compose.ui.favourite.menu.MenuItem
|
||||||
|
import com.aurora.store.data.room.favourite.Favourite
|
||||||
|
import com.aurora.store.viewmodel.all.FavouriteViewModel
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FavouriteScreen(
|
||||||
|
onNavigateUp: () -> Unit,
|
||||||
|
onNavigateToAppDetails: (packageName: String) -> Unit,
|
||||||
|
viewModel: FavouriteViewModel = hiltViewModel()
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val favourites = viewModel.favourites.collectAsLazyPagingItems()
|
||||||
|
|
||||||
|
val documentOpenLauncher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.OpenDocument(),
|
||||||
|
onResult = {
|
||||||
|
if (it != null) {
|
||||||
|
viewModel.importFavourites(it)
|
||||||
|
context.toast(R.string.toast_fav_import_success)
|
||||||
|
} else {
|
||||||
|
context.toast(R.string.toast_fav_import_failed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val documentCreateLauncher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.CreateDocument(JSON_MIME_TYPE),
|
||||||
|
onResult = {
|
||||||
|
if (it != null) {
|
||||||
|
viewModel.exportFavourites(it)
|
||||||
|
context.toast(R.string.toast_fav_export_success)
|
||||||
|
} else {
|
||||||
|
context.toast(R.string.toast_fav_export_failed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ScreenContent(
|
||||||
|
favourites = favourites,
|
||||||
|
onNavigateUp = onNavigateUp,
|
||||||
|
onNavigateToAppDetails = onNavigateToAppDetails,
|
||||||
|
onRemoveFavourite = { packageName -> viewModel.removeFavourite(packageName) },
|
||||||
|
onImportFavourites = {
|
||||||
|
documentOpenLauncher.launch(arrayOf(JSON_MIME_TYPE))
|
||||||
|
},
|
||||||
|
onExportFavourites = {
|
||||||
|
documentCreateLauncher.launch(
|
||||||
|
"aurora_store_favourites_${Calendar.getInstance().time.time}.json"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ScreenContent(
|
||||||
|
favourites: LazyPagingItems<Favourite> = emptyPagingItems(),
|
||||||
|
onNavigateUp: () -> Unit = {},
|
||||||
|
onNavigateToAppDetails: (packageName: String) -> Unit = {},
|
||||||
|
onRemoveFavourite: (packageName: String) -> Unit = {},
|
||||||
|
onImportFavourites: () -> Unit = {},
|
||||||
|
onExportFavourites: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SetupMenu() {
|
||||||
|
FavouriteMenu { menuItem ->
|
||||||
|
when (menuItem) {
|
||||||
|
MenuItem.IMPORT -> onImportFavourites()
|
||||||
|
MenuItem.EXPORT -> onExportFavourites()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBarComposable(
|
||||||
|
title = stringResource(R.string.title_favourites_manager),
|
||||||
|
onNavigateUp = onNavigateUp,
|
||||||
|
actions = { if (favourites.itemCount != 0) SetupMenu() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(paddingValues)
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(vertical = dimensionResource(R.dimen.padding_medium))
|
||||||
|
) {
|
||||||
|
when (favourites.loadState.refresh) {
|
||||||
|
is LoadState.Loading -> ProgressComposable()
|
||||||
|
|
||||||
|
is LoadState.Error -> {
|
||||||
|
ErrorComposable(
|
||||||
|
modifier = Modifier.padding(paddingValues),
|
||||||
|
icon = painterResource(R.drawable.ic_disclaimer),
|
||||||
|
message = stringResource(R.string.error)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
if (favourites.itemCount == 0) {
|
||||||
|
ErrorComposable(
|
||||||
|
modifier = Modifier.padding(paddingValues),
|
||||||
|
icon = painterResource(R.drawable.ic_favorite_unchecked),
|
||||||
|
message = stringResource(R.string.details_no_favourites)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LazyColumn {
|
||||||
|
items(
|
||||||
|
count = favourites.itemCount,
|
||||||
|
key = favourites.itemKey { it.packageName }
|
||||||
|
) { index ->
|
||||||
|
favourites[index]?.let { favourite ->
|
||||||
|
FavouriteComposable(
|
||||||
|
favourite = favourite,
|
||||||
|
onClick = { onNavigateToAppDetails(favourite.packageName) },
|
||||||
|
onClear = { onRemoveFavourite(favourite.packageName) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun FavouriteScreenPreview() {
|
||||||
|
ScreenContent()
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 The Calyx Institute
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.aurora.store.compose.ui.favourite.menu
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import com.aurora.store.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menu for the favourite screen
|
||||||
|
* @param modifier The modifier to be applied to the composable
|
||||||
|
* @param onMenuItemClicked Callback when a menu item has been clicked
|
||||||
|
* @see MenuItem
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun FavouriteMenu(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
isExpanded: Boolean = false,
|
||||||
|
onMenuItemClicked: (menuItem: MenuItem) -> Unit = {}
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(isExpanded) }
|
||||||
|
fun onClick(menuItem: MenuItem) {
|
||||||
|
onMenuItemClicked(menuItem)
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = modifier) {
|
||||||
|
IconButton(onClick = { expanded = true }) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.ic_more_vert),
|
||||||
|
contentDescription = stringResource(R.string.menu)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.action_import)) },
|
||||||
|
onClick = { onClick(MenuItem.IMPORT) }
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(R.string.action_export)) },
|
||||||
|
onClick = { onClick(MenuItem.EXPORT) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun FavouriteMenuPreview() {
|
||||||
|
FavouriteMenu(isExpanded = true)
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 The Calyx Institute
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.aurora.store.compose.ui.favourite.menu
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid menu items for the purpose of handling clicks
|
||||||
|
*/
|
||||||
|
enum class MenuItem {
|
||||||
|
IMPORT,
|
||||||
|
EXPORT
|
||||||
|
}
|
||||||
@@ -70,6 +70,7 @@ import com.aurora.store.compose.composables.SearchSuggestionComposable
|
|||||||
import com.aurora.store.compose.composables.app.AppListComposable
|
import com.aurora.store.compose.composables.app.AppListComposable
|
||||||
import com.aurora.store.compose.preview.AppPreviewProvider
|
import com.aurora.store.compose.preview.AppPreviewProvider
|
||||||
import com.aurora.store.compose.preview.coilPreviewProvider
|
import com.aurora.store.compose.preview.coilPreviewProvider
|
||||||
|
import com.aurora.store.compose.preview.emptyPagingItems
|
||||||
import com.aurora.store.compose.ui.details.AppDetailsScreen
|
import com.aurora.store.compose.ui.details.AppDetailsScreen
|
||||||
import com.aurora.store.data.model.SearchFilter
|
import com.aurora.store.data.model.SearchFilter
|
||||||
import com.aurora.store.viewmodel.search.SearchViewModel
|
import com.aurora.store.viewmodel.search.SearchViewModel
|
||||||
@@ -98,7 +99,7 @@ fun SearchScreen(onNavigateUp: () -> Unit, viewModel: SearchViewModel = hiltView
|
|||||||
@Composable
|
@Composable
|
||||||
private fun ScreenContent(
|
private fun ScreenContent(
|
||||||
suggestions: List<SearchSuggestEntry> = emptyList(),
|
suggestions: List<SearchSuggestEntry> = emptyList(),
|
||||||
results: LazyPagingItems<App> = flowOf(PagingData.empty<App>()).collectAsLazyPagingItems(),
|
results: LazyPagingItems<App> = emptyPagingItems(),
|
||||||
onNavigateUp: () -> Unit = {},
|
onNavigateUp: () -> Unit = {},
|
||||||
onFetchSuggestions: (String) -> Unit = {},
|
onFetchSuggestions: (String) -> Unit = {},
|
||||||
onSearch: (String) -> Unit = {},
|
onSearch: (String) -> Unit = {},
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.aurora.store.data.room.favourite
|
package com.aurora.store.data.room.favourite
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
@@ -18,6 +19,9 @@ interface FavouriteDao {
|
|||||||
@Query("SELECT * FROM favourite")
|
@Query("SELECT * FROM favourite")
|
||||||
fun favourites(): Flow<List<Favourite>>
|
fun favourites(): Flow<List<Favourite>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM favourite")
|
||||||
|
fun pagedFavourites(): PagingSource<Int, Favourite>
|
||||||
|
|
||||||
@Query("SELECT EXISTS(SELECT 1 FROM favourite WHERE packageName = :packageName)")
|
@Query("SELECT EXISTS(SELECT 1 FROM favourite WHERE packageName = :packageName)")
|
||||||
suspend fun isFavourite(packageName: String): Boolean
|
suspend fun isFavourite(packageName: String): Boolean
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Aurora Store
|
|
||||||
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
|
||||||
*
|
|
||||||
* Aurora Store is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Aurora Store is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.aurora.store.view.epoxy.views
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import coil3.load
|
|
||||||
import coil3.request.placeholder
|
|
||||||
import coil3.request.transformations
|
|
||||||
import coil3.transform.RoundedCornersTransformation
|
|
||||||
import com.airbnb.epoxy.CallbackProp
|
|
||||||
import com.airbnb.epoxy.ModelProp
|
|
||||||
import com.airbnb.epoxy.ModelView
|
|
||||||
import com.aurora.store.R
|
|
||||||
import com.aurora.store.data.room.favourite.Favourite
|
|
||||||
import com.aurora.store.databinding.ViewFavBinding
|
|
||||||
|
|
||||||
@ModelView(
|
|
||||||
autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT,
|
|
||||||
baseModelClass = BaseModel::class
|
|
||||||
)
|
|
||||||
class FavouriteView @JvmOverloads constructor(
|
|
||||||
context: Context?,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : BaseView<ViewFavBinding>(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
@ModelProp
|
|
||||||
fun favourite(favourite: Favourite) {
|
|
||||||
binding.imgIcon.load(favourite.iconURL) {
|
|
||||||
placeholder(R.drawable.bg_placeholder)
|
|
||||||
transformations(RoundedCornersTransformation(25F))
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.txtLine1.text = favourite.displayName
|
|
||||||
binding.txtLine2.text = favourite.packageName
|
|
||||||
}
|
|
||||||
|
|
||||||
@CallbackProp
|
|
||||||
fun onClick(onClickListener: OnClickListener?) {
|
|
||||||
binding.root.setOnClickListener(onClickListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
@CallbackProp
|
|
||||||
fun onFavourite(onClickListener: OnClickListener?) {
|
|
||||||
binding.btnFavourite.setOnClickListener(onClickListener)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Aurora Store
|
|
||||||
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
|
||||||
*
|
|
||||||
* Aurora Store is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Aurora Store is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.aurora.store.view.ui.commons
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.fragment.app.viewModels
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import com.aurora.Constants
|
|
||||||
import com.aurora.extensions.toast
|
|
||||||
import com.aurora.store.R
|
|
||||||
import com.aurora.store.data.room.favourite.Favourite
|
|
||||||
import com.aurora.store.databinding.FragmentFavouriteBinding
|
|
||||||
import com.aurora.store.view.epoxy.views.FavouriteViewModel_
|
|
||||||
import com.aurora.store.view.epoxy.views.app.NoAppViewModel_
|
|
||||||
import com.aurora.store.view.epoxy.views.shimmer.AppListViewShimmerModel_
|
|
||||||
import com.aurora.store.viewmodel.all.FavouriteViewModel
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.util.Calendar
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class FavouriteFragment : BaseFragment<FragmentFavouriteBinding>() {
|
|
||||||
private val viewModel: FavouriteViewModel by viewModels()
|
|
||||||
|
|
||||||
private val startForDocumentImport =
|
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) {
|
|
||||||
if (it != null) importFavourites(it) else toast(R.string.toast_fav_import_failed)
|
|
||||||
}
|
|
||||||
private val startForDocumentExport =
|
|
||||||
registerForActivityResult(ActivityResultContracts.CreateDocument(Constants.JSON_MIME_TYPE)) {
|
|
||||||
if (it != null) exportFavourites(it) else toast(R.string.toast_fav_export_failed)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
|
||||||
viewModel.favouritesList.collect {
|
|
||||||
updateController(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toolbar
|
|
||||||
binding.toolbar.apply {
|
|
||||||
setOnMenuItemClickListener {
|
|
||||||
when (it.itemId) {
|
|
||||||
R.id.action_import -> startForDocumentImport.launch(arrayOf(Constants.JSON_MIME_TYPE))
|
|
||||||
R.id.action_export -> {
|
|
||||||
startForDocumentExport.launch(
|
|
||||||
"aurora_store_favourites_${Calendar.getInstance().time.time}.json"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
setNavigationOnClickListener { findNavController().navigateUp() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateController(favourites: List<Favourite>?) {
|
|
||||||
binding.recycler.withModels {
|
|
||||||
setFilterDuplicates(true)
|
|
||||||
if (favourites == null) {
|
|
||||||
for (i in 1..10) {
|
|
||||||
add(
|
|
||||||
AppListViewShimmerModel_()
|
|
||||||
.id(i)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else if (favourites.isEmpty()) {
|
|
||||||
add(
|
|
||||||
NoAppViewModel_()
|
|
||||||
.id("no_app")
|
|
||||||
.icon(R.drawable.ic_favorite_unchecked)
|
|
||||||
.message(R.string.details_no_favourites)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
favourites.forEach {
|
|
||||||
add(
|
|
||||||
FavouriteViewModel_()
|
|
||||||
.id(it.packageName.hashCode())
|
|
||||||
.favourite(it)
|
|
||||||
.onClick { _ -> openDetailsFragment(it.packageName) }
|
|
||||||
.onFavourite { _ -> viewModel.removeFavourite(it.packageName) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun importFavourites(uri: Uri) {
|
|
||||||
viewModel.importFavourites(requireContext(), uri)
|
|
||||||
binding.recycler.requestModelBuild()
|
|
||||||
toast(R.string.toast_fav_import_success)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun exportFavourites(uri: Uri) {
|
|
||||||
viewModel.exportFavourites(requireContext(), uri)
|
|
||||||
toast(R.string.toast_fav_export_success)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -433,10 +433,10 @@ class MoreDialogFragment : DialogFragment() {
|
|||||||
icon = R.drawable.ic_blacklist,
|
icon = R.drawable.ic_blacklist,
|
||||||
screen = Screen.Blacklist
|
screen = Screen.Blacklist
|
||||||
),
|
),
|
||||||
ViewOption(
|
ComposeOption(
|
||||||
title = R.string.title_favourites_manager,
|
title = R.string.title_favourites_manager,
|
||||||
icon = R.drawable.ic_favorite_unchecked,
|
icon = R.drawable.ic_favorite_unchecked,
|
||||||
destinationID = R.id.favouriteFragment
|
screen = Screen.Favourite
|
||||||
),
|
),
|
||||||
ViewOption(
|
ViewOption(
|
||||||
title = R.string.title_spoof_manager,
|
title = R.string.title_spoof_manager,
|
||||||
|
|||||||
@@ -1,20 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Aurora Store
|
* SPDX-FileCopyrightText: 2024-2025 Rahul Kumar Patel <whyorean@gmail.com>
|
||||||
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
* SPDX-FileCopyrightText: 2024-2025 The Calyx Institute
|
||||||
*
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
* Aurora Store is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Aurora Store is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.aurora.store.viewmodel.all
|
package com.aurora.store.viewmodel.all
|
||||||
@@ -24,13 +11,21 @@ import android.net.Uri
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import com.aurora.store.data.paging.GenericPagingSource.Companion.pager
|
||||||
import com.aurora.store.data.room.favourite.Favourite
|
import com.aurora.store.data.room.favourite.Favourite
|
||||||
import com.aurora.store.data.room.favourite.FavouriteDao
|
import com.aurora.store.data.room.favourite.FavouriteDao
|
||||||
import com.aurora.store.data.room.favourite.ImportExport
|
import com.aurora.store.data.room.favourite.ImportExport
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -38,14 +33,19 @@ import javax.inject.Inject
|
|||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class FavouriteViewModel @Inject constructor(
|
class FavouriteViewModel @Inject constructor(
|
||||||
private val favouriteDao: FavouriteDao,
|
private val favouriteDao: FavouriteDao,
|
||||||
private val json: Json
|
private val json: Json,
|
||||||
|
@ApplicationContext private val context: Context
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val TAG = FavouriteViewModel::class.java.simpleName
|
private val TAG = FavouriteViewModel::class.java.simpleName
|
||||||
|
|
||||||
val favouritesList = favouriteDao.favourites()
|
private val _favourites = MutableStateFlow<PagingData<Favourite>>(PagingData.empty())
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
|
val favourites = _favourites.asStateFlow()
|
||||||
|
|
||||||
fun importFavourites(context: Context, uri: Uri) {
|
init {
|
||||||
|
getPagedFavourites()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun importFavourites(uri: Uri) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
context.contentResolver.openInputStream(uri)?.use {
|
context.contentResolver.openInputStream(uri)?.use {
|
||||||
@@ -54,7 +54,9 @@ class FavouriteViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
favouriteDao.insertAll(
|
favouriteDao.insertAll(
|
||||||
importExport.favourites.map { fav -> fav.copy(mode = Favourite.Mode.IMPORT) }
|
importExport.favourites.map { fav ->
|
||||||
|
fav.copy(mode = Favourite.Mode.IMPORT)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
@@ -63,12 +65,12 @@ class FavouriteViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportFavourites(context: Context, uri: Uri) {
|
fun exportFavourites(uri: Uri) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
context.contentResolver.openOutputStream(uri)?.use {
|
context.contentResolver.openOutputStream(uri)?.use {
|
||||||
it.write(
|
it.write(
|
||||||
json.encodeToString(ImportExport(favouritesList.value!!))
|
json.encodeToString(ImportExport(favouriteDao.favourites().first()))
|
||||||
.encodeToByteArray()
|
.encodeToByteArray()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -83,4 +85,12 @@ class FavouriteViewModel @Inject constructor(
|
|||||||
favouriteDao.delete(packageName)
|
favouriteDao.delete(packageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getPagedFavourites() {
|
||||||
|
pager { favouriteDao.pagedFavourites() }.flow
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.cachedIn(viewModelScope)
|
||||||
|
.onEach { _favourites.value = it }
|
||||||
|
.launchIn(viewModelScope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Aurora Store
|
|
||||||
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
|
||||||
~
|
|
||||||
~ Aurora Store is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 2 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ Aurora Store is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="?attr/actionBarSize"
|
|
||||||
app:menu="@menu/menu_import_export"
|
|
||||||
app:navigationIcon="@drawable/ic_arrow_back"
|
|
||||||
app:title="@string/title_favourites_manager" />
|
|
||||||
|
|
||||||
<com.airbnb.epoxy.EpoxyRecyclerView
|
|
||||||
android:id="@+id/recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@+id/toolbar"
|
|
||||||
android:clipToPadding="true"
|
|
||||||
android:paddingBottom="@dimen/height_bottom_adj"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
tools:listitem="@layout/view_app_list"
|
|
||||||
app:stackFromEnd="false" />
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Aurora Store
|
|
||||||
~ Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
|
|
||||||
~
|
|
||||||
~ Aurora Store is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 2 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ Aurora Store is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingStart="@dimen/padding_small"
|
|
||||||
android:paddingTop="@dimen/padding_xsmall"
|
|
||||||
android:paddingEnd="@dimen/padding_small"
|
|
||||||
android:paddingBottom="@dimen/padding_xsmall">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
|
||||||
android:id="@+id/img_icon"
|
|
||||||
android:layout_width="@dimen/icon_size_medium"
|
|
||||||
android:layout_height="@dimen/icon_size_medium" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/txt_line1"
|
|
||||||
style="@style/AuroraTextStyle.Line1"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/margin_normal"
|
|
||||||
android:layout_toStartOf="@id/btn_favourite"
|
|
||||||
android:layout_toEndOf="@id/img_icon"
|
|
||||||
tools:text="Line1" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/txt_line2"
|
|
||||||
style="@style/AuroraTextStyle.Line2"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/txt_line1"
|
|
||||||
android:layout_alignStart="@id/txt_line1"
|
|
||||||
android:layout_alignEnd="@id/txt_line1"
|
|
||||||
tools:text="Line2" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/txt_line3"
|
|
||||||
style="@style/AuroraTextStyle.Line3"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/txt_line2"
|
|
||||||
android:layout_alignStart="@id/txt_line1"
|
|
||||||
android:layout_alignEnd="@id/txt_line1"
|
|
||||||
tools:text="Line3" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/btn_favourite"
|
|
||||||
style="@style/Widget.Material3.Button.IconButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:contentDescription="@string/action_favourite"
|
|
||||||
android:padding="@dimen/padding_large"
|
|
||||||
app:icon="@drawable/ic_favorite_checked" />
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -66,11 +66,6 @@
|
|||||||
android:name="com.aurora.store.view.ui.spoof.SpoofFragment"
|
android:name="com.aurora.store.view.ui.spoof.SpoofFragment"
|
||||||
android:label="@string/title_spoof_manager"
|
android:label="@string/title_spoof_manager"
|
||||||
tools:layout="@layout/fragment_spoof" />
|
tools:layout="@layout/fragment_spoof" />
|
||||||
<fragment
|
|
||||||
android:id="@+id/favouriteFragment"
|
|
||||||
android:name="com.aurora.store.view.ui.commons.FavouriteFragment"
|
|
||||||
android:label="@string/title_favourites_manager"
|
|
||||||
tools:layout="@layout/fragment_generic_with_toolbar" />
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/settingsFragment"
|
android:id="@+id/settingsFragment"
|
||||||
android:name="com.aurora.store.view.ui.preferences.SettingsFragment"
|
android:name="com.aurora.store.view.ui.preferences.SettingsFragment"
|
||||||
|
|||||||
Reference in New Issue
Block a user