Skip to content

Commit

Permalink
Initial MVP integration with my BackwardsCompatibleAPI (#1284)
Browse files Browse the repository at this point in the history
* Initial MVP integration with my API, still loads TODO

* Fix formatting

* More todos done

* Add wait on init for api Creation

* Fix sumthing

* Fix build

* Fix some todos

* Add better login failure handling

* Better account switching

* Fix auth problem + crash on login

* Fix object passing between screens

* Add instance blocking

* Use snapshot build

* Fix lint

* Update gradle

* Update kotlin compiler

* Fix test
  • Loading branch information
MV-GH authored Dec 12, 2023
1 parent 7cc5fdd commit 9463f78
Show file tree
Hide file tree
Showing 325 changed files with 1,301 additions and 5,120 deletions.
6 changes: 3 additions & 3 deletions .woodpecker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ steps:
[MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET]

check_formatting:
image: cimg/android:2023.08
image: cimg/android:2023.12
commands:
- sudo chown -R circleci:circleci .
- ./gradlew lintKotlin
environment:
GRADLE_USER_HOME: ".gradle"

build_project:
image: cimg/android:2023.08
image: cimg/android:2023.12
commands:
- sudo chown -R circleci:circleci .
- ./gradlew assembleDebug
environment:
GRADLE_USER_HOME: ".gradle"

run_tests:
image: cimg/android:2023.08
image: cimg/android:2023.12
commands:
- sudo chown -R circleci:circleci .
- ./gradlew testDebug
Expand Down
30 changes: 14 additions & 16 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ plugins {
id("org.jetbrains.kotlin.android")
id("com.google.devtools.ksp")
id("androidx.baselineprofile")
id("kotlin-parcelize")
kotlin("plugin.serialization") version "1.9.21"

}

apply(from = "update_instances.gradle.kts")

android {
buildToolsVersion = "34.0.0-rc3"
buildToolsVersion = "34.0.0"
compileSdk = 34

defaultConfig {
Expand Down Expand Up @@ -95,7 +95,7 @@ android {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.4"
kotlinCompilerExtensionVersion = "1.5.6"
}
}

Expand Down Expand Up @@ -138,37 +138,32 @@ dependencies {
// crash handling
implementation("com.github.FunkyMuse:Crashy:1.2.0")

// Versioning
implementation("io.github.z4kn4fein:semver:1.4.2")

// To use Kotlin annotation processing tool
ksp("androidx.room:room-compiler:2.6.0")
ksp("androidx.room:room-compiler:2.6.1")

implementation("androidx.room:room-runtime:2.6.0")
annotationProcessor("androidx.room:room-compiler:2.6.0")
implementation("androidx.room:room-runtime:2.6.1")
annotationProcessor("androidx.room:room-compiler:2.6.1")

// optional - Kotlin Extensions and Coroutines support for Room
implementation("androidx.room:room-ktx:2.6.0")
implementation("androidx.room:room-ktx:2.6.1")

// optional - Test helpers
testImplementation("androidx.room:room-testing:2.6.0")
testImplementation("androidx.room:room-testing:2.6.1")
testImplementation("pl.pragmatists:JUnitParams:1.1.1")
androidTestImplementation("androidx.room:room-testing:2.6.0")
androidTestImplementation("androidx.room:room-testing:2.6.1")

// optional - Paging 3 Integration
implementation("androidx.room:room-paging:2.6.0")
implementation("androidx.room:room-paging:2.6.1")

implementation("io.arrow-kt:arrow-core:1.2.1")
// Unfortunately, ui tooling, and the markdown thing, still brings in the other material2 dependencies
implementation("androidx.compose.material3:material3:1.1.2")
implementation("androidx.compose.material3:material3-window-size-class:1.1.2")

implementation("org.ocpsoft.prettytime:prettytime:5.0.6.Final")
implementation("org.ocpsoft.prettytime:prettytime:5.0.7.Final")
implementation("androidx.navigation:navigation-compose:2.7.5")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
testImplementation("androidx.arch.core:core-testing:2.2.0")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")

implementation("androidx.compose.ui:ui:1.5.4")
implementation("androidx.compose.ui:ui-tooling-preview:1.5.4")
Expand All @@ -191,4 +186,7 @@ dependencies {
baselineProfile(project(":benchmarks"))

implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.6")

implementation("it.vercruysse.lemmyapi:lemmy-api-jvm:0.1.0-SNAPSHOT")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.1")
}
11 changes: 3 additions & 8 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,17 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.jerboa.datatypes.** { *; }

# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
-keep,allowobfuscation,allowshrinking interface retrofit2.Call
-keep,allowobfuscation,allowshrinking class retrofit2.Response

# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

# Some gson stuff
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

# Some prettytime stuff
-keep class com.ocpsoft.pretty.time.i18n.**
-keep class org.ocpsoft.prettytime.i18n.**
-keepnames class ** implements org.ocpsoft.prettytime.TimeUnit

# Ktor needs this
-dontwarn org.slf4j.impl.StaticLoggerBinder
5 changes: 5 additions & 0 deletions app/src/main/java/com/jerboa/Constants.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.jerboa

const val DEBOUNCE_DELAY = 1000L
const val MAX_POST_TITLE_LENGTH = 200
const val DEFAULT_FONT_SIZE = 16
58 changes: 37 additions & 21 deletions app/src/main/java/com/jerboa/JerboaAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.jerboa.datatypes.types.CommentView
import com.jerboa.datatypes.types.Community
import com.jerboa.datatypes.types.CommunityView
import com.jerboa.datatypes.types.PostView
import com.jerboa.datatypes.types.PrivateMessageView
import com.jerboa.model.ReplyItem
import com.jerboa.ui.components.comment.edit.CommentEditReturn
import com.jerboa.ui.components.comment.reply.CommentReplyReturn
Expand All @@ -23,9 +19,16 @@ import com.jerboa.ui.components.community.sidebar.CommunityViewSidebar
import com.jerboa.ui.components.post.create.CreatePostReturn
import com.jerboa.ui.components.post.edit.PostEditReturn
import com.jerboa.ui.components.privatemessage.PrivateMessage
import it.vercruysse.lemmyapi.v0x19.datatypes.CommentView
import it.vercruysse.lemmyapi.v0x19.datatypes.Community
import it.vercruysse.lemmyapi.v0x19.datatypes.CommunityView
import it.vercruysse.lemmyapi.v0x19.datatypes.PostView
import it.vercruysse.lemmyapi.v0x19.datatypes.PrivateMessageView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

Expand Down Expand Up @@ -166,11 +169,11 @@ class JerboaAppState(
*
* When you want to pass a [Parcelable] to the previous screen/activity you came from
*/
fun addReturn(
inline fun <reified T> addReturn(
key: String,
value: Parcelable,
value: T,
) {
navController.previousBackStackEntry?.savedStateHandle?.set(key, value)
navController.previousBackStackEntry?.savedStateHandle?.set(key, Json.encodeToString(value))
}

/**
Expand All @@ -180,11 +183,11 @@ class JerboaAppState(
*
* When you want to pass a [Parcelable] to another screen/activity
*/
fun sendReturnForwards(
inline fun <reified T> sendReturnForwards(
key: String,
value: Parcelable,
value: T,
) {
navController.currentBackStackEntry?.savedStateHandle?.set(key, value)
navController.currentBackStackEntry?.savedStateHandle?.set(key, Json.encodeToString(value))
}

fun toPostWithPopUpTo(postId: Int) {
Expand Down Expand Up @@ -216,14 +219,16 @@ class JerboaAppState(
*/

@Composable
inline fun <reified T : Parcelable> ConsumeReturn(
inline fun <reified T> ConsumeReturn(
key: String,
crossinline consumeBlock: (T) -> Unit,
) {
LaunchedEffect(key) {
val savedStateHandle = navController.currentBackStackEntry?.savedStateHandle
if (savedStateHandle?.contains(key) == true) {
savedStateHandle.get<T>(key)?.also(consumeBlock)
savedStateHandle.get<String>(key)?.let {
consumeBlock(Json.decodeFromString<T>(it))
}
savedStateHandle.remove<String>(key)
}
}
Expand All @@ -239,11 +244,13 @@ class JerboaAppState(
* - It actually contains the key
*/
@Composable
inline fun <reified D : Parcelable> getPrevReturn(key: String): D {
inline fun <reified D : Any> getPrevReturn(key: String): D {
// This will survive process death
return rememberSaveable {
navController.previousBackStackEntry!!.savedStateHandle.get<D>(key)
?: throw IllegalStateException("This route doesn't contain this key `$key`")
return rememberSaveable(saver = getKotlinxSerializerSaver<D>()) {
Json.decodeFromString<D>(
navController.previousBackStackEntry!!.savedStateHandle.get<String>(key)
?: throw IllegalStateException("This route doesn't contain this key `$key`"),
)
}
}

Expand All @@ -252,11 +259,11 @@ class JerboaAppState(
* This is important as, we could navigate further up the tree and back again
* but when you consume on second return it will be gone
*/
inline fun <reified T : Parcelable> getPrevReturnNullable(key: String): T? {
inline fun <reified T : Any> getPrevReturnNullable(key: String): T? {
val savedStateHandle = navController.previousBackStackEntry?.savedStateHandle

if (savedStateHandle?.contains(key) == true) {
return savedStateHandle.get<T>(key)
return savedStateHandle.get<String>(key)?.let { Json.decodeFromString<T>(it) }
}
return null
}
Expand All @@ -268,15 +275,24 @@ class JerboaAppState(
*
*/
@Composable
inline fun <reified T : Parcelable> usePrevReturn(
inline fun <reified T> usePrevReturn(
key: String,
crossinline consumeBlock: (T) -> Unit,
) {
LaunchedEffect(key) {
val savedStateHandle = navController.previousBackStackEntry?.savedStateHandle
if (savedStateHandle?.contains(key) == true) {
savedStateHandle.get<T>(key)?.also(consumeBlock)
savedStateHandle.get<String>(key)
?.let { Json.decodeFromString<T>(it) }
?.also(consumeBlock)
}
}
}
}

inline fun <reified T> getKotlinxSerializerSaver(): Saver<T, String> {
return Saver(
save = { Json.encodeToString(it) },
restore = { Json.decodeFromString<T>(it) },
)
}
1 change: 1 addition & 0 deletions app/src/main/java/com/jerboa/JerboaApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class JerboaApplication : Application(), ImageLoaderFactory {

override fun onCreate() {
super.onCreate()

container = AppDBContainer(this)
imageLoader =
ImageLoader.Builder(this)
Expand Down
34 changes: 0 additions & 34 deletions app/src/main/java/com/jerboa/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.util.Patterns
import android.widget.TextView
import android.widget.Toast
Expand All @@ -29,9 +28,6 @@ import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import arrow.core.Either
import coil.Coil
import com.jerboa.api.API
import com.jerboa.api.ApiState
import com.jerboa.api.MINIMUM_API_VERSION
import com.jerboa.db.APP_SETTINGS_DEFAULT
import com.jerboa.feat.BackConfirmation.addConfirmationDialog
import com.jerboa.feat.BackConfirmation.addConfirmationToast
Expand All @@ -51,7 +47,6 @@ import com.jerboa.ui.components.common.LinkDropDownMenu
import com.jerboa.ui.components.common.MarkdownHelper
import com.jerboa.ui.components.common.Route
import com.jerboa.ui.components.common.ShowChangelog
import com.jerboa.ui.components.common.ShowOutdatedServerDialog
import com.jerboa.ui.components.common.SwipeToNavigateBack
import com.jerboa.ui.components.community.CommunityActivity
import com.jerboa.ui.components.community.list.CommunityListActivity
Expand All @@ -76,7 +71,6 @@ import com.jerboa.ui.components.settings.crashlogs.CrashLogsActivity
import com.jerboa.ui.components.settings.lookandfeel.LookAndFeelActivity
import com.jerboa.ui.theme.JerboaTheme
import com.jerboa.util.markwon.BetterLinkMovementMethod
import io.github.z4kn4fein.semver.toVersion

class MainActivity : AppCompatActivity() {
val siteViewModel by viewModels<SiteViewModel>(factoryProducer = { SiteViewModel.Factory })
Expand All @@ -92,18 +86,6 @@ class MainActivity : AppCompatActivity() {
setContent {
val ctx = LocalContext.current

API.errorHandler = {
Log.e("jerboa", it.toString())
runOnUiThread {
Toast.makeText(
ctx,
ctx.resources.getString(R.string.networkError),
Toast.LENGTH_SHORT,
).show()
}
null
}

val appSettings by appSettingsViewModel.appSettings.observeAsState(APP_SETTINGS_DEFAULT)

@Suppress("SENSELESS_COMPARISON")
Expand Down Expand Up @@ -144,8 +126,6 @@ class MainActivity : AppCompatActivity() {
}
}

val serverVersionOutdatedViewed = remember { mutableStateOf(false) }

MarkdownHelper.init(
appState,
appSettings.useCustomTabs,
Expand All @@ -171,19 +151,6 @@ class MainActivity : AppCompatActivity() {

ShowChangelog(appSettingsViewModel = appSettingsViewModel)

when (val siteRes = siteViewModel.siteRes) {
is ApiState.Success -> {
val siteVersion = siteRes.data.version
if (siteVersion.toVersion() < MINIMUM_API_VERSION && !serverVersionOutdatedViewed.value) {
ShowOutdatedServerDialog(
siteVersion = siteVersion,
onConfirm = { serverVersionOutdatedViewed.value = true },
)
}
}
else -> {}
}

val drawerState = rememberDrawerState(DrawerValue.Closed)

NavHost(
Expand Down Expand Up @@ -401,7 +368,6 @@ class MainActivity : AppCompatActivity() {
val args = Route.CommunityListArgs(it)
CommunityListActivity(
appState = appState,
accountViewModel = accountViewModel,
selectMode = args.select,
blurNSFW = appSettings.blurNSFW,
drawerState = drawerState,
Expand Down
Loading

0 comments on commit 9463f78

Please sign in to comment.