Merge pull request #96 from kirmanak/ui-improvements

Rewrite UI with Material Design
This commit is contained in:
Kirill Kamakin
2022-11-20 16:27:58 +01:00
committed by GitHub
49 changed files with 504 additions and 564 deletions

View File

@@ -9,18 +9,18 @@ repository.
## What is this?
An unofficial Android client for [Mealie](https://hay-kot.github.io/mealie/). It enables you to
easily access your recipes using via Android phone. The main goal is to have everything stored
locally to access it without Internet connection which is impossible with web site version.
easily access your recipes using an Android device. The main advantage over website is that
recipe data is stored locally and can be accessed without the Internet connection.
## Status
Current version is a very early alpha which supports a tiny portion of the Mealie capabilites. There
is a lot of work ahead, do not expect much. Having said that, you can list your recipes and read the
instructions/ingredients for each of them.
Current version is a very early alpha which supports a small subset of the Mealie capabilities.
It supports both API of older Mealie 0.5.6 and newer 1.0.0. Displays the list of recipes,
information about each of the recipes. Moreover, you can create a recipe from the app!
## Screenshots
<img src="https://user-images.githubusercontent.com/24299495/143483169-58bfa02b-d692-4d20-ad82-7e206de0c26c.png" width="274" height="489" /> <img src="https://user-images.githubusercontent.com/24299495/143483174-3c05f3e2-957d-4558-83e5-8fa53c07b66e.png" width="274" height="489" /> <img src="https://user-images.githubusercontent.com/24299495/143483181-20fc5bd9-2d47-4228-a85b-4dc571c49340.png" width="274" height="489" />
<img src="https://user-images.githubusercontent.com/24299495/202909772-fc03e0ca-6ccb-4579-8ac1-30ead4cb9586.png" width="236" height="500" /> <img src="https://user-images.githubusercontent.com/24299495/202909799-cfa73ebf-cdc6-4e79-84cc-a430d204654b.png" width="236" height="500" /> <img src="https://user-images.githubusercontent.com/24299495/202909840-da163637-57d9-431d-be63-fc38066a8055.png" width="236" height="500" /> <img src="https://user-images.githubusercontent.com/24299495/202909845-d857259f-90f9-4988-beff-038cd784215d.png" width="236" height="500" />
## How to install
@@ -28,6 +28,4 @@ Download the latest apk from the releases page.
## Contribution
Any contribution is greatly appreciated. Including translations, new issues, feature requests and
typo corrections. I won't specify any rules until I have to ask the same thing multiple times. Just
use the common sense.
Any contribution is greatly appreciated: translations, bug reports, feature requests and any PR.

View File

@@ -1,6 +1,7 @@
package gq.kirmanak.mealient
import android.app.Application
import com.google.android.material.color.DynamicColors
import dagger.hilt.android.HiltAndroidApp
import gq.kirmanak.mealient.architecture.configuration.BuildConfiguration
import gq.kirmanak.mealient.data.analytics.Analytics
@@ -23,5 +24,6 @@ class App : Application() {
super.onCreate()
logger.v { "onCreate() called" }
analytics.setIsEnabled(!buildConfiguration.isDebug())
DynamicColors.applyToActivitiesIfAvailable(this)
}
}

View File

@@ -2,19 +2,11 @@ package gq.kirmanak.mealient.extensions
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.launch
fun <T> Fragment.collectWhenViewResumed(flow: Flow<T>, collector: FlowCollector<T>) {
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
flow.collect(collector)
}
}
viewLifecycleOwner.collectWhenResumed(flow, collector)
}
fun Fragment.showLongToast(@StringRes text: Int) = context?.showLongToast(text) != null

View File

@@ -2,6 +2,9 @@ package gq.kirmanak.mealient.extensions
import android.content.Context
import android.content.SharedPreferences
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.os.Build
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
@@ -10,10 +13,7 @@ import android.widget.Toast
import androidx.annotation.StringRes
import androidx.core.content.getSystemService
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.*
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.textfield.TextInputLayout
import gq.kirmanak.mealient.logging.Logger
@@ -21,10 +21,7 @@ import kotlinx.coroutines.channels.ChannelResult
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.onClosed
import kotlinx.coroutines.channels.onFailure
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
fun SwipeRefreshLayout.refreshRequestFlow(logger: Logger): Flow<Unit> = callbackFlow {
@@ -114,4 +111,19 @@ private fun Context.showToast(text: String, length: Int) {
fun View.hideKeyboard() {
val imm = context.getSystemService<InputMethodManager>()
imm?.hideSoftInputFromWindow(windowToken, 0)
}
fun Context.isDarkThemeOn(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
resources.configuration.isNightModeActive
else
resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES
}
fun <T> LifecycleOwner.collectWhenResumed(flow: Flow<T>, collector: FlowCollector<T>) {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
flow.collect(collector)
}
}
}

View File

@@ -1,20 +1,18 @@
package gq.kirmanak.mealient.ui.activity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.SearchView.OnQueryTextListener
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.isVisible
import androidx.core.view.iterator
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.NavController
import androidx.navigation.NavDirections
import androidx.navigation.fragment.NavHostFragment
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.MaterialShapeDrawable
import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealient.NavGraphDirections.Companion.actionGlobalAddRecipeFragment
import gq.kirmanak.mealient.NavGraphDirections.Companion.actionGlobalAuthenticationFragment
@@ -22,6 +20,8 @@ import gq.kirmanak.mealient.NavGraphDirections.Companion.actionGlobalBaseURLFrag
import gq.kirmanak.mealient.NavGraphDirections.Companion.actionGlobalRecipesListFragment
import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.databinding.MainActivityBinding
import gq.kirmanak.mealient.extensions.collectWhenResumed
import gq.kirmanak.mealient.extensions.isDarkThemeOn
import gq.kirmanak.mealient.extensions.observeOnce
import gq.kirmanak.mealient.logging.Logger
import javax.inject.Inject
@@ -31,8 +31,6 @@ class MainActivity : AppCompatActivity(R.layout.main_activity) {
private val binding: MainActivityBinding by viewBinding(MainActivityBinding::bind, R.id.drawer)
private val viewModel by viewModels<MainActivityViewModel>()
private val title: String by lazy { getString(R.string.app_name) }
private val uiState: MainActivityUiState get() = viewModel.uiState
private val navController: NavController
get() = binding.navHost.getFragment<NavHostFragment>().navController
@@ -45,126 +43,98 @@ class MainActivity : AppCompatActivity(R.layout.main_activity) {
logger.v { "onCreate() called with: savedInstanceState = $savedInstanceState" }
splashScreen.setKeepOnScreenCondition { viewModel.startDestination.value == null }
setContentView(binding.root)
configureToolbar()
setupUi()
configureNavGraph()
viewModel.uiStateLive.observe(this, ::onUiStateChange)
binding.navigationView.setNavigationItemSelectedListener(::onNavigationItemSelected)
}
private fun configureNavGraph() {
logger.v { "configureNavGraph() called" }
viewModel.startDestination.observeOnce(this) {
logger.d { "configureNavGraph: received destination" }
val graph = navController.navInflater.inflate(R.navigation.nav_graph)
val controller = navController
val graph = controller.navInflater.inflate(R.navigation.nav_graph)
graph.setStartDestination(it)
navController.setGraph(graph, intent.extras)
controller.setGraph(graph, intent.extras)
}
}
private fun configureToolbar() {
setSupportActionBar(binding.toolbar)
binding.toolbar.setNavigationIcon(R.drawable.ic_toolbar)
binding.toolbar.setNavigationOnClickListener { binding.drawer.open() }
setToolbarRoundCorner()
private fun setupUi() {
binding.toolbar.setNavigationOnClickListener {
binding.toolbar.clearSearchFocus()
binding.drawer.open()
}
binding.toolbar.onSearchQueryChanged { query ->
viewModel.onSearchQuery(query.trim().takeUnless { it.isEmpty() })
}
binding.navigationView.setNavigationItemSelectedListener(::onNavigationItemSelected)
with(WindowInsetsControllerCompat(window, window.decorView)) {
val isAppearanceLightBars = !isDarkThemeOn()
isAppearanceLightNavigationBars = isAppearanceLightBars
isAppearanceLightStatusBars = isAppearanceLightBars
}
viewModel.uiStateLive.observe(this, ::onUiStateChange)
collectWhenResumed(viewModel.clearSearchViewFocus) {
logger.d { "clearSearchViewFocus(): received event" }
binding.toolbar.clearSearchFocus()
}
}
private fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
logger.v { "onNavigationItemSelected() called with: menuItem = $menuItem" }
menuItem.isChecked = true
if (menuItem.isChecked) {
logger.d { "Not navigating because it is the current destination" }
binding.drawer.close()
return true
}
val directions = when (menuItem.itemId) {
R.id.add_recipe -> actionGlobalAddRecipeFragment()
R.id.recipes_list -> actionGlobalRecipesListFragment()
R.id.change_url -> actionGlobalBaseURLFragment()
R.id.change_url -> actionGlobalBaseURLFragment(false)
R.id.login -> actionGlobalAuthenticationFragment()
R.id.logout -> {
viewModel.logout()
return true
}
else -> throw IllegalArgumentException("Unknown menu item id: ${menuItem.itemId}")
}
menuItem.isChecked = true
navigateTo(directions)
binding.drawer.close()
return true
}
private fun onUiStateChange(uiState: MainActivityUiState) {
logger.v { "onUiStateChange() called with: uiState = $uiState" }
supportActionBar?.title = if (uiState.titleVisible) title else null
binding.navigationView.isVisible = uiState.navigationVisible
invalidateOptionsMenu()
}
for (menuItem in binding.navigationView.menu.iterator()) {
val itemId = menuItem.itemId
when (itemId) {
R.id.logout -> menuItem.isVisible = uiState.canShowLogout
R.id.login -> menuItem.isVisible = uiState.canShowLogin
}
menuItem.isChecked = itemId == uiState.checkedMenuItemId
}
private fun setToolbarRoundCorner() {
logger.v { "setToolbarRoundCorner() called" }
val drawables = listOf(
binding.toolbarHolder.background as? MaterialShapeDrawable,
binding.toolbar.background as? MaterialShapeDrawable,
binding.toolbar.isVisible = uiState.navigationVisible
binding.root.setDrawerLockMode(
if (uiState.navigationVisible) {
DrawerLayout.LOCK_MODE_UNLOCKED
} else {
DrawerLayout.LOCK_MODE_LOCKED_CLOSED
}
)
logger.d { "setToolbarRoundCorner: drawables = $drawables" }
val radius = resources.getDimension(R.dimen.main_activity_toolbar_corner_radius)
for (drawable in drawables) {
drawable?.apply {
shapeAppearanceModel = shapeAppearanceModel.toBuilder()
.setBottomLeftCorner(CornerFamily.ROUNDED, radius).build()
}
binding.toolbar.isSearchVisible = uiState.searchVisible
if (uiState.searchVisible) {
binding.toolbarHolder.setBackgroundResource(R.drawable.bg_toolbar)
} else {
binding.toolbarHolder.background = null
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
logger.v { "onCreateOptionsMenu() called with: menu = $menu" }
menuInflater.inflate(R.menu.main_toolbar, menu)
menu.findItem(R.id.logout).isVisible = uiState.canShowLogout
menu.findItem(R.id.login).isVisible = uiState.canShowLogin
val searchItem = menu.findItem(R.id.search_recipe_action)
searchItem.isVisible = uiState.searchVisible
setupSearchItem(searchItem)
return true
}
private fun setupSearchItem(searchItem: MenuItem) {
logger.v { "setupSearchItem() called with: searchItem = $searchItem" }
val searchView = searchItem.actionView as? SearchView
if (searchView == null) {
logger.e { "setupSearchItem: search item's actionView is null or not SearchView" }
return
}
searchView.queryHint = getString(R.string.search_recipes_hint)
searchView.isSubmitButtonEnabled = false
searchView.setQuery(viewModel.lastSearchQuery, false)
searchView.isIconified = viewModel.lastSearchQuery.isNullOrBlank()
searchView.setOnCloseListener {
logger.v { "onClose() called" }
viewModel.onSearchQuery(null)
false
}
searchView.setOnQueryTextListener(object : OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean = true
override fun onQueryTextChange(newText: String?): Boolean {
logger.v { "onQueryTextChange() called with: newText = $newText" }
viewModel.onSearchQuery(newText?.trim()?.takeUnless { it.isEmpty() })
return true
}
})
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
logger.v { "onOptionsItemSelected() called with: item = $item" }
val result = when (item.itemId) {
R.id.login -> {
navigateTo(actionGlobalAuthenticationFragment())
true
}
R.id.logout -> {
viewModel.logout()
true
}
else -> super.onOptionsItemSelected(item)
}
return result
}
private fun navigateTo(directions: NavDirections) {
logger.v { "navigateTo() called with: directions = $directions" }
binding.toolbarHolder.setExpanded(true)
binding.drawer.close()
navController.navigate(directions)
}
}

View File

@@ -1,15 +1,14 @@
package gq.kirmanak.mealient.ui.activity
import androidx.annotation.IdRes
data class MainActivityUiState(
val loginButtonVisible: Boolean = false,
val titleVisible: Boolean = true,
val isAuthorized: Boolean = false,
val navigationVisible: Boolean = false,
val searchVisible: Boolean = false,
@IdRes val checkedMenuItemId: Int? = null,
) {
val canShowLogin: Boolean
get() = !isAuthorized && loginButtonVisible
val canShowLogin: Boolean get() = !isAuthorized
val canShowLogout: Boolean
get() = isAuthorized && loginButtonVisible
val canShowLogout: Boolean get() = isAuthorized
}

View File

@@ -8,8 +8,11 @@ import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.data.disclaimer.DisclaimerStorage
import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.logging.Logger
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -32,8 +35,8 @@ class MainActivityViewModel @Inject constructor(
private val _startDestination = MutableLiveData<Int>()
val startDestination: LiveData<Int> = _startDestination
var lastSearchQuery: String? = null
private set
private val _clearSearchViewFocusChannel = Channel<Unit>()
val clearSearchViewFocus: Flow<Unit> = _clearSearchViewFocusChannel.receiveAsFlow()
init {
authRepo.isAuthorizedFlow
@@ -60,9 +63,11 @@ class MainActivityViewModel @Inject constructor(
fun onSearchQuery(query: String?) {
logger.v { "onSearchQuery() called with: query = $query" }
if (lastSearchQuery != query) {
lastSearchQuery = query
recipeRepo.updateNameQuery(query)
}
recipeRepo.updateNameQuery(query)
}
fun clearSearchViewFocus() {
logger.v { "clearSearchViewFocus() called" }
_clearSearchViewFocusChannel.trySend(Unit)
}
}

View File

@@ -0,0 +1,47 @@
package gq.kirmanak.mealient.ui.activity
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.annotation.AttrRes
import androidx.annotation.StyleRes
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
import gq.kirmanak.mealient.databinding.ViewToolbarBinding
import gq.kirmanak.mealient.extensions.hideKeyboard
class ToolbarView @JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
@StyleRes defStyleRes: Int = 0,
) : ConstraintLayout(context, attributeSet, defStyleAttr, defStyleRes) {
private lateinit var binding: ViewToolbarBinding
var isSearchVisible: Boolean
get() = binding.searchEdit.isVisible
set(value) {
binding.searchEdit.isVisible = value
}
override fun onFinishInflate() {
super.onFinishInflate()
val inflater = LayoutInflater.from(context)
binding = ViewToolbarBinding.inflate(inflater, this)
}
fun setNavigationOnClickListener(listener: OnClickListener?) {
binding.navigationIcon.setOnClickListener(listener)
}
fun onSearchQueryChanged(block: (String) -> Unit) {
binding.searchEdit.doAfterTextChanged { block(it.toString()) }
}
fun clearSearchFocus() {
binding.searchEdit.clearFocus()
hideKeyboard()
}
}

View File

@@ -39,10 +39,9 @@ class AddRecipeFragment : Fragment(R.layout.fragment_add_recipe) {
logger.v { "onViewCreated() called with: view = $view, savedInstanceState = $savedInstanceState" }
activityViewModel.updateUiState {
it.copy(
loginButtonVisible = true,
titleVisible = false,
navigationVisible = true,
searchVisible = false,
checkedMenuItemId = R.id.add_recipe,
)
}
viewModel.loadPreservedRequest()

View File

@@ -32,12 +32,7 @@ class AuthenticationFragment : Fragment(R.layout.fragment_authentication) {
logger.v { "onViewCreated() called with: view = $view, savedInstanceState = $savedInstanceState" }
binding.button.setOnClickListener { onLoginClicked() }
activityViewModel.updateUiState {
it.copy(
loginButtonVisible = false,
titleVisible = true,
navigationVisible = false,
searchVisible = false
)
it.copy(navigationVisible = true, searchVisible = false, checkedMenuItemId = R.id.login)
}
viewModel.uiState.observe(viewLifecycleOwner, ::onUiStateChange)
}
@@ -66,7 +61,7 @@ class AuthenticationFragment : Fragment(R.layout.fragment_authentication) {
private fun onUiStateChange(uiState: OperationUiState<Unit>) = with(binding) {
logger.v { "onUiStateChange() called with: authUiState = $uiState" }
if (uiState.isSuccess) {
findNavController().popBackStack()
findNavController().navigateUp()
return
}

View File

@@ -6,6 +6,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import by.kirich1409.viewbindingdelegate.viewBinding
import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealient.R
@@ -24,6 +25,7 @@ class BaseURLFragment : Fragment(R.layout.fragment_base_url) {
private val binding by viewBinding(FragmentBaseUrlBinding::bind)
private val viewModel by viewModels<BaseURLViewModel>()
private val activityViewModel by activityViewModels<MainActivityViewModel>()
private val args by navArgs<BaseURLFragmentArgs>()
@Inject
lateinit var logger: Logger
@@ -35,10 +37,9 @@ class BaseURLFragment : Fragment(R.layout.fragment_base_url) {
viewModel.uiState.observe(viewLifecycleOwner, ::onUiStateChange)
activityViewModel.updateUiState {
it.copy(
loginButtonVisible = false,
titleVisible = true,
navigationVisible = false,
searchVisible = false
navigationVisible = !args.isOnboarding,
searchVisible = false,
checkedMenuItemId = R.id.change_url,
)
}
}

View File

@@ -38,7 +38,7 @@ class DisclaimerFragment : Fragment(R.layout.fragment_disclaimer) {
private fun navigateNext() {
logger.v { "navigateNext() called" }
findNavController().navigate(actionDisclaimerFragmentToBaseURLFragment())
findNavController().navigate(actionDisclaimerFragmentToBaseURLFragment(true))
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -58,12 +58,7 @@ class DisclaimerFragment : Fragment(R.layout.fragment_disclaimer) {
}
viewModel.startCountDown()
activityViewModel.updateUiState {
it.copy(
loginButtonVisible = false,
titleVisible = true,
navigationVisible = false,
searchVisible = false
)
it.copy(navigationVisible = false, searchVisible = false, checkedMenuItemId = null)
}
}
}

View File

@@ -50,10 +50,9 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
logger.v { "onViewCreated() called with: view = $view, savedInstanceState = $savedInstanceState" }
activityViewModel.updateUiState {
it.copy(
loginButtonVisible = true,
titleVisible = false,
navigationVisible = true,
searchVisible = true,
checkedMenuItemId = R.id.recipes_list
)
}
setupRecipeAdapter()
@@ -62,8 +61,8 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
@SuppressLint("ClickableViewAccessibility")
private fun hideKeyboardOnScroll() {
binding.recipes.setOnTouchListener { view, _ ->
view?.hideKeyboard()
binding.recipes.setOnTouchListener { _, _ ->
activityViewModel.clearSearchViewFocus()
false
}
}
@@ -85,9 +84,7 @@ class RecipesListFragment : Fragment(R.layout.fragment_recipes_list) {
private fun isNavigatingSomewhere(): Boolean {
logger.v { "isNavigatingSomewhere() called" }
val label = findNavController().currentDestination?.label
logger.d { "isNavigatingSomewhere: current destination is $label" }
return label != "fragment_recipes"
return findNavController().currentDestination?.id != R.id.recipesListFragment
}
private fun setupRecipeAdapter() {
@@ -158,18 +155,12 @@ private fun Throwable.toLoadErrorReasonText(): Int? = when (this) {
}
private fun <T : Any, VH : RecyclerView.ViewHolder> PagingDataAdapter<T, VH>.refreshErrors(): Flow<Throwable> {
return loadStateFlow
.map { it.refresh }
.valueUpdatesOnly()
.filterIsInstance<LoadState.Error>()
return loadStateFlow.map { it.refresh }.valueUpdatesOnly().filterIsInstance<LoadState.Error>()
.map { it.error }
}
private fun <T : Any, VH : RecyclerView.ViewHolder> PagingDataAdapter<T, VH>.appendPaginationEnd(): Flow<Unit> {
return loadStateFlow
.map { it.append.endOfPaginationReached }
.valueUpdatesOnly()
.filter { it }
return loadStateFlow.map { it.append.endOfPaginationReached }.valueUpdatesOnly().filter { it }
.map { }
}

View File

@@ -1,6 +1,5 @@
package gq.kirmanak.mealient.ui.recipes.info
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -8,10 +7,8 @@ import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealient.R
import gq.kirmanak.mealient.databinding.FragmentRecipeInfoBinding
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.ui.recipes.images.RecipeImageLoader
@@ -71,9 +68,6 @@ class RecipeInfoFragment : BottomSheetDialogFragment() {
instructionsAdapter.submitList(uiState.recipeInstructions)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
BottomSheetDialog(requireContext(), R.style.NoShapeBottomSheetDialog)
override fun onDestroyView() {
super.onDestroyView()
logger.v { "onDestroyView() called" }

View File

@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="288dp"
android:height="288dp"
android:viewportWidth="288"
android:viewportHeight="288">
<group
android:scaleX="7.1"
android:scaleY="7.1">
<path
android:fillColor="@android:color/black"
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0" />
</group>
</vector>

View File

@@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="288dp"
android:height="288dp"
android:viewportWidth="288"
android:viewportHeight="288">
<group
android:scaleX="3"
android:scaleY="3"
android:translateX="95"
android:translateY="95">
<path
android:fillColor="#FF9F2F"
android:pathData="M3,13.4V12.067C3,9.644 4.181,7.694 6.544,6.217C8.906,4.739 12.225,4 16.5,4C20.775,4 24.094,4.739 26.456,6.217C28.819,7.694 30,9.644 30,12.067V13.4H3ZM3,19.267V17.267C3.743,17.267 4.389,17.022 4.941,16.533C5.492,16.044 6.375,15.8 7.59,15.8C8.805,15.8 9.609,16.044 10.003,16.533C10.397,17.022 11.055,17.267 11.977,17.267C12.9,17.267 13.581,17.022 14.019,16.533C14.458,16.044 15.285,15.8 16.5,15.8C17.715,15.8 18.542,16.044 18.981,16.533C19.419,17.022 20.1,17.267 21.022,17.267C21.945,17.267 22.603,17.022 22.997,16.533C23.391,16.044 24.195,15.8 25.41,15.8C26.625,15.8 27.508,16.044 28.059,16.533C28.611,17.022 29.257,17.267 30,17.267V19.267C28.785,19.267 27.947,19.022 27.486,18.533C27.024,18.044 26.333,17.8 25.41,17.8C24.487,17.8 23.829,18.044 23.436,18.533C23.042,19.022 22.237,19.267 21.022,19.267C19.808,19.267 18.981,19.022 18.542,18.533C18.103,18.044 17.423,17.8 16.5,17.8C15.578,17.8 14.897,18.044 14.458,18.533C14.019,19.022 13.193,19.267 11.977,19.267C10.762,19.267 9.958,19.022 9.564,18.533C9.171,18.044 8.512,17.8 7.59,17.8C6.668,17.8 5.976,18.044 5.514,18.533C5.053,19.022 4.215,19.267 3,19.267V19.267ZM5.025,28C4.485,28 4.012,27.8 3.608,27.4C3.203,27 3,26.533 3,26V21.733H30V26C30,26.533 29.798,27 29.392,27.4C28.987,27.8 28.515,28 27.975,28H5.025Z" />
<path
android:fillColor="#FF9F2F"
android:pathData="M3,13.4V12.067C3,9.644 4.181,7.694 6.544,6.217C8.906,4.739 12.225,4 16.5,4C20.775,4 24.094,4.739 26.456,6.217C28.819,7.694 30,9.644 30,12.067V13.4H3ZM5.093,11.4H27.907C27.84,9.867 26.754,8.583 24.651,7.55C22.547,6.517 19.83,6 16.5,6C13.17,6 10.442,6.517 8.316,7.55C6.189,8.583 5.115,9.867 5.093,11.4ZM3,19.267V17.267C3.743,17.267 4.389,17.022 4.941,16.533C5.492,16.044 6.375,15.8 7.59,15.8C8.805,15.8 9.609,16.044 10.003,16.533C10.397,17.022 11.055,17.267 11.977,17.267C12.9,17.267 13.581,17.022 14.019,16.533C14.458,16.044 15.285,15.8 16.5,15.8C17.715,15.8 18.542,16.044 18.981,16.533C19.419,17.022 20.1,17.267 21.022,17.267C21.945,17.267 22.603,17.022 22.997,16.533C23.391,16.044 24.195,15.8 25.41,15.8C26.625,15.8 27.508,16.044 28.059,16.533C28.611,17.022 29.257,17.267 30,17.267V19.267C28.785,19.267 27.947,19.022 27.486,18.533C27.024,18.044 26.333,17.8 25.41,17.8C24.487,17.8 23.829,18.044 23.436,18.533C23.042,19.022 22.237,19.267 21.022,19.267C19.808,19.267 18.981,19.022 18.542,18.533C18.103,18.044 17.423,17.8 16.5,17.8C15.578,17.8 14.897,18.044 14.458,18.533C14.019,19.022 13.193,19.267 11.977,19.267C10.762,19.267 9.958,19.022 9.564,18.533C9.171,18.044 8.512,17.8 7.59,17.8C6.668,17.8 5.976,18.044 5.514,18.533C5.053,19.022 4.215,19.267 3,19.267ZM5.025,28C4.485,28 4.012,27.8 3.608,27.4C3.203,27 3,26.533 3,26V21.733H30V26C30,26.533 29.798,27 29.392,27.4C28.987,27.8 28.515,28 27.975,28H5.025ZM5.025,26H27.975V23.733H5.025V26ZM5.025,23.733H27.975H5.025ZM5.093,11.4H27.907H5.093Z" />
</group>
</vector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" />
<solid android:color="?colorSurfaceVariant" />
</shape>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11,19V13H5V11H11V5H13V11H19V13H13V19Z" />
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M7,21 L2,16 7,11 8.425,12.4 5.825,15H21V17H5.825L8.425,19.6ZM17,13 L15.575,11.6 18.175,9H3V7H18.175L15.575,4.4L17,3L22,8Z" />
</vector>

View File

@@ -1,31 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="2.7"
android:scaleY="2.7">
<path android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0">
<aapt:attr name="android:fillColor">
<gradient
android:endX="34.5"
android:endY="36"
android:startX="5"
android:startY="9"
android:type="linear">
<item
android:color="#FF9D76DC"
android:offset="0" />
<item
android:color="#FFDA59B6"
android:offset="0.53125" />
<item
android:color="#FFF83563"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
</group>
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="2.7"
android:scaleY="2.7">
<path
android:fillColor="@android:color/white"
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0" />
</group>
</vector>

View File

@@ -1,35 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="1.7767742"
android:scaleY="1.7767742"
android:translateX="26.46"
android:translateY="26.46">
<path
android:fillColor="#00000000"
android:pathData="M22.6128,14.1675L22.3938,14.2642L22.3318,14.4955L18.7865,27.7266C18.6268,28.3225 18.0205,28.6712 17.4379,28.5151L1.9968,24.3777C1.4142,24.2216 1.0635,23.6165 1.2232,23.0205L4.7684,9.7894L4.8304,9.5581L4.6891,9.3648C3.6072,7.8855 3.2064,6.3541 3.578,4.9673C4.0332,3.2684 5.6083,1.9554 7.9527,1.2763C10.2865,0.6002 13.2976,0.5853 16.4225,1.4226C19.5473,2.2599 22.1475,3.7784 23.8307,5.5308C25.5214,7.2911 26.229,9.2157 25.7737,10.9146C25.4021,12.3014 24.2894,13.4272 22.6128,14.1675ZM25.6576,4.9637C26.6549,5.6419 27.4994,6.3946 28.1585,7.183C29.5107,8.8003 30.0445,10.5131 29.6338,12.0457C29.2623,13.4325 28.1495,14.5583 26.4729,15.2985L26.2539,15.3952L26.1919,15.6265L22.6466,28.8576C22.4869,29.4536 21.8806,29.8023 21.298,29.6462L20.0265,29.3055C20.2507,29.0109 20.4226,28.6685 20.5243,28.2889L23.9141,15.638C25.6464,14.7352 27.0104,13.3474 27.5116,11.477C28.1292,9.1717 27.2542,6.8659 25.6576,4.9637Z"
android:strokeWidth="1"
android:strokeColor="#ffffff" />
<path
android:fillColor="#00000000"
android:pathData="M8,9C10,7 11,7.5 11.5,10"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M16,11.2341C18,9.2341 19,9.7341 19.5,12.2341"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M11,15.1199C11.9172,16.2266 12.5604,16.4972 14.0376,15.9992"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
</group>
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="1.5"
android:scaleY="1.5"
android:translateX="30"
android:translateY="30">
<path
android:fillColor="#FF9F2F"
android:pathData="M3,13.4V12.067C3,9.644 4.181,7.694 6.544,6.217C8.906,4.739 12.225,4 16.5,4C20.775,4 24.094,4.739 26.456,6.217C28.819,7.694 30,9.644 30,12.067V13.4H3ZM3,19.267V17.267C3.743,17.267 4.389,17.022 4.941,16.533C5.492,16.044 6.375,15.8 7.59,15.8C8.805,15.8 9.609,16.044 10.003,16.533C10.397,17.022 11.055,17.267 11.977,17.267C12.9,17.267 13.581,17.022 14.019,16.533C14.458,16.044 15.285,15.8 16.5,15.8C17.715,15.8 18.542,16.044 18.981,16.533C19.419,17.022 20.1,17.267 21.022,17.267C21.945,17.267 22.603,17.022 22.997,16.533C23.391,16.044 24.195,15.8 25.41,15.8C26.625,15.8 27.508,16.044 28.059,16.533C28.611,17.022 29.257,17.267 30,17.267V19.267C28.785,19.267 27.947,19.022 27.486,18.533C27.024,18.044 26.333,17.8 25.41,17.8C24.487,17.8 23.829,18.044 23.436,18.533C23.042,19.022 22.237,19.267 21.022,19.267C19.808,19.267 18.981,19.022 18.542,18.533C18.103,18.044 17.423,17.8 16.5,17.8C15.578,17.8 14.897,18.044 14.458,18.533C14.019,19.022 13.193,19.267 11.977,19.267C10.762,19.267 9.958,19.022 9.564,18.533C9.171,18.044 8.512,17.8 7.59,17.8C6.668,17.8 5.976,18.044 5.514,18.533C5.053,19.022 4.215,19.267 3,19.267V19.267ZM5.025,28C4.485,28 4.012,27.8 3.608,27.4C3.203,27 3,26.533 3,26V21.733H30V26C30,26.533 29.798,27 29.392,27.4C28.987,27.8 28.515,28 27.975,28H5.025Z" />
<path
android:fillColor="@android:color/black"
android:pathData="M3,13.4V12.067C3,9.644 4.181,7.694 6.544,6.217C8.906,4.739 12.225,4 16.5,4C20.775,4 24.094,4.739 26.456,6.217C28.819,7.694 30,9.644 30,12.067V13.4H3ZM5.093,11.4H27.907C27.84,9.867 26.754,8.583 24.651,7.55C22.547,6.517 19.83,6 16.5,6C13.17,6 10.442,6.517 8.316,7.55C6.189,8.583 5.115,9.867 5.093,11.4ZM3,19.267V17.267C3.743,17.267 4.389,17.022 4.941,16.533C5.492,16.044 6.375,15.8 7.59,15.8C8.805,15.8 9.609,16.044 10.003,16.533C10.397,17.022 11.055,17.267 11.977,17.267C12.9,17.267 13.581,17.022 14.019,16.533C14.458,16.044 15.285,15.8 16.5,15.8C17.715,15.8 18.542,16.044 18.981,16.533C19.419,17.022 20.1,17.267 21.022,17.267C21.945,17.267 22.603,17.022 22.997,16.533C23.391,16.044 24.195,15.8 25.41,15.8C26.625,15.8 27.508,16.044 28.059,16.533C28.611,17.022 29.257,17.267 30,17.267V19.267C28.785,19.267 27.947,19.022 27.486,18.533C27.024,18.044 26.333,17.8 25.41,17.8C24.487,17.8 23.829,18.044 23.436,18.533C23.042,19.022 22.237,19.267 21.022,19.267C19.808,19.267 18.981,19.022 18.542,18.533C18.103,18.044 17.423,17.8 16.5,17.8C15.578,17.8 14.897,18.044 14.458,18.533C14.019,19.022 13.193,19.267 11.977,19.267C10.762,19.267 9.958,19.022 9.564,18.533C9.171,18.044 8.512,17.8 7.59,17.8C6.668,17.8 5.976,18.044 5.514,18.533C5.053,19.022 4.215,19.267 3,19.267ZM5.025,28C4.485,28 4.012,27.8 3.608,27.4C3.203,27 3,26.533 3,26V21.733H30V26C30,26.533 29.798,27 29.392,27.4C28.987,27.8 28.515,28 27.975,28H5.025ZM5.025,26H27.975V23.733H5.025V26ZM5.025,23.733H27.975H5.025ZM5.093,11.4H27.907H5.093Z" />
</group>
</vector>

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:translateX="30"
android:translateY="30">
<path
android:fillColor="@android:color/white"
android:pathData="M3.35,20.1V17.3Q3.35,12.2 8.975,8.675Q14.6,5.15 24.05,5.15Q33.45,5.15 39.05,8.675Q44.65,12.2 44.65,17.3V20.1ZM8.2,16.4H39.8Q39.1,13.6 34.85,11.65Q30.6,9.7 24,9.7Q17.4,9.7 13.075,11.65Q8.75,13.6 8.2,16.4ZM3.35,28.9V25.2Q5,25.2 6.275,24.1Q7.55,23 10.25,23Q12.95,23 14,24.1Q15.05,25.2 17,25.2Q19.05,25.2 20.175,24.1Q21.3,23 24,23Q26.7,23 27.825,24.1Q28.95,25.2 30.95,25.2Q32.95,25.2 34,24.1Q35.05,23 37.75,23Q40.45,23 41.75,24.1Q43.05,25.2 44.65,25.2V28.9Q42,28.9 40.9,27.8Q39.8,26.7 37.8,26.7Q35.8,26.7 34.725,27.8Q33.65,28.9 30.95,28.9Q28.3,28.9 27.175,27.8Q26.05,26.7 24.05,26.7Q22,26.7 20.875,27.8Q19.75,28.9 17.05,28.9Q14.35,28.9 13.3,27.8Q12.25,26.7 10.3,26.7Q8.25,26.7 7.125,27.8Q6,28.9 3.35,28.9ZM7.9,43.75Q6.05,43.75 4.7,42.375Q3.35,41 3.35,39.2V31.9H44.65V39.2Q44.65,41 43.3,42.375Q41.95,43.75 40.1,43.75ZM7.9,39.2H40.1Q40.1,39.2 40.1,39.2Q40.1,39.2 40.1,39.2V35.65H7.9V39.2Q7.9,39.2 7.9,39.2Q7.9,39.2 7.9,39.2ZM7.9,35.65Q7.9,35.65 7.9,35.65Q7.9,35.65 7.9,35.65H40.1Q40.1,35.65 40.1,35.65Q40.1,35.65 40.1,35.65ZM8.2,16.4Q8.75,16.4 13.075,16.4Q17.4,16.4 24,16.4Q30.6,16.4 34.85,16.4Q39.1,16.4 39.8,16.4Z" />
</group>
</vector>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M4,17Q3.575,17 3.288,16.712Q3,16.425 3,16Q3,15.575 3.288,15.287Q3.575,15 4,15Q4.425,15 4.713,15.287Q5,15.575 5,16Q5,16.425 4.713,16.712Q4.425,17 4,17ZM4,13Q3.575,13 3.288,12.712Q3,12.425 3,12Q3,11.575 3.288,11.287Q3.575,11 4,11Q4.425,11 4.713,11.287Q5,11.575 5,12Q5,12.425 4.713,12.712Q4.425,13 4,13ZM4,9Q3.575,9 3.288,8.712Q3,8.425 3,8Q3,7.575 3.288,7.287Q3.575,7 4,7Q4.425,7 4.713,7.287Q5,7.575 5,8Q5,8.425 4.713,8.712Q4.425,9 4,9ZM7,17V15H21V17ZM7,13V11H21V13ZM7,9V7H21V9Z" />
</vector>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,21V19H19Q19,19 19,19Q19,19 19,19V5Q19,5 19,5Q19,5 19,5H12V3H19Q19.825,3 20.413,3.587Q21,4.175 21,5V19Q21,19.825 20.413,20.413Q19.825,21 19,21ZM10,17 L8.625,15.55 11.175,13H3V11H11.175L8.625,8.45L10,7L15,12Z" />
</vector>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M5,21Q4.175,21 3.587,20.413Q3,19.825 3,19V5Q3,4.175 3.587,3.587Q4.175,3 5,3H12V5H5Q5,5 5,5Q5,5 5,5V19Q5,19 5,19Q5,19 5,19H12V21ZM16,17 L14.625,15.55 17.175,13H9V11H17.175L14.625,8.45L16,7L21,12Z" />
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M3,18V16H21V18ZM3,13V11H21V13ZM3,8V6H21V8Z" />
</vector>

View File

@@ -1,31 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="288dp"
android:height="288dp"
android:viewportWidth="288"
android:viewportHeight="288">
<group
android:scaleX="7"
android:scaleY="7">
<path android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0">
<aapt:attr name="android:fillColor">
<gradient
android:endX="34.5"
android:endY="36"
android:startX="5"
android:startY="9"
android:type="linear">
<item
android:color="#FF9D76DC"
android:offset="0" />
<item
android:color="#FFDA59B6"
android:offset="0.53125" />
<item
android:color="#FFF83563"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
android:scaleX="7.1"
android:scaleY="7.1">
<path
android:fillColor="@android:color/white"
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0" />
</group>
</vector>

View File

@@ -1,35 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="288dp"
android:height="288dp"
android:viewportWidth="288"
android:viewportHeight="288">
<group
android:scaleX="4"
android:scaleY="4"
android:translateX="85"
android:translateY="90">
<path
android:fillColor="#00000000"
android:pathData="M22.6128,14.1675L22.3938,14.2642L22.3318,14.4955L18.7865,27.7266C18.6268,28.3225 18.0205,28.6712 17.4379,28.5151L1.9968,24.3777C1.4142,24.2216 1.0635,23.6165 1.2232,23.0205L4.7684,9.7894L4.8304,9.5581L4.6891,9.3648C3.6072,7.8855 3.2064,6.3541 3.578,4.9673C4.0332,3.2684 5.6083,1.9554 7.9527,1.2763C10.2865,0.6002 13.2976,0.5853 16.4225,1.4226C19.5473,2.2599 22.1475,3.7784 23.8307,5.5308C25.5214,7.2911 26.229,9.2157 25.7737,10.9146C25.4021,12.3014 24.2894,13.4272 22.6128,14.1675ZM25.6576,4.9637C26.6549,5.6419 27.4994,6.3946 28.1585,7.183C29.5107,8.8003 30.0445,10.5131 29.6338,12.0457C29.2623,13.4325 28.1495,14.5583 26.4729,15.2985L26.2539,15.3952L26.1919,15.6265L22.6466,28.8576C22.4869,29.4536 21.8806,29.8023 21.298,29.6462L20.0265,29.3055C20.2507,29.0109 20.4226,28.6685 20.5243,28.2889L23.9141,15.638C25.6464,14.7352 27.0104,13.3474 27.5116,11.477C28.1292,9.1717 27.2542,6.8659 25.6576,4.9637Z"
android:strokeWidth="1"
android:strokeColor="#ffffff" />
<path
android:fillColor="#00000000"
android:pathData="M8,9C10,7 11,7.5 11.5,10"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M16,11.2341C18,9.2341 19,9.7341 19.5,12.2341"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M11,15.1199C11.9172,16.2266 12.5604,16.4972 14.0376,15.9992"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
</group>
android:width="288dp"
android:height="288dp"
android:viewportWidth="288"
android:viewportHeight="288">
<group
android:scaleX="3"
android:scaleY="3"
android:translateX="95"
android:translateY="95">
<path
android:fillColor="#FF9F2F"
android:pathData="M3,13.4V12.067C3,9.644 4.181,7.694 6.544,6.217C8.906,4.739 12.225,4 16.5,4C20.775,4 24.094,4.739 26.456,6.217C28.819,7.694 30,9.644 30,12.067V13.4H3ZM3,19.267V17.267C3.743,17.267 4.389,17.022 4.941,16.533C5.492,16.044 6.375,15.8 7.59,15.8C8.805,15.8 9.609,16.044 10.003,16.533C10.397,17.022 11.055,17.267 11.977,17.267C12.9,17.267 13.581,17.022 14.019,16.533C14.458,16.044 15.285,15.8 16.5,15.8C17.715,15.8 18.542,16.044 18.981,16.533C19.419,17.022 20.1,17.267 21.022,17.267C21.945,17.267 22.603,17.022 22.997,16.533C23.391,16.044 24.195,15.8 25.41,15.8C26.625,15.8 27.508,16.044 28.059,16.533C28.611,17.022 29.257,17.267 30,17.267V19.267C28.785,19.267 27.947,19.022 27.486,18.533C27.024,18.044 26.333,17.8 25.41,17.8C24.487,17.8 23.829,18.044 23.436,18.533C23.042,19.022 22.237,19.267 21.022,19.267C19.808,19.267 18.981,19.022 18.542,18.533C18.103,18.044 17.423,17.8 16.5,17.8C15.578,17.8 14.897,18.044 14.458,18.533C14.019,19.022 13.193,19.267 11.977,19.267C10.762,19.267 9.958,19.022 9.564,18.533C9.171,18.044 8.512,17.8 7.59,17.8C6.668,17.8 5.976,18.044 5.514,18.533C5.053,19.022 4.215,19.267 3,19.267V19.267ZM5.025,28C4.485,28 4.012,27.8 3.608,27.4C3.203,27 3,26.533 3,26V21.733H30V26C30,26.533 29.798,27 29.392,27.4C28.987,27.8 28.515,28 27.975,28H5.025Z" />
<path
android:fillColor="@android:color/black"
android:pathData="M3,13.4V12.067C3,9.644 4.181,7.694 6.544,6.217C8.906,4.739 12.225,4 16.5,4C20.775,4 24.094,4.739 26.456,6.217C28.819,7.694 30,9.644 30,12.067V13.4H3ZM5.093,11.4H27.907C27.84,9.867 26.754,8.583 24.651,7.55C22.547,6.517 19.83,6 16.5,6C13.17,6 10.442,6.517 8.316,7.55C6.189,8.583 5.115,9.867 5.093,11.4ZM3,19.267V17.267C3.743,17.267 4.389,17.022 4.941,16.533C5.492,16.044 6.375,15.8 7.59,15.8C8.805,15.8 9.609,16.044 10.003,16.533C10.397,17.022 11.055,17.267 11.977,17.267C12.9,17.267 13.581,17.022 14.019,16.533C14.458,16.044 15.285,15.8 16.5,15.8C17.715,15.8 18.542,16.044 18.981,16.533C19.419,17.022 20.1,17.267 21.022,17.267C21.945,17.267 22.603,17.022 22.997,16.533C23.391,16.044 24.195,15.8 25.41,15.8C26.625,15.8 27.508,16.044 28.059,16.533C28.611,17.022 29.257,17.267 30,17.267V19.267C28.785,19.267 27.947,19.022 27.486,18.533C27.024,18.044 26.333,17.8 25.41,17.8C24.487,17.8 23.829,18.044 23.436,18.533C23.042,19.022 22.237,19.267 21.022,19.267C19.808,19.267 18.981,19.022 18.542,18.533C18.103,18.044 17.423,17.8 16.5,17.8C15.578,17.8 14.897,18.044 14.458,18.533C14.019,19.022 13.193,19.267 11.977,19.267C10.762,19.267 9.958,19.022 9.564,18.533C9.171,18.044 8.512,17.8 7.59,17.8C6.668,17.8 5.976,18.044 5.514,18.533C5.053,19.022 4.215,19.267 3,19.267ZM5.025,28C4.485,28 4.012,27.8 3.608,27.4C3.203,27 3,26.533 3,26V21.733H30V26C30,26.533 29.798,27 29.392,27.4C28.987,27.8 28.515,28 27.975,28H5.025ZM5.025,26H27.975V23.733H5.025V26ZM5.025,23.733H27.975H5.025ZM5.093,11.4H27.907H5.093Z" />
</group>
</vector>

View File

@@ -1,35 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="1.7767742"
android:scaleY="1.7767742"
android:translateX="26.46"
android:translateY="26.46">
<path
android:fillColor="#00000000"
android:pathData="M22.6128,14.1675L22.3938,14.2642L22.3318,14.4955L18.7865,27.7266C18.6268,28.3225 18.0205,28.6712 17.4379,28.5151L1.9968,24.3777C1.4142,24.2216 1.0635,23.6165 1.2232,23.0205L4.7684,9.7894L4.8304,9.5581L4.6891,9.3648C3.6072,7.8855 3.2064,6.3541 3.578,4.9673C4.0332,3.2684 5.6083,1.9554 7.9527,1.2763C10.2865,0.6002 13.2976,0.5853 16.4225,1.4226C19.5473,2.2599 22.1475,3.7784 23.8307,5.5308C25.5214,7.2911 26.229,9.2157 25.7737,10.9146C25.4021,12.3014 24.2894,13.4272 22.6128,14.1675ZM25.6576,4.9637C26.6549,5.6419 27.4994,6.3946 28.1585,7.183C29.5107,8.8003 30.0445,10.5131 29.6338,12.0457C29.2623,13.4325 28.1495,14.5583 26.4729,15.2985L26.2539,15.3952L26.1919,15.6265L22.6466,28.8576C22.4869,29.4536 21.8806,29.8023 21.298,29.6462L20.0265,29.3055C20.2507,29.0109 20.4226,28.6685 20.5243,28.2889L23.9141,15.638C25.6464,14.7352 27.0104,13.3474 27.5116,11.477C28.1292,9.1717 27.2542,6.8659 25.6576,4.9637Z"
android:strokeWidth="1"
android:strokeColor="#ffffff" />
<path
android:fillColor="#00000000"
android:pathData="M8,9C10,7 11,7.5 11.5,10"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M16,11.2341C18,9.2341 19,9.7341 19.5,12.2341"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M11,15.1199C11.9172,16.2266 12.5604,16.4972 14.0376,15.9992"
android:strokeWidth="1"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
</group>
</vector>

View File

@@ -1,19 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="122dp"
android:viewportWidth="300"
android:viewportHeight="182">
<path
android:fillColor="#FFB45B"
android:pathData="M12,0L288,0A12,12 0,0 1,300 12L300,170A12,12 0,0 1,288 182L12,182A12,12 0,0 1,0 170L0,12A12,12 0,0 1,12 0z" />
<path
android:fillColor="#ffffff"
android:fillType="evenOdd"
android:pathData="M143.099,66.442C143.099,62.729 146.319,59.72 150.291,59.72C154.263,59.72 157.483,62.729 157.483,66.442C157.483,69.566 159.797,72.16 162.783,73.079C172.437,76.051 180.19,82.937 183.891,91.728C186.462,97.836 180.878,103.413 174.251,103.413H126.331C119.703,103.413 114.12,97.836 116.691,91.728C120.392,82.937 128.144,76.051 137.799,73.079C140.785,72.16 143.099,69.566 143.099,66.442ZM146.695,69.728C146.695,70.707 147.514,71.483 148.493,71.483H152.089C153.068,71.483 153.887,70.707 153.887,69.728V66.442C153.887,64.585 152.277,63.081 150.291,63.081C148.305,63.081 146.695,64.585 146.695,66.442V69.728Z" />
<path
android:fillColor="#ffffff"
android:pathData="M112.533,106.775C111.54,106.775 110.735,107.527 110.735,108.455C110.735,109.383 111.54,110.136 112.533,110.136H188.049C189.042,110.136 189.847,109.383 189.847,108.455C189.847,107.527 189.042,106.775 188.049,106.775H112.533Z" />
<path
android:fillColor="#ffffff"
android:pathData="M117.927,113.497C116.934,113.497 116.129,114.249 116.129,115.177C116.129,116.105 116.934,116.858 117.927,116.858H182.655C183.648,116.858 184.453,116.105 184.453,115.177C184.453,114.249 183.648,113.497 182.655,113.497H117.927Z" />
android:width="200dp"
android:height="122dp"
android:viewportWidth="300"
android:viewportHeight="182">
<path
android:fillColor="?colorPrimary"
android:pathData="M12,0L288,0A12,12 0,0 1,300 12L300,170A12,12 0,0 1,288 182L12,182A12,12 0,0 1,0 170L0,12A12,12 0,0 1,12 0z" />
<path
android:fillColor="?colorOnPrimary"
android:fillType="evenOdd"
android:pathData="M143.099,66.442C143.099,62.729 146.319,59.72 150.291,59.72C154.263,59.72 157.483,62.729 157.483,66.442C157.483,69.566 159.797,72.16 162.783,73.079C172.437,76.051 180.19,82.937 183.891,91.728C186.462,97.836 180.878,103.413 174.251,103.413H126.331C119.703,103.413 114.12,97.836 116.691,91.728C120.392,82.937 128.144,76.051 137.799,73.079C140.785,72.16 143.099,69.566 143.099,66.442ZM146.695,69.728C146.695,70.707 147.514,71.483 148.493,71.483H152.089C153.068,71.483 153.887,70.707 153.887,69.728V66.442C153.887,64.585 152.277,63.081 150.291,63.081C148.305,63.081 146.695,64.585 146.695,66.442V69.728Z" />
<path
android:fillColor="?colorOnPrimary"
android:pathData="M112.533,106.775C111.54,106.775 110.735,107.527 110.735,108.455C110.735,109.383 111.54,110.136 112.533,110.136H188.049C189.042,110.136 189.847,109.383 189.847,108.455C189.847,107.527 189.042,106.775 188.049,106.775H112.533Z" />
<path
android:fillColor="?colorOnPrimary"
android:pathData="M117.927,113.497C116.934,113.497 116.129,114.249 116.129,115.177C116.129,116.105 116.934,116.858 117.927,116.858H182.655C183.648,116.858 184.453,116.105 184.453,115.177C184.453,114.249 183.648,113.497 182.655,113.497H117.927Z" />
</vector>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?attr/colorOnPrimary" />
<corners
android:topLeftRadius="@dimen/rounded_corner_size_default"
android:topRightRadius="@dimen/rounded_corner_size_default" />
</shape>

View File

@@ -2,6 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout 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"
style="?materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ui.disclaimer.DisclaimerFragment">
@@ -12,12 +13,10 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="40dp"
app:cardElevation="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/okay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:shapeAppearance="@style/ShapeAppearance.AllCornersRounded">
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/main_text"
@@ -32,10 +31,10 @@
<Button
android:id="@+id/okay"
android:clickable="false"
tools:text="Okay (3 seconds)"
style="@style/SmallMarginButton"
android:clickable="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/main_text_holder" />
app:layout_constraintTop_toBottomOf="@+id/main_text_holder"
tools:text="Okay (3 seconds)" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -33,22 +33,23 @@
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image"
android:scaleType="centerCrop"
android:layout_width="0dp"
app:shapeAppearance="@style/ShapeAppearance.AllCornersRounded"
android:layout_height="@dimen/fragment_recipe_info_image_height"
android:layout_height="0dp"
android:contentDescription="@string/content_description_fragment_recipe_info_image"
android:scaleType="centerCrop"
app:layout_constraintBottom_toTopOf="@+id/title"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/title"
app:shapeAppearance="?shapeAppearanceCornerMedium"
tools:srcCompat="@drawable/placeholder_recipe" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginHorizontal="@dimen/margin_small"
android:layout_marginTop="7dp"
android:textAppearance="?textAppearanceHeadline6"
app:layout_constraintBottom_toTopOf="@+id/description"
@@ -60,8 +61,8 @@
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_marginHorizontal="8dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_small"
android:layout_marginTop="6dp"
android:textAppearance="?textAppearanceBody2"
app:layout_constraintBottom_toTopOf="@+id/ingredients_holder"
@@ -72,13 +73,12 @@
<com.google.android.material.card.MaterialCardView
android:id="@+id/ingredients_holder"
style="?materialCardViewFilledStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginHorizontal="@dimen/margin_small"
android:layout_marginTop="11dp"
android:layout_marginBottom="20dp"
app:shapeAppearance="@style/ShapeAppearance.AllCornersRounded"
app:cardElevation="10dp"
app:layout_constraintBottom_toTopOf="@+id/instructions_header"
app:layout_constraintEnd_toStartOf="@+id/end_guide"
app:layout_constraintStart_toEndOf="@+id/start_guide"
@@ -93,8 +93,8 @@
android:id="@+id/ingredients_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="17dp"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_medium"
android:text="@string/fragment_recipe_info_ingredients_header"
android:textAppearance="?textAppearanceHeadline6" />
@@ -102,7 +102,7 @@
android:id="@+id/ingredients_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginHorizontal="@dimen/margin_small"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/view_holder_ingredient" />
@@ -121,7 +121,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="35dp"
android:layout_marginEnd="8dp"
android:layout_marginEnd="@dimen/margin_small"
android:text="@string/fragment_recipe_info_instructions_header"
android:textAppearance="?textAppearanceHeadline6"
app:layout_constraintBottom_toTopOf="@+id/instructions_list"
@@ -133,11 +133,11 @@
android:id="@+id/instructions_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/end_guide"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@+id/instructions_header"
app:layout_constraintStart_toEndOf="@+id/start_guide"
app:layout_constraintTop_toBottomOf="@+id/instructions_header"
tools:itemCount="2"
tools:listitem="@layout/view_holder_instruction" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer"
style="?drawerLayoutStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.MainActivity"
@@ -10,21 +11,20 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_medium"
android:background="@drawable/bg_toolbar"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
<gq.kirmanak.mealient.ui.activity.ToolbarView
android:id="@+id/toolbar"
style="@style/Widget.MaterialComponents.Toolbar.Primary"
android:theme="@style/ThemeOverlay.Toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|snap|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
@@ -33,6 +33,7 @@
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/margin_small"
app:defaultNavHost="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -42,5 +43,6 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/view_navigation_drawer_header"
app:menu="@menu/navigation_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

View File

@@ -2,11 +2,10 @@
<com.google.android.material.card.MaterialCardView 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"
style="?materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_margin="8dp"
app:shapeAppearance="@style/ShapeAppearance.AllCornersRounded"
app:cardElevation="10dp"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_small">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"

View File

@@ -2,13 +2,12 @@
<com.google.android.material.card.MaterialCardView 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"
style="?materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:shapeAppearance="@style/ShapeAppearance.AllCornersRounded"
android:layout_marginVertical="7dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="19dp"
app:cardElevation="8dp">
android:layout_marginVertical="@dimen/margin_small"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
@@ -31,19 +30,20 @@
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/image"
android:layout_width="300dp"
android:layout_height="@dimen/height_view_holder_recipe_image"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="15dp"
app:shapeAppearance="@style/ShapeAppearance.AllCornersRounded"
android:layout_marginTop="20dp"
android:layout_marginEnd="13dp"
android:contentDescription="@string/content_description_view_holder_recipe_image"
android:scaleType="centerCrop"
app:layout_constraintBottom_toTopOf="@+id/name"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
app:shapeAppearance="?shapeAppearanceCornerMedium"
tools:srcCompat="@drawable/placeholder_recipe" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_small"
android:text="@string/menu_navigation_drawer_header"
android:textAppearance="?attr/textAppearanceHeadlineSmall"
android:textColor="?attr/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<merge 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"
tools:context=".ui.activity.ToolbarView"
tools:layout_height="wrap_content"
tools:layout_width="match_parent"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<ImageView
android:id="@+id/navigation_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_small"
android:contentDescription="@string/view_toolbar_navigation_icon_content_description"
android:src="@drawable/ic_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/search_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_small"
android:background="@null"
android:hint="@string/search_recipes_hint"
android:importantForAutofill="no"
android:inputType="textFilter"
android:textAppearance="?textAppearanceBodyLarge"
android:textColor="?colorOnSurfaceVariant"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/navigation_icon"
app:layout_constraintTop_toTopOf="parent" />
</merge>

View File

@@ -2,23 +2,10 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/login"
android:contentDescription="@string/menu_main_toolbar_content_description_login"
android:title="@string/menu_main_toolbar_login"
app:showAsAction="ifRoom" />
<item
android:id="@+id/logout"
android:contentDescription="@string/menu_main_toolbar_content_description_logout"
android:title="@string/menu_main_toolbar_logout"
app:showAsAction="never" />
<item
android:id="@+id/search_recipe_action"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/search_recipes_hint"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom" />
app:showAsAction="always" />
</menu>

View File

@@ -2,13 +2,31 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/recipes_list"
android:title="@string/menu_bottom_navigation_recipes_list" />
android:checkable="true"
android:icon="@drawable/ic_list"
android:title="@string/menu_navigation_drawer_recipes_list" />
<item
android:id="@+id/add_recipe"
android:title="@string/menu_bottom_navigation_add_recipe" />
android:checkable="true"
android:icon="@drawable/ic_add"
android:title="@string/menu_navigation_drawer_add_recipe" />
<item
android:id="@+id/change_url"
android:title="@string/menu_bottom_navigation_change_url" />
android:checkable="true"
android:icon="@drawable/ic_change"
android:title="@string/menu_navigation_drawer_change_url" />
<item
android:id="@+id/login"
android:checkable="true"
android:icon="@drawable/ic_login"
android:title="@string/menu_navigation_drawer_login" />
<item
android:id="@+id/logout"
android:icon="@drawable/ic_logout"
android:title="@string/menu_navigation_drawer_logout" />
</menu>

View File

@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>

View File

@@ -51,8 +51,10 @@
<action
android:id="@+id/action_baseURLFragment_to_recipesListFragment"
app:destination="@id/recipesListFragment"
app:popUpTo="@id/nav_graph"
app:popUpToInclusive="true" />
app:popUpTo="@id/nav_graph" />
<argument
android:name="isOnboarding"
app:argType="boolean" />
</fragment>
<fragment
@@ -63,12 +65,12 @@
<action
android:id="@+id/action_global_authenticationFragment"
app:destination="@id/authenticationFragment"
app:popUpTo="@id/recipesListFragment" />
app:destination="@id/authenticationFragment" />
<action
android:id="@+id/action_global_recipesListFragment"
app:destination="@id/recipesListFragment" />
app:destination="@id/recipesListFragment"
app:popUpTo="@id/nav_graph" />
<action
android:id="@+id/action_global_addRecipeFragment"

View File

@@ -1,32 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.Material3.Dark.NoActionBar">
<item name="colorPrimary">@color/md_theme_dark_primary</item>
<item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_theme_dark_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_theme_dark_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_theme_dark_secondary</item>
<item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_dark_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_dark_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_theme_dark_tertiary</item>
<item name="colorOnTertiary">@color/md_theme_dark_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_theme_dark_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_theme_dark_onTertiaryContainer</item>
<item name="colorError">@color/md_theme_dark_error</item>
<item name="colorErrorContainer">@color/md_theme_dark_errorContainer</item>
<item name="colorOnError">@color/md_theme_dark_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_dark_onErrorContainer</item>
<item name="android:colorBackground">@color/md_theme_dark_background</item>
<item name="colorOnBackground">@color/md_theme_dark_onBackground</item>
<item name="colorSurface">@color/md_theme_dark_surface</item>
<item name="colorOnSurface">@color/md_theme_dark_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_dark_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_dark_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_dark_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_dark_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_dark_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_dark_primaryInverse</item>
<item name="android:overScrollMode">never</item>
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<item name="postSplashScreenTheme">@style/AppTheme</item>
<item name="windowSplashScreenBackground">@android:color/black</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_screen</item>
</style>
</resources>

View File

@@ -5,7 +5,7 @@
<string name="fragment_authentication_input_hint_url">URL сервера</string>
<string name="fragment_authentication_button_login">Войти</string>
<string name="content_description_view_holder_recipe_image">Изображение готового блюда</string>
<string name="menu_main_toolbar_logout">Выйти</string>
<string name="menu_navigation_drawer_logout">Выйти</string>
<string name="view_holder_recipe_text_placeholder">Загрузка</string>
<string name="fragment_recipe_info_ingredients_header">Ингредиенты</string>
<string name="fragment_recipe_info_instructions_header">Инструкции</string>
@@ -21,11 +21,11 @@
<string name="fragment_authentication_unknown_error">Что-то пошло не так, попробуйте еще раз.</string>
<string name="fragment_base_url_malformed_url">Проверьте формат URL: %s</string>
<string name="fragment_base_url_save">Продолжить</string>
<string name="menu_main_toolbar_login">Войти</string>
<string name="menu_navigation_drawer_login">Войти</string>
<string name="fragment_add_recipe_recipe_name">Название рецепта</string>
<string name="fragment_add_recipe_recipe_description">Описание</string>
<string name="menu_bottom_navigation_recipes_list">Рецепты</string>
<string name="menu_bottom_navigation_add_recipe">Добавить рецепт</string>
<string name="menu_navigation_drawer_recipes_list">Рецепты</string>
<string name="menu_navigation_drawer_add_recipe">Добавить рецепт</string>
<string name="fragment_add_recipe_recipe_yield">Количество порций</string>
<string name="fragment_add_recipe_save_button">Сохранить рецепт</string>
<string name="fragment_add_recipe_new_instruction">Добавить шаг</string>
@@ -47,6 +47,7 @@
<string name="fragment_recipes_load_failure_toast_unexpected_response">неожиданный ответ</string>
<string name="fragment_recipes_load_failure_toast_no_connection">нет соединения</string>
<string name="fragment_recipes_load_failure_toast_no_reason">Ошибка загрузки.</string>
<string name="menu_bottom_navigation_change_url">Сменить URL</string>
<string name="menu_navigation_drawer_change_url">Сменить URL</string>
<string name="search_recipes_hint">Найти рецепты</string>
<string name="view_toolbar_navigation_icon_content_description">Открыть меню навигации</string>
</resources>

View File

@@ -1,58 +0,0 @@
<resources>
<color name="md_theme_light_primary">#7743B5</color>
<color name="md_theme_light_onPrimary">#FFFFFF</color>
<color name="md_theme_light_primaryContainer">#EFDBFF</color>
<color name="md_theme_light_onPrimaryContainer">#290054</color>
<color name="md_theme_light_secondary">#655A70</color>
<color name="md_theme_light_onSecondary">#FFFFFF</color>
<color name="md_theme_light_secondaryContainer">#ECDDF7</color>
<color name="md_theme_light_onSecondaryContainer">#201829</color>
<color name="md_theme_light_tertiary">#805159</color>
<color name="md_theme_light_onTertiary">#FFFFFF</color>
<color name="md_theme_light_tertiaryContainer">#FFD9DF</color>
<color name="md_theme_light_onTertiaryContainer">#321118</color>
<color name="md_theme_light_error">#BA1B1B</color>
<color name="md_theme_light_errorContainer">#FFDAD4</color>
<color name="md_theme_light_onError">#FFFFFF</color>
<color name="md_theme_light_onErrorContainer">#410001</color>
<color name="md_theme_light_background">#FFFBFC</color>
<color name="md_theme_light_onBackground">#1D1B1E</color>
<color name="md_theme_light_surface">#FFFBFC</color>
<color name="md_theme_light_onSurface">#1D1B1E</color>
<color name="md_theme_light_surfaceVariant">#E8DFEB</color>
<color name="md_theme_light_onSurfaceVariant">#4A454E</color>
<color name="md_theme_light_outline">#7B757E</color>
<color name="md_theme_light_inverseOnSurface">#F5EFF3</color>
<color name="md_theme_light_inverseSurface">#322F33</color>
<color name="md_theme_light_inversePrimary">#DBB8FF</color>
<color name="md_theme_light_shadow">#000000</color>
<color name="md_theme_light_primaryInverse">#DBB8FF</color>
<color name="md_theme_dark_primary">#DBB8FF</color>
<color name="md_theme_dark_onPrimary">#460283</color>
<color name="md_theme_dark_primaryContainer">#5E289B</color>
<color name="md_theme_dark_onPrimaryContainer">#EFDBFF</color>
<color name="md_theme_dark_secondary">#CFC1DA</color>
<color name="md_theme_dark_onSecondary">#362D40</color>
<color name="md_theme_dark_secondaryContainer">#4D4357</color>
<color name="md_theme_dark_onSecondaryContainer">#ECDDF7</color>
<color name="md_theme_dark_tertiary">#F2B7C0</color>
<color name="md_theme_dark_onTertiary">#4B252C</color>
<color name="md_theme_dark_tertiaryContainer">#653A42</color>
<color name="md_theme_dark_onTertiaryContainer">#FFD9DF</color>
<color name="md_theme_dark_error">#FFB4A9</color>
<color name="md_theme_dark_errorContainer">#930006</color>
<color name="md_theme_dark_onError">#680003</color>
<color name="md_theme_dark_onErrorContainer">#FFDAD4</color>
<color name="md_theme_dark_background">#1D1B1E</color>
<color name="md_theme_dark_onBackground">#E7E1E5</color>
<color name="md_theme_dark_surface">#1D1B1E</color>
<color name="md_theme_dark_onSurface">#E7E1E5</color>
<color name="md_theme_dark_surfaceVariant">#4A454E</color>
<color name="md_theme_dark_onSurfaceVariant">#CCC4CF</color>
<color name="md_theme_dark_outline">#958E98</color>
<color name="md_theme_dark_inverseOnSurface">#1D1B1E</color>
<color name="md_theme_dark_inverseSurface">#E7E1E5</color>
<color name="md_theme_dark_inversePrimary">#7743B5</color>
<color name="md_theme_dark_shadow">#000000</color>
<color name="md_theme_dark_primaryInverse">#7743B5</color>
</resources>

View File

@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="margin_small">8dp</dimen>
<dimen name="height_view_holder_recipe_image">182dp</dimen>
<dimen name="fragment_recipe_info_image_height">@dimen/height_view_holder_recipe_image</dimen>
<dimen name="main_activity_toolbar_corner_radius">32dp</dimen>
<dimen name="rounded_corner_size_default">15dp</dimen>
<dimen name="margin_medium">16dp</dimen>
</resources>

View File

@@ -5,8 +5,7 @@
<string name="fragment_authentication_input_hint_url">Server URL</string>
<string name="fragment_authentication_button_login">Login</string>
<string name="content_description_view_holder_recipe_image">Picture of the cooked meal</string>
<string name="menu_main_toolbar_content_description_logout" translatable="false">@string/menu_main_toolbar_logout</string>
<string name="menu_main_toolbar_logout">Logout</string>
<string name="menu_navigation_drawer_logout">Logout</string>
<string name="view_holder_recipe_text_placeholder">Loading…</string>
<string name="content_description_fragment_recipe_info_image" translatable="false">@string/content_description_view_holder_recipe_image</string>
<string name="fragment_recipe_info_ingredients_header">Ingredients</string>
@@ -18,8 +17,7 @@
<string name="fragment_base_url_malformed_url">Check URL format: %s</string>
<string name="fragment_base_url_save">Proceed</string>
<string name="fragment_base_url_unknown_error" translatable="false">@string/fragment_authentication_unknown_error</string>
<string name="menu_main_toolbar_content_description_login" translatable="false">@string/menu_main_toolbar_login</string>
<string name="menu_main_toolbar_login">Login</string>
<string name="menu_navigation_drawer_login">Login</string>
<string name="fragment_disclaimer_button_okay">Okay</string>
<string name="view_holder_recipe_instructions_step">Step: %d</string>
<string name="fragment_authentication_email_input_empty">E-mail can\'t be empty</string>
@@ -28,8 +26,8 @@
<string name="fragment_authentication_unknown_error">Something went wrong, please try again.</string>
<string name="fragment_add_recipe_recipe_name">Recipe name</string>
<string name="fragment_add_recipe_recipe_description">Description</string>
<string name="menu_bottom_navigation_add_recipe">Add recipe</string>
<string name="menu_bottom_navigation_recipes_list">Recipes</string>
<string name="menu_navigation_drawer_add_recipe">Add recipe</string>
<string name="menu_navigation_drawer_recipes_list">Recipes</string>
<string name="fragment_add_recipe_recipe_yield">Recipe yield</string>
<string name="fragment_add_recipe_save_button">Save recipe</string>
<string name="fragment_add_recipe_new_instruction">New step</string>
@@ -51,6 +49,8 @@
<string name="fragment_recipes_load_failure_toast_unauthorized">unauthorized</string>
<string name="fragment_recipes_load_failure_toast_unexpected_response">unexpected response</string>
<string name="fragment_recipes_load_failure_toast_no_connection">no connection</string>
<string name="menu_bottom_navigation_change_url">Change URL</string>
<string name="menu_navigation_drawer_change_url">Change URL</string>
<string name="search_recipes_hint">Search recipes</string>
<string name="menu_navigation_drawer_header" translatable="false">@string/app_name</string>
<string name="view_toolbar_navigation_icon_content_description">Open navigation drawer</string>
</resources>

View File

@@ -13,22 +13,6 @@
<item name="android:layout_margin">@dimen/margin_small</item>
</style>
<style name="ShapeAppearance.AllCornersRounded" parent="ShapeAppearance.Material3.LargeComponent">
<item name="cornerSize">@dimen/rounded_corner_size_default</item>
</style>
<!-- This is a workaround to support always round corners of the bottom sheet
See more at https://github.com/material-components/material-components-android/pull/437#issuecomment-852461685 -->
<style name="NoShapeBottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
<item name="bottomSheetStyle">@style/NoShapeBottomSheet</item>
</style>
<style name="NoShapeBottomSheet" parent="Widget.Material3.BottomSheet.Modal">
<item name="shapeAppearance">@null</item>
<item name="shapeAppearanceOverlay">@null</item>
<item name="android:background">@drawable/recipe_info_background</item>
</style>
<style name="IndeterminateProgress">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>

View File

@@ -4,40 +4,13 @@
<item name="postSplashScreenTheme">@style/AppTheme</item>
<item name="windowSplashScreenBackground">@android:color/white</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_screen</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="AppTheme" parent="Theme.Material3.Light.NoActionBar">
<item name="colorPrimary">@color/md_theme_light_primary</item>
<item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
<item name="colorSecondary">@color/md_theme_light_secondary</item>
<item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
<item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
<item name="colorTertiary">@color/md_theme_light_tertiary</item>
<item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
<item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
<item name="colorError">@color/md_theme_light_error</item>
<item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
<item name="colorOnError">@color/md_theme_light_onError</item>
<item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
<item name="android:colorBackground">@color/md_theme_light_background</item>
<item name="colorOnBackground">@color/md_theme_light_onBackground</item>
<item name="colorSurface">@color/md_theme_light_surface</item>
<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
<item name="colorOutline">@color/md_theme_light_outline</item>
<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
<item name="colorPrimaryInverse">@color/md_theme_light_primaryInverse</item>
<item name="android:overScrollMode">never</item>
<style name="AppTheme" parent="Theme.Material3.DynamicColors.DayNight">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<style name="ThemeOverlay.Toolbar" parent="ThemeOverlay.MaterialComponents.Toolbar.Primary">
<item name="android:editTextColor">?colorOnPrimary</item>
<item name="android:textColorHint">?colorOnPrimary</item>
</style>
</resources>
</resources>