Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Gradle JDK: JetBrains Runtime version 17.0.6/...**
0. Jetpack [Read here](https://developer.android.com/jetpack/getting-started)
0. Hilt & Jetpack [Read here](https://developer.android.com/jetpack/androidx/releases/hilt)
0. Compose [Read here](https://developer.android.com/jetpack/androidx/releases/compose-ui)
0. Compose State [Read here](https://developer.android.com/jetpack/compose/state)
0. MVVM [Read here](https://blog.mindorks.com/mvc-mvp-mvvm-architecture-in-android)
0. View Models [Read here](https://developer.android.com/topic/libraries/architecture/viewmodel)
0. DataModel [Read here](https://developer.android.com/topic/libraries/architecture/viewmodel)
Expand Down
33 changes: 23 additions & 10 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,39 @@ android {
dependencies {

implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))

implementation "androidx.navigation:navigation-runtime-ktx:$nav_version"

/*Compose*/
implementation 'androidx.compose.material:material'
implementation 'androidx.activity:activity-compose:1.5.1'
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.navigation:navigation-runtime-ktx:2.5.3'

/*Dependency injection library*/
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

/*Dependency injection and compose library*/
implementation "androidx.hilt:hilt-navigation-compose:$hilt_nav_version"

/*ViewModel libraries*/
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.compose.runtime:runtime-livedata:$livedata_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-compose:$uistate_version"

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'

/*Dependency injection library*/
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

/*Dependency injection and compose library*/
implementation "androidx.hilt:hilt-navigation-compose:1.0.0"
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<activity
android:name=".MainActivity"
android:exported="true"
android:screenOrientation="portrait"
android:label="@string/app_name"
android:theme="@style/Theme.FlickrApp">
<intent-filter>
Expand Down
9 changes: 3 additions & 6 deletions app/src/main/java/com/example/flickrapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -20,12 +19,10 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
FlickrAppTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
color = MaterialTheme.colors.background
) {
// Greeting("Android")
NavigationApp()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,101 @@
package com.example.flickrapp.presentation

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update

class FlickrViewModel(): ViewModel() {
}

private val _searchText = MutableStateFlow("")
val searchText = _searchText.asStateFlow()


private val _isSearching = MutableStateFlow(false)
val isSearching = _isSearching.asStateFlow()

private val _picture = MutableStateFlow(pictureList)
val pictures = searchText
.debounce(500L)
.onEach { _isSearching.update { true } }
.combine(_picture) { text, pictureMatches ->
if(text.isBlank()) {
pictureMatches
} else {
delay(500L)
pictureMatches.filter {
it.doesMatchSearchQuery(text)
}
}
}
.onEach { _isSearching.update { false } }
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(1000),
_picture.value
)
fun onSearchTextChange(text: String) {
_searchText.update { text }
}
}

private val pictureList = listOf(
Picture(
name = "sunset",
),
Picture(
name = "forest",
),
Picture(
name = "dog",
),
Picture(
name = "food",
),
Picture(
name = "travel",
),
Picture(
name = "computer",
),
Picture(
name = "cat",
),
Picture(
name = "shoes",
),
Picture(
name = "selfie",
),
Picture(
name = "beach",
),
Picture(
name = "house",
),
Picture(
name = "cars",
),
)

data class Picture(
val name: String,
) {
fun doesMatchSearchQuery(query: String): Boolean {
val matchingCombinations = listOf(
"$name",
"${name.first()}}",
)

return matchingCombinations.any {
it.contains(query, ignoreCase = true)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,74 @@
package com.example.flickrapp.presentation

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import com.example.flickrapp.R
import com.example.flickrapp.presentation.home.ImagesGrid
import com.example.flickrapp.presentation.utils.Loading
import com.example.flickrapp.ui.theme.AppDimension
import com.example.flickrapp.utils.TopAppBarFlickr

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun FlickrHomeScreen(navController: NavController, viewModel: FlickrViewModel) {
Text(
text = "Hello Flickr!",
modifier = Modifier.fillMaxSize(),
color = Color.Red
)
val searchText by viewModel.searchText.collectAsStateWithLifecycle()
val isSearching by viewModel.isSearching.collectAsStateWithLifecycle()
val pictures by viewModel.pictures.collectAsStateWithLifecycle()


Column() {
Row(
modifier = Modifier.fillMaxWidth()
) {
TopAppBarFlickr(title = stringResource(R.string.app_name)) {
navController.backQueue
}
}
Row(
modifier = Modifier
.fillMaxSize()
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(AppDimension.smallPadding)
) {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
value = searchText,
onValueChange = { viewModel.onSearchTextChange(it) },
trailingIcon = {
Icon(
imageVector = Icons.Default.Search,
contentDescription = stringResource(R.string.search)
)
},
placeholder = { Text(text = stringResource(R.string.search)) }
)
Spacer(modifier = Modifier.height(AppDimension.normalPadding))
if (isSearching) {
Loading()
} else {
ImagesGrid(pictures)
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.example.flickrapp.presentation.home

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.example.flickrapp.R
import com.example.flickrapp.presentation.Picture
import com.example.flickrapp.ui.theme.AppDimension
import com.example.flickrapp.ui.theme.ExtendedTheme
import kotlin.random.Random


@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ImagesGrid(pictures: List<Picture>) {
LazyVerticalStaggeredGrid(
modifier = Modifier
.fillMaxSize(),
columns = StaggeredGridCells.Fixed(2),
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(pictures.size) {
ItemBox(pictures[it])
}
}
}

@Composable
fun ItemBox(item: Picture) {
Box(
modifier = Modifier
.fillMaxSize()
.height(Random.nextInt(100, 300).dp)
.clip(RoundedCornerShape(AppDimension.smallPadding))
.background(
Color(
Random.nextLong(0xFFFFFFFF)
).copy(alpha = 1f)
),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(
id = R.drawable.ic_launcher_foreground,
),
contentDescription = "",
modifier = Modifier
.align(Alignment.Center)
.clip(RoundedCornerShape(AppDimension.normalPadding))
.background(ExtendedTheme.colors.primary)
.size(80.dp),
contentScale = ContentScale.Crop,
)

Text(
text = "${item.name}",
modifier = Modifier
.fillMaxSize()
.padding(AppDimension.normalPadding),
textAlign = TextAlign.Center
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.flickrapp.presentation.utils

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

@Composable
fun Loading(){
Box(modifier = Modifier.fillMaxSize()) {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/example/flickrapp/ui/theme/AppDimension.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.flickrapp.ui.theme

import androidx.compose.ui.unit.dp

class AppDimension {
companion object {
val defaultPadding = 0.dp
val xSmallPadding = 4.dp
val smallPadding = 8.dp
val normalPadding = 16.dp
}
}
Loading