diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index b7e3c1d..11dacc2 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -5,13 +5,13 @@ plugins { } kotlin { - android() + androidTarget() sourceSets { val androidMain by getting { dependencies { implementation(project(":shared")) api("androidx.activity:activity-compose:1.7.2") - api("androidx.core:core-ktx:1.10.1") + api("androidx.core:core-ktx:1.12.0") } } } diff --git a/build.gradle.kts b/build.gradle.kts index 304c715..ab7d679 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,6 +12,7 @@ plugins { id("org.jetbrains.compose") version Versions.COMPOSE apply false id("com.adarshr.test-logger") version "3.2.0" apply false id("org.jlleitschuh.gradle.ktlint") version "11.5.0" apply true + id("com.codingfeline.buildkonfig") version "0.14.0" apply false } allprojects { diff --git a/buildSrc/src/main/kotlin/Artifacts.kt b/buildSrc/src/main/kotlin/Artifacts.kt index 57c3013..7d57152 100644 --- a/buildSrc/src/main/kotlin/Artifacts.kt +++ b/buildSrc/src/main/kotlin/Artifacts.kt @@ -1,8 +1,9 @@ object Artifact { const val APP_ID = "me.sujanpoudel.playdeals" const val APP_NAME = "App Deals" - const val VERSION_CODE = 1 - const val VERSION_NAME = "1.0.0" + const val VERSION_CODE = 16 + const val VERSION_NAME = "1.1.5" + const val MAJOR_RELEASE = true const val ANDROID_COMPILE_SDK = 34 const val ANDROID_TARGET_SDK = 34 diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 423cfbf..535702d 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,7 +1,7 @@ object Versions { - const val KOTLIN = "1.8.22" + const val KOTLIN = "1.9.10" const val AGP = "8.1.1" - const val COMPOSE = "1.5.0" + const val COMPOSE = "1.5.1" const val KO_TEST = "5.5.5" const val KTOR = "2.3.2" diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 3b9e6f9..1f4b4a6 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,4 +1,8 @@ + import com.android.build.gradle.tasks.factory.AndroidUnitTest +import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.BOOLEAN +import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.INT +import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { @@ -7,10 +11,13 @@ plugins { id("com.android.library") id("org.jetbrains.compose") id("com.adarshr.test-logger") + id("com.codingfeline.buildkonfig") } version = "1.0-SNAPSHOT" +val pkgName = "me.sujanpoudel.playdeals.common" + fun KotlinNativeTarget.configureFramework() { binaries.framework { baseName = "shared" @@ -19,10 +26,9 @@ fun KotlinNativeTarget.configureFramework() { } kotlin { - jvmToolchain(17) - android() + androidTarget() jvm("desktop") ios { configureFramework() } iosSimulatorArm64().configureFramework() @@ -32,6 +38,7 @@ kotlin { dependencies { implementation(compose.ui) implementation(compose.foundation) + implementation(compose.material) implementation(compose.material3) implementation(compose.animation) implementation(compose.materialIconsExtended) @@ -50,6 +57,8 @@ kotlin { implementation("media.kamel:kamel-image:0.6.0") implementation("com.russhwolf:multiplatform-settings:${Versions.SETTINGS}") implementation("com.russhwolf:multiplatform-settings-no-arg:${Versions.SETTINGS}") + + implementation("com.mikepenz:multiplatform-markdown-renderer:0.7.2") } } @@ -92,7 +101,7 @@ kotlin { } android { - namespace = "me.sujanpoudel.playdeals.common" + namespace = pkgName sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") sourceSets["main"].res.srcDirs("src/androidMain/res", "src/commonMain/resources") sourceSets["main"].resources.srcDirs("src/commonMain/resources") @@ -109,15 +118,31 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = "1.4.4" + kotlinCompilerExtensionVersion = "1.5.3" } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + proguardFiles("proguard-rules.pro") + } + } } tasks.withType { useJUnitPlatform() } + +buildkonfig { + packageName = pkgName + defaultConfigs { + buildConfigField(STRING, "VERSION_NAME", Artifact.VERSION_NAME) + buildConfigField(INT, "VERSION_CODE", Artifact.VERSION_CODE.toString()) + buildConfigField(BOOLEAN, "MAJOR_RELEASE", Artifact.MAJOR_RELEASE.toString()) + } +} diff --git a/shared/proguard-rules.pro b/shared/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/shared/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/shared/src/androidMain/kotlin/me/sujanpoudel/playdeals/common/App.kt b/shared/src/androidMain/kotlin/me/sujanpoudel/playdeals/common/App.kt index 5e2ee65..17b1015 100644 --- a/shared/src/androidMain/kotlin/me/sujanpoudel/playdeals/common/App.kt +++ b/shared/src/androidMain/kotlin/me/sujanpoudel/playdeals/common/App.kt @@ -3,25 +3,14 @@ package me.sujanpoudel.playdeals.common import android.content.Intent import android.net.Uri import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import me.sujanpoudel.playdeals.common.ui.screens.home.LinkOpener -import java.io.File @Composable fun PlayDealsAppAndroid() { val context = LocalContext.current - LaunchedEffect(Unit) { - val b = context.assets - -// Font(fileDescriptor = InputStream().readBytes() ) - - val file = File("font/roboto_bold.ttf") - println(file) - } - val linkOpener = remember { LinkOpener { val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(it)) diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/AppPreferences.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/AppPreferences.kt index 310901c..30e2178 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/AppPreferences.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/AppPreferences.kt @@ -1,19 +1,21 @@ package me.sujanpoudel.playdeals.common import com.russhwolf.settings.ObservableSettings +import com.russhwolf.settings.set import kotlinx.datetime.Instant import me.sujanpoudel.playdeals.common.strings.AppLanguage import me.sujanpoudel.playdeals.common.ui.theme.AppearanceMode import me.sujanpoudel.playdeals.common.utils.settings.boolSettingState import me.sujanpoudel.playdeals.common.utils.settings.stringBackedSettingState -class AppPreferences(settings: ObservableSettings) { +class AppPreferences(private val settings: ObservableSettings) { private object Keys { const val APPEARANCE_MODE = "APPEARANCE_MODE" const val DEVELOPER_MODE = "DEVELOPER_MODE_ENABLED" const val NEW_DEAL_NOTIFICATION = "NEW_DEAL_NOTIFICATION" const val PREFERRED_LANGUAGE = "PREFERRED_LANGUAGE" const val LAST_UPDATED_TIME = "LAST_UPDATED_TIME" + const val CHANGELOG_SHOWN_FOR_VERSION = "CHANGELOG_SHOWN_FOR_VERSION" } val appearanceMode = settings.stringBackedSettingState( @@ -36,4 +38,7 @@ class AppPreferences(settings: ObservableSettings) { val developerMode = settings.boolSettingState(Keys.DEVELOPER_MODE, false) val newDealNotification = settings.boolSettingState(Keys.NEW_DEAL_NOTIFICATION, true) + + fun getChangelogShownVersion() = settings.getIntOrNull(Keys.CHANGELOG_SHOWN_FOR_VERSION) + fun setChangelogShownVersion(version: Int) = settings.set(Keys.CHANGELOG_SHOWN_FOR_VERSION, version) } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/NavHost.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/NavHost.kt index dfccd07..ec62764 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/NavHost.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/NavHost.kt @@ -3,14 +3,11 @@ package me.sujanpoudel.playdeals.common.navigation import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentTransitionScope import androidx.compose.animation.ContentTransform -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.togetherWith import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue -@OptIn(ExperimentalAnimationApi::class) @Composable fun NavHost(navigator: Navigator) { val currentEntry by navigator.currentEntry @@ -34,9 +31,16 @@ fun NavHost(navigator: Navigator) { ) { val transitionSpec: AnimatedContentTransitionScope.() -> ContentTransform = { if (initialState.id < targetState.id) { // pushing new entry - targetState.enter(this).togetherWith(targetState.exitTransition(this)) + ContentTransform( + targetState.enter(this), + targetState.exitTransition(this), + ) } else { // popping old entry - initialState.popEnter(this).togetherWith(initialState.popExit(this)) + ContentTransform( + initialState.popEnter(this), + initialState.popExit(this), + targetContentZIndex = -1f, + ) } } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/Navigator.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/Navigator.kt index 226cc7d..35b0348 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/Navigator.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/navigation/Navigator.kt @@ -113,6 +113,10 @@ object NavTransitions { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Down) } + val EmptyEnterTransition: NavEnterTransition = { + EnterTransition.None + } + val slideOutToRight: NavExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Right) } @@ -125,4 +129,8 @@ object NavTransitions { val slideOutToTop: NavExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Up) } + + val EmptyExitTransition: NavExitTransition = { + ExitTransition.None + } } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/AppStrings.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/AppStrings.kt index ae23eeb..d787d0f 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/AppStrings.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/AppStrings.kt @@ -29,4 +29,7 @@ interface AppStrings { val dontMissDealDescription: String val themePreference: String val chooseLanguage: String + val close: String + val changelog: String + val viewAll: String } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/en.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/en.kt index f7d4609..18a2af7 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/en.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/strings/en.kt @@ -4,6 +4,7 @@ object StringEn : AppStrings { override val appDeals = "App Deals" override val settings = "Settings" + // Home Screen override val retry = "Retry" override val tryAgain = "Try Again" override val refresh = "Refresh" @@ -21,10 +22,16 @@ object StringEn : AppStrings { override val aboutMe = "About me" override val whatsNew = "What's New" + // Settings Screen override val appearance = "Appearance" override val appearanceModeDescription = "Choose your light ot dark theme preference" override val dontMissDeal = "Don't miss any deals" override val dontMissDealDescription = "Get notification for all new app deals" override val themePreference = "Theme Preference" override val chooseLanguage = "Choose Language" + + // Changelog Screen + override val close = "Close" + override val changelog = "Changelog" + override val viewAll = "View All" } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/common/Scaffold.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/common/Scaffold.kt index 4346010..e0234d6 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/common/Scaffold.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/common/Scaffold.kt @@ -30,7 +30,8 @@ fun Scaffold( modifier = modifier, ) { Box( - modifier = Modifier.padding(it), + modifier = Modifier + .padding(it), ) { content() } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/home/HomeScreenSwipe.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/home/HomeScreenSwipe.kt index 5c2db64..eb16de2 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/home/HomeScreenSwipe.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/home/HomeScreenSwipe.kt @@ -198,7 +198,6 @@ fun Modifier.withScreenSwipe(state: HomeScreenSwipeState): Modifier = composed { } LaunchedEffect(scrollState.isScrollInProgress) { - println("isScrollInProgress : ${scrollState.isScrollInProgress}") if (!scrollState.isScrollInProgress) { dragEnd() } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/settings/SettingsScreen.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/settings/SettingsScreen.kt index 570cce2..671b632 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/settings/SettingsScreen.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/components/settings/SettingsScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import me.sujanpoudel.playdeals.common.BuildKonfig import me.sujanpoudel.playdeals.common.extensions.capitalizeWords import me.sujanpoudel.playdeals.common.strings.AppLanguage import me.sujanpoudel.playdeals.common.strings.Strings @@ -83,7 +84,11 @@ object SettingsScreen { horizontalAlignment = Alignment.CenterHorizontally, ) { Text(Strings.appDeals, style = MaterialTheme.typography.titleSmall, color = color) - Text("V1.1.5-16", style = MaterialTheme.typography.bodySmall, color = color) + Text( + "V${BuildKonfig.VERSION_NAME}-${BuildKonfig.VERSION_CODE}", + style = MaterialTheme.typography.bodySmall, + color = color, + ) } } diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/ChangeLogScreen.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/ChangeLogScreen.kt index 9fb2d98..dff1b8b 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/ChangeLogScreen.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/ChangeLogScreen.kt @@ -1,130 +1,168 @@ package me.sujanpoudel.playdeals.common.ui.screens -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.mikepenz.markdown.compose.Markdown +import com.mikepenz.markdown.model.markdownColor +import com.mikepenz.markdown.model.markdownTypography +import me.sujanpoudel.playdeals.common.AppPreferences +import me.sujanpoudel.playdeals.common.BuildKonfig +import me.sujanpoudel.playdeals.common.di.PrimaryDI +import me.sujanpoudel.playdeals.common.strings.Strings import me.sujanpoudel.playdeals.common.ui.components.ChangeLog import me.sujanpoudel.playdeals.common.ui.components.common.Scaffold import me.sujanpoudel.playdeals.common.ui.screens.home.LocalLinkOpener import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.resource +import org.kodein.di.direct +import org.kodein.di.instance -class ChangeLog( - val version: String, - val date: String, - val bulletListItems: List, -) - -class BulletListItem( - val title: String, - val description: String, -) +private const val SEPARATOR = "-------------------------------------------" +private const val CHANGELOG_PATH = "raw/changelog.md" -val changeLogs = listOf( - ChangeLog( - version = "v1.2.1", - date = "29th Aug 2023", - bulletListItems = listOf( - BulletListItem( - title = "Play Deal is now Open Source", - description = "Yes, Play deals is now open source. If you are nerd and " + - "want to look at the code it is viable at the play deal repo from here", - ), - ), - ), -) +@OptIn(ExperimentalResourceApi::class, ExperimentalFoundationApi::class) +@Composable +fun ChangeLogScreen() = Scaffold( + title = Strings.changelog, + showNavBackIcon = false, + actions = { + val outlineColor = MaterialTheme.colorScheme.outlineVariant -val messages = listOf( - "Hey This is first paragraph", - "Hey this is my second paragraph. Any this is 2nd line.", - "Hey this is 3rd paragraph.", -) + IconButton( + onClick = it::pop, + modifier = Modifier + .drawBehind { + drawCircle(outlineColor, radius = size.minDimension / 2.5f) + }, + ) { + Icon( + Icons.Default.Close, + contentDescription = Strings.close, + tint = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.size(22.dp), + ) + } + }, +) { + val appPreferences = remember { PrimaryDI.direct.instance() } -@OptIn(ExperimentalResourceApi::class) -@Composable -fun ChangeLogScreen() { val linkOpener = LocalLinkOpener.current + var isChangelogExpanded by remember { mutableStateOf(false) } - Scaffold( - title = "Changelog", - showNavBackIcon = false, - actions = { - val outlineColor = MaterialTheme.colorScheme.outlineVariant + var previousChangelogs by remember { mutableStateOf>(emptyList()) } + var currentChangelog by remember { mutableStateOf(null) } - IconButton( - onClick = it::pop, - modifier = Modifier - .drawBehind { - drawCircle(outlineColor, radius = size.minDimension / 2.5f) - }, - ) { - Icon( - Icons.Default.Close, - contentDescription = "Close", - tint = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.size(22.dp), - ) - } - }, - ) { - Column( - modifier = Modifier.padding(horizontal = 16.dp), - ) { - var resource by remember { mutableStateOf("") } + LaunchedEffect(Unit) { + appPreferences.setChangelogShownVersion(BuildKonfig.VERSION_CODE) + } - LaunchedEffect(Unit) { - resource = resource("raw/changelog.json").readBytes().decodeToString() - } + LaunchedEffect(CHANGELOG_PATH) { + val changelogs = resource(CHANGELOG_PATH).readBytes().decodeToString().split(SEPARATOR) + .filter { it.isNotEmpty() } - Spacer(Modifier.height(24.dp)) + currentChangelog = changelogs.first() + previousChangelogs = changelogs.drop(1) + } - Text("What's New in v1.2.1", style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold)) - Text( - "15th Feb 2021", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6f), - ) + if (currentChangelog != null) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(start = 16.dp, end = 16.dp), + contentPadding = PaddingValues(top = 24.dp, bottom = 16.dp), - Text(resource) + ) { + currentChangelog?.also { + item { + ChangeLogItem(it) + } + } + + if (isChangelogExpanded && previousChangelogs.isNotEmpty()) { + items(previousChangelogs) { + ChangeLogItem( + string = it, + modifier = Modifier.animateItemPlacement(), + ) + } + } -// -// Text( -// buildAnnotatedString { -// messages.forEach { -// withStyle(style = ParagraphStyle(textIndent = TextIndent(restLine = 12.sp))) { -// append(Typography.bullet) -// append("\t\t") -// append(it) -// } -// } -// }, -// modifier = Modifier.padding(top = 16.dp), -// style = MaterialTheme.typography.bodyMedium -// ) + item("button") { + Box( + modifier = Modifier + .fillMaxWidth() + .animateItemPlacement(), + contentAlignment = Alignment.Center, + ) { + TextButton( + onClick = { isChangelogExpanded = !isChangelogExpanded }, + ) { + Text(if (isChangelogExpanded) Strings.close else Strings.viewAll) + } + } + } - ChangeLog.SocialActions( - modifier = Modifier.padding(top = 24.dp), - ) { - linkOpener.openLink(it.url) + item("social-actions") { + Box( + modifier = Modifier + .fillMaxWidth() + .animateItemPlacement(), + contentAlignment = Alignment.Center, + ) { + ChangeLog.SocialActions( + modifier = Modifier + .padding(horizontal = 16.dp, vertical = 16.dp) + .align(Alignment.BottomCenter), + ) { + linkOpener.openLink(it.url) + } + } } } } } + +@Composable +fun ChangeLogItem( + string: String, + modifier: Modifier = Modifier, +) = Markdown( + modifier = modifier.fillMaxWidth(), + content = string, + colors = markdownColor(MaterialTheme.colorScheme.onBackground), + typography = markdownTypography( + h1 = MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Medium, + ), + h2 = MaterialTheme.typography.titleMedium, + paragraph = MaterialTheme.typography.bodySmall.copy( + color = MaterialTheme.colorScheme.onBackground.copy(0.6f), + ), + bullet = MaterialTheme.typography.bodyMedium, + ), +) diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreen.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreen.kt index 98357f5..618db32 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreen.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreen.kt @@ -61,6 +61,13 @@ fun HomeScreen() { val strings = Strings + LaunchedEffect(state.destinationOneOff) { + state.destinationOneOff?.also { + viewModel.clearOneOffDestination() + navigator.navigateToChangelog() + } + } + Box( modifier = Modifier.withScreenSwipe(swipeState), ) { @@ -152,13 +159,8 @@ fun HomeScreen() { onMenuClicked = { when (it) { HomeScreenDrawer.Menu.SETTINGS -> navigator.push(Screens.SETTINGS) - HomeScreenDrawer.Menu.WHAT_NEW -> navigator.push( - Screens.CHANGELOG, - enterTransition = NavTransitions.slideInFromBottom, - exitTransition = NavTransitions.slideOutToTop, - popEnter = NavTransitions.slideInFromTop, - popExit = NavTransitions.slideOutToBottom, - ) + HomeScreenDrawer.Menu.WHAT_NEW -> navigator.navigateToChangelog() + HomeScreenDrawer.Menu.FOOTER -> linkOpener.openLink(Constants.ABOUT_ME_URL) } @@ -181,3 +183,13 @@ fun HomeScreen() { ) } } + +fun Navigator.navigateToChangelog() { + push( + Screens.CHANGELOG, + enterTransition = NavTransitions.slideInFromBottom, + exitTransition = NavTransitions.EmptyExitTransition, + popEnter = NavTransitions.EmptyEnterTransition, + popExit = NavTransitions.slideOutToBottom, + ) +} diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenState.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenState.kt index 8d0dce2..3e0df13 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenState.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenState.kt @@ -3,6 +3,7 @@ package me.sujanpoudel.playdeals.common.ui.screens.home import androidx.compose.runtime.Immutable import kotlinx.datetime.Clock import kotlinx.datetime.Instant +import me.sujanpoudel.playdeals.common.Screens import me.sujanpoudel.playdeals.common.domain.models.AppDeal import me.sujanpoudel.playdeals.common.domain.models.DealFilterOption import me.sujanpoudel.playdeals.common.domain.models.Selectable @@ -16,6 +17,7 @@ data class HomeScreenState( val isRefreshing: Boolean = false, val persistentError: String? = null, val errorOneOff: String? = null, + val destinationOneOff: Screens? = null, ) { val dealsToDisplay: List get() { diff --git a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenViewModel.kt b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenViewModel.kt index 7514c02..7385b49 100644 --- a/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenViewModel.kt +++ b/shared/src/commonMain/kotlin/me/sujanpoudel/playdeals/common/ui/screens/home/HomeScreenViewModel.kt @@ -1,12 +1,15 @@ package me.sujanpoudel.playdeals.common.ui.screens.home import io.ktor.util.reflect.instanceOf +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.datetime.Clock import me.sujanpoudel.playdeals.common.AppPreferences +import me.sujanpoudel.playdeals.common.BuildKonfig +import me.sujanpoudel.playdeals.common.Screens import me.sujanpoudel.playdeals.common.domain.models.AppDeal import me.sujanpoudel.playdeals.common.domain.models.DealFilterOption import me.sujanpoudel.playdeals.common.domain.models.Selectable @@ -29,12 +32,24 @@ class HomeScreenViewModel( init { getDeals() + checkIfChangelogNeedsToBeShown() } - fun refreshDeals() { - getDeals() + private fun checkIfChangelogNeedsToBeShown() { + if (BuildKonfig.MAJOR_RELEASE && appPreferences.getChangelogShownVersion() != BuildKonfig.VERSION_CODE) { + viewModelScope.launch { + delay(1000) + _state.update { + it.copy( + destinationOneOff = Screens.CHANGELOG, + ) + } + } + } } + fun refreshDeals() = getDeals() + private fun getDeals() { _state.update { state -> state.copy( @@ -78,6 +93,12 @@ class HomeScreenViewModel( } } + fun clearOneOffDestination() { + _state.update { state -> + state.copy(destinationOneOff = null) + } + } + fun toggleFilterItem(item: DealFilterOption) { _state.update { state -> state.copy( diff --git a/shared/src/commonMain/resources/raw/changelog.json b/shared/src/commonMain/resources/raw/changelog.json deleted file mode 100644 index cb3c6c6..0000000 --- a/shared/src/commonMain/resources/raw/changelog.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "date": "29th Aug 2023", - "version": "v1.2.1", - "header": "", - "footer": "", - "changeList": [ - { - "title": "", - "body": "" - } - ] - } -] diff --git a/shared/src/commonMain/resources/raw/changelog.md b/shared/src/commonMain/resources/raw/changelog.md new file mode 100644 index 0000000..567ace1 --- /dev/null +++ b/shared/src/commonMain/resources/raw/changelog.md @@ -0,0 +1,36 @@ +# What's New in v2.0.0 + +**11th Sept 2023** + +It has been a while the play deals was + +- **Open Source 🥳🥳:** Play deals is now a open source project. You can view the source code for this app on [Github (psuzn/app-deals)](https://github.com/psuzn/app-deals). +- **Ads No More:** I made a decision to remove all the ads. I hope this improves your experience :). +- **Kotlin Everywhere:** I rewrote the play deals app using [Kotlin Multiplatform](https://github.com/JetBrains/compose-multiplatform) and backend is also freshly cooked with kotlin. + +------------------------------------------- + +# What's New in v1.0.1 + +**11th Sept 2023** + +It has been a while the play deals was + +- **Open Source 🥳🥳:** Play deals is now a open source project. You can view the source code for this app on [Github (psuzn/app-deals)](https://github.com/psuzn/app-deals). +- **Ads No More:** I made a decision to remove all the ads. I hope this improves your experience :). +- **Kotlin Everywhere:** I rewrote the play deals app using [Kotlin Multiplatform](https://github.com/JetBrains/compose-multiplatform) and backend is also freshly cooked with kotlin. + +------------------------------------------- + + +# What's New in v1.0.0 + +**11th Sept 2023** + +It has been a while the play deals was + +- **Open Source 🥳🥳:** Play deals is now a open source project. You can view the source code for this app on [Github (psuzn/app-deals)](https://github.com/psuzn/app-deals). +- **Ads No More:** I made a decision to remove all the ads. I hope this improves your experience :). +- **Kotlin Everywhere:** I rewrote the play deals app using [Kotlin Multiplatform](https://github.com/JetBrains/compose-multiplatform) and backend is also freshly cooked with kotlin. + +-------------------------------------------