Skip to content

Commit

Permalink
Merge pull request #42 from ImaginativeShohag/dev
Browse files Browse the repository at this point in the history
Add new confetti `Lottie` example
  • Loading branch information
ImaginativeShohag authored Jul 31, 2024
2 parents a13b819 + db44f8b commit 03e3712
Show file tree
Hide file tree
Showing 245 changed files with 218 additions and 153 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Feel free to request features or suggestions for improvements.
- [ ] List with `LazyGrid`
- [ ] Paging with `LazyGrid`
- [ ] Update to new storage permission
- [ ] Auto Theme mode from system
- [x] Auto Theme mode from system
- [ ] Create color ready for dark and light mode
- [ ] AlarmManager example
- [ ] Update `CheckBox` code (see example from AOSP)
Expand All @@ -99,8 +99,9 @@ Feel free to request features or suggestions for improvements.
- [x] Check map example issue: on click freeze
- [ ] New: File browser using MediaStore
- [ ] Get sidebar from Emudi app (https://www.youtube.com/watch?v=HNSKJIQtb4c)
- [ ] Update `popBackStack()`
- [x] Update `popBackStack()`
- [ ] Migrate ExoPlayer: https://developer.android.com/media/media3/exoplayer/migration-guide
- [ ] Update all `LaunchedEffect` with lambda issue using `rememberUpdatedState`: https://developer.android.com/develop/ui/compose/side-effects#rememberupdatedstate

# Note

Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ android {
minSdk = BuildConfigConst.minSdk
targetSdk = BuildConfigConst.targetSdk
versionCode = (findProperty("android.injected.version.code") as? String)?.toIntOrNull() ?: 1
versionName = "7.0.0.${getCurrentDateAsYYMMDD()}" // Major.Minor.Patch.YYMMDD
versionName = "7.1.0.${getCurrentDateAsYYMMDD()}" // Major.Minor.Patch.YYMMDD
vectorDrawables.useSupportLibrary = true

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ import android.app.Application
import com.google.android.gms.maps.MapsInitializer
import com.google.android.gms.maps.OnMapsSdkInitializedCallback
import com.onesignal.OneSignal
import com.onesignal.debug.LogLevel
import dagger.hilt.android.HiltAndroidApp
import org.imaginativeworld.whynotcompose.utils.onesignal.MyNotificationOpenedHandler
import org.imaginativeworld.whynotcompose.utils.onesignal.MyNotificationWillShowInForegroundHandler
import org.imaginativeworld.whynotcompose.utils.onesignal.MyNotificationClickListener
import org.imaginativeworld.whynotcompose.utils.onesignal.MyNotificationLifecycleListener
import timber.log.Timber

@HiltAndroidApp
Expand All @@ -45,19 +46,22 @@ class App :
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())

OneSignal.setLogLevel(OneSignal.LOG_LEVEL.VERBOSE, OneSignal.LOG_LEVEL.NONE)
OneSignal.Debug.logLevel = LogLevel.VERBOSE
} else {
OneSignal.Debug.logLevel = LogLevel.NONE
}

// New Map Renderer
MapsInitializer.initialize(applicationContext, MapsInitializer.Renderer.LATEST, this)

// OneSignal
OneSignal.initWithContext(this)
OneSignal.setAppId(ONESIGNAL_APP_ID)
OneSignal.setNotificationWillShowInForegroundHandler(
MyNotificationWillShowInForegroundHandler(this)
OneSignal.initWithContext(this, ONESIGNAL_APP_ID)
OneSignal.Notifications.addForegroundLifecycleListener(
MyNotificationLifecycleListener(this)
)
OneSignal.Notifications.addClickListener(
MyNotificationClickListener(this)
)
OneSignal.setNotificationOpenedHandler(MyNotificationOpenedHandler(this))
}

override fun onMapsSdkInitialized(renderer: MapsInitializer.Renderer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ import org.imaginativeworld.whynotcompose.ui.screens.tutorial.navdatapass.NavDat
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.navdatapass.NavDataPassOneScreen
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.navdatapass.NavDataPassThreeScreen
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.navdatapass.NavDataPassTwoScreen
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.onesignalandbroadcast.OneSignalAndBroadcastScreen
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.permission.PermissionScreen
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.reactivemodel.ReactiveModelScreen
import org.imaginativeworld.whynotcompose.ui.screens.tutorial.reactivemodel.ReactiveModelViewModel
Expand Down Expand Up @@ -232,7 +231,6 @@ sealed class TutorialsScreen(val route: String) {
data object TutorialPermission : TutorialsScreen("tutorial/permission")
data object TutorialDataFetchAndPaging : TutorialsScreen("tutorial/data-fetch-and-paging")
data object TutorialTicTacToe : TutorialsScreen("tutorial/tic-tac-toe")
data object TutorialOneSignalAndBroadcast : TutorialsScreen("tutorial/onesignal-and-broadcast")
data object TutorialExoPlayer : TutorialsScreen("tutorial/exoplayer")
data object TutorialCMS : TutorialsScreen("tutorial/cms")
data object TutorialDeepLink : TutorialsScreen("tutorial/deep-link")
Expand Down Expand Up @@ -949,14 +947,6 @@ private fun NavGraphBuilder.addTutorialIndexScreen(
)
}

composable(TutorialsScreen.TutorialOneSignalAndBroadcast.route) {
OneSignalAndBroadcastScreen(
goBack = {
navController.popBackStackOrIgnore()
}
)
}

composable(TutorialsScreen.TutorialExoPlayer.route) {
ExoPlayerScreen(
goBack = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,6 @@ data class Tutorial(
route = TutorialsScreen.TutorialTicTacToe,
level = TutorialLevel.Advanced
),
Tutorial(
name = "OneSignal and Broadcast",
description = "Send notification with data using `OneSignal`, then send broadcast when a new notification comes. Finally, receive the broadcast and data from Compose UI.",
route = TutorialsScreen.TutorialOneSignalAndBroadcast,
level = TutorialLevel.Intermediate
),
Tutorial(
name = "ExoPlayer",
description = "Example usage of `ExoPlayer` with Compose.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@

package org.imaginativeworld.whynotcompose.ui.screens.tutorial.lottie

import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand All @@ -41,11 +41,14 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.RocketLaunch
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand All @@ -56,6 +59,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
Expand All @@ -65,6 +69,7 @@ import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.rememberLottieAnimatable
import com.airbnb.lottie.compose.rememberLottieComposition
import com.airbnb.lottie.compose.resetToBeginning
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.imaginativeworld.whynotcompose.R
import org.imaginativeworld.whynotcompose.common.compose.compositions.AppComponent
Expand All @@ -81,7 +86,7 @@ fun LottieScreen(

@PreviewLightDark
@Composable
private fun LottieScreenSkeletonPreviewDark() {
private fun LottieScreenSkeletonPreview() {
AppTheme {
LottieScreenSkeleton()
}
Expand All @@ -92,6 +97,24 @@ private fun LottieScreenSkeletonPreviewDark() {
fun LottieScreenSkeleton(
goBack: () -> Unit = {}
) {
val scope = rememberCoroutineScope()

// ----------------------------------------------------------------

val loadingComposition by rememberLottieComposition(
LottieCompositionSpec.RawRes(R.raw.loading)
)
var showLoading by remember { mutableStateOf(false) }

// ----------------------------------------------------------------

val compositionConfetti by rememberLottieComposition(
LottieCompositionSpec.RawRes(R.raw.confetti)
)
val confettiAnimatable = rememberLottieAnimatable()

// ----------------------------------------------------------------

Scaffold(
Modifier
.navigationBarsPadding()
Expand All @@ -107,8 +130,8 @@ fun LottieScreenSkeleton(
Column(
Modifier
.padding(innerPadding)
.fillMaxSize()
.verticalScroll(rememberScrollState())
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
Modifier.padding(
Expand Down Expand Up @@ -162,7 +185,6 @@ fun LottieScreenSkeleton(
)

Box(Modifier.size(48.dp)) {
val scope = rememberCoroutineScope()
var isFavorite by remember { mutableStateOf(false) }
val compositionHeart by rememberLottieComposition(
LottieCompositionSpec.RawRes(
Expand All @@ -174,37 +196,103 @@ fun LottieScreenSkeleton(
LottieAnimation(
modifier = Modifier
.requiredSize(96.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = {
compositionHeart ?: return@clickable

scope.launch {
if (isFavorite) {
heartAnimatable.resetToBeginning()
} else {
heartAnimatable.animate(
compositionHeart,
continueFromPreviousAnimate = false
)
}
.pointerInput(Unit) {
detectTapGestures(
onPress = {
compositionHeart ?: return@detectTapGestures

scope.launch {
if (isFavorite) {
heartAnimatable.resetToBeginning()
} else {
heartAnimatable.animate(
compositionHeart,
continueFromPreviousAnimate = false
)
}

isFavorite = !isFavorite
isFavorite = !isFavorite
}
}
}
),
)
},
composition = compositionHeart,
progress = { heartAnimatable.progress }
)
}
}
}

Spacer(Modifier.weight(1f))

// ----------------------------------------------------------------

Box(
contentAlignment = Alignment.Center
) {
Crossfade(
modifier = Modifier
.fillMaxWidth()
.height(128.dp),
targetState = showLoading,
label = "Launch button"
) {
when (it) {
true -> LottieAnimation(
modifier = Modifier.height(128.dp),
composition = loadingComposition,
iterations = LottieConstants.IterateForever
)

false -> Box(
Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
OutlinedButton(
modifier = Modifier,
onClick = {
scope.launch {
showLoading = true

delay(2000)

showLoading = false

confettiAnimatable.animate(
compositionConfetti,
continueFromPreviousAnimate = false
)
}
},
contentPadding = ButtonDefaults.ButtonWithIconContentPadding
) {
Icon(
Icons.Rounded.RocketLaunch,
contentDescription = "Launch",
modifier = Modifier.size(ButtonDefaults.IconSize)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))

Text("Launch")
}
}
}
}
}

// ----------------------------------------------------------------
// ----------------------------------------------------------------

AppComponent.BigSpacer()
}

LottieAnimation(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
.padding(16.dp),
composition = compositionConfetti,
progress = { confettiAnimatable.progress }
)
}
}
Loading

0 comments on commit 03e3712

Please sign in to comment.