Fix compilation issues

This commit is contained in:
William Brawner 2022-09-12 22:01:05 -06:00
parent 2eba6c7c75
commit 2d02416101
15 changed files with 110 additions and 79 deletions

1
.idea/.name Normal file
View file

@ -0,0 +1 @@
Nanoflux

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_4_API_33.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-07-21T22:56:15.131545Z" />
</component>
</project>

View file

@ -16,7 +16,6 @@
<option value="$PROJECT_DIR$/storage" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>

View file

@ -21,6 +21,9 @@
<entry key="../../../../layout/compose-model-1622768616366.xml" value="0.2179054054054054" />
<entry key="../../../../layout/compose-model-1622823049252.xml" value="2.0" />
<entry key="../../../../layout/compose-model-1623272040152.xml" value="0.6351851851851852" />
<entry key="../../../../layout/compose-model-1663094305778.xml" value="0.1" />
<entry key="../../../../layout/compose-model-1663094326622.xml" value="0.1" />
<entry key="../../../../layout/compose-model-1663094326625.xml" value="1.0" />
</map>
</option>
</component>

View file

@ -45,7 +45,7 @@ android {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.get()
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}
}

View file

@ -14,6 +14,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import javax.inject.Inject
@ -28,8 +29,10 @@ class MainViewModel @Inject constructor(
init {
viewModelScope.launch {
if (entryRepository.getCount() == 0L) {
syncAll(categoryRepository, feedRepository, iconRepository, entryRepository)
withContext(Dispatchers.IO) {
if (entryRepository.getCount() == 0L) {
syncAll(categoryRepository, feedRepository, iconRepository, entryRepository)
}
}
}
}

View file

@ -86,7 +86,8 @@ fun EntryListItem(
feed.icon?.let {
val bytes = Base64.decode(it.data.substringAfter(","), Base64.DEFAULT)
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
.asImageBitmap()
?.asImageBitmap()
?: return@let
Image(
modifier = Modifier
.width(16.dp)

View file

@ -18,8 +18,8 @@ import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.navArgument
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.wbrawner.nanoflux.NanofluxApp

View file

@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.*
import androidx.compose.ui.input.key.*
@ -45,6 +46,7 @@ fun AuthScreen(authViewModel: AuthViewModel) {
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun AuthForm(
initialServer: String,

View file

@ -4,10 +4,10 @@ buildscript {
google()
mavenCentral()
}
val hiltVersion by extra("2.36")
val kotlinVersion by extra("1.4.32")
val hiltVersion by extra("2.43.2")
val kotlinVersion by extra("1.7.10")
dependencies {
classpath("com.android.tools.build:gradle:7.0.0-beta03")
classpath("com.android.tools.build:gradle:7.2.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("com.google.dagger:hilt-android-gradle-plugin:$hiltVersion")
}

View file

@ -1,61 +1,65 @@
[versions]
androidx-core = "1.3.2"
androidx-appcompat = "1.2.0"
compose = "1.0.0-beta07"
coroutines = "1.4.3"
androidx-core = "1.9.0"
androidx-appcompat = "1.5.1"
compose-ui = "1.2.1"
compose-compiler = "1.3.1"
coroutines = "1.6.4"
espresso = "3.3.0"
hilt-android = "2.36"
hilt-android = "2.43.2"
hilt-work = "1.0.0"
kotlin = "1.4.32"
ktor = "1.6.0"
kotlin = "1.7.10"
ktor = "2.1.0"
material = "1.3.0"
maxSdk = "30"
maxSdk = "33"
minSdk = "21"
room = "2.3.0"
room = "2.4.3"
versionCode = "1"
versionName = "1.0"
work = "2.5.0"
work = "2.7.1"
[libraries]
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
material = { module = "com.google.android.material:material", version.ref = "material" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose" }
compose-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
compose-activity = { module = "androidx.activity:activity-compose", version = "1.3.0-alpha07" }
compose-test = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" }
navigation-compose = { module = "androidx.navigation:navigation-compose", version = "2.4.0-alpha01" }
compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "compose-compiler" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose-ui" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose-ui" }
compose-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose-ui" }
compose-activity = { module = "androidx.activity:activity-compose", version = "1.5.1" }
compose-test = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose-ui" }
navigation-compose = { module = "androidx.navigation:navigation-compose", version = "2.5.2" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
preference = { module = "androidx.preference:preference-ktx", version = "1.1.1" }
lifecycle = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version = "2.3.1" }
preference = { module = "androidx.preference:preference-ktx", version = "1.2.0" }
lifecycle = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version = "2.5.1" }
hilt-android-core = { module = "com.google.dagger:hilt-android", version.ref = "hilt-android" }
hilt-android-kapt = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt-android" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.0.0-alpha02" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.0.0" }
hilt-work-core = { module = "androidx.hilt:hilt-work", version.ref = "hilt-work" }
hilt-work-kapt = { module = "androidx.hilt:hilt-compiler", version.ref = "hilt-work" }
junit = { module = "junit:junit", version = "4.12" }
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
kotlin-reflection = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.2.1"}
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.4.0"}
ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor"}
ktor-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor"}
ktor-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktor-logging = { module = "io.ktor:ktor-client-logging-jvm", version.ref = "ktor"}
ktor-serialization = { module = "io.ktor:ktor-client-serialization", version.ref = "ktor"}
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
room-kapt = { module = "androidx.room:room-compiler", version.ref = "room" }
room-test = { module = "androidx.room:room-testing", version.ref = "room" }
timber = { module = "com.jakewharton.timber:timber", version = "4.7.1" }
timber = { module = "com.jakewharton.timber:timber", version = "5.0.1" }
test-ext = { module = "androidx.test.ext:junit", version = "1.1.2" }
espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
work-core = { module = "androidx.work:work-runtime-ktx", version.ref = "work" }
work-test = { module = "androidx.work:work-testing", version.ref = "work" }
[bundles]
compose = ["compose-ui", "compose-material", "compose-tooling", "compose-activity", "navigation-compose"]
compose = ["compose-compiler", "compose-ui", "compose-material", "compose-tooling", "compose-activity", "navigation-compose"]
coroutines = ["coroutines-core", "coroutines-android"]
networking = ["kotlin-reflection", "kotlinx-serialization", "ktor-core", "ktor-cio", "ktor-logging", "ktor-serialization"]
networking = ["kotlin-reflection", "kotlinx-serialization", "ktor-core", "ktor-cio", "ktor-content-negotiation", "ktor-json", "ktor-logging", "ktor-serialization"]

View file

@ -1,6 +1,6 @@
#Sun May 09 12:06:51 MDT 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View file

@ -4,16 +4,17 @@ import android.content.SharedPreferences
import com.wbrawner.nanoflux.network.repository.PREF_KEY_AUTH_TOKEN
import com.wbrawner.nanoflux.storage.model.*
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.engine.cio.*
import io.ktor.client.features.*
import io.ktor.client.features.json.*
import io.ktor.client.features.json.serializer.*
import io.ktor.client.features.logging.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import timber.log.Timber
import java.io.File
import java.util.concurrent.atomic.AtomicReference
@ -176,8 +177,8 @@ class KtorMinifluxApiService @Inject constructor(
private val _logger: Timber.Tree
) : MinifluxApiService {
private val client = HttpClient(CIO) {
install(JsonFeature) {
serializer = KotlinxSerializer(kotlinx.serialization.json.Json {
install(ContentNegotiation) {
json(Json {
isLenient = true
ignoreUnknownKeys = true
})
@ -230,17 +231,17 @@ class KtorMinifluxApiService @Inject constructor(
userAgent: String?,
fetchViaProxy: Boolean?
): DiscoverResponse = client.post(url("discover")) {
body = DiscoverRequest(url, username, password, userAgent, fetchViaProxy)
setBody(DiscoverRequest(url, username, password, userAgent, fetchViaProxy))
headers {
header("Authorization", sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString())
}
}
}.body()
override suspend fun getFeeds(): List<FeedJson> = client.get(url("feeds")) {
headers {
header("Authorization", sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString())
}
}
}.body()
override suspend fun getCategoryFeeds(categoryId: Long): List<FeedJson> =
client.get(baseUrl + "categories/$categoryId/feeds") {
@ -250,13 +251,13 @@ class KtorMinifluxApiService @Inject constructor(
sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString()
)
}
}
}.body()
override suspend fun getFeed(id: Long): FeedJson = client.get(url("feeds/$id")) {
headers {
header("Authorization", sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString())
}
}
}.body()
override suspend fun getFeedIcon(feedId: Long): Feed.Icon =
client.get(url("feeds/$feedId/icon")) {
@ -266,23 +267,23 @@ class KtorMinifluxApiService @Inject constructor(
sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString()
)
}
}
}.body()
override suspend fun createFeed(url: String, categoryId: Long?): CreateFeedResponse =
client.post(url("feeds")) {
body = FeedRequest(url, categoryId)
setBody(FeedRequest(url, categoryId))
headers {
header(
"Authorization",
sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString()
)
}
}
}.body()
override suspend fun updateFeed(id: Long, feed: FeedJson): Feed = client.put(url("feeds/$id")) {
contentType(ContentType.Application.Json)
body = feed
}
setBody(feed)
}.body()
override suspend fun refreshFeeds(): HttpResponse = client.put(url("feeds/refresh"))
@ -320,10 +321,10 @@ class KtorMinifluxApiService @Inject constructor(
"search" to search,
"category_id" to categoryId,
)
)
).body()
override suspend fun getFeedEntry(feedId: Long, entryId: Long): Entry =
client.get(url("feeds/$feedId/entries/$entryId"))
client.get(url("feeds/$feedId/entries/$entryId")).body()
override suspend fun getEntries(
status: List<Entry.Status>?,
@ -358,9 +359,9 @@ class KtorMinifluxApiService @Inject constructor(
headers {
header("Authorization", sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString())
}
}
}.body()
override suspend fun getEntry(entryId: Long): Entry = client.get(url("entries/$entryId"))
override suspend fun getEntry(entryId: Long): Entry = client.get(url("entries/$entryId")).body()
override suspend fun markFeedEntriesAsRead(id: Long): HttpResponse =
client.put(url("feeds/$id/mark-all-as-read"))
@ -368,7 +369,7 @@ class KtorMinifluxApiService @Inject constructor(
override suspend fun updateEntries(entryIds: List<Long>, status: Entry.Status): HttpResponse =
client.put(url("entries")) {
contentType(ContentType.Application.Json)
body = UpdateEntryRequest(entryIds, status)
setBody(UpdateEntryRequest(entryIds, status))
}
override suspend fun toggleEntryBookmark(id: Long): HttpResponse =
@ -378,20 +379,20 @@ class KtorMinifluxApiService @Inject constructor(
headers {
header("Authorization", sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString())
}
}
}.body()
override suspend fun createCategory(title: String): Category = client.post(url("categories")) {
// body = @Serializable object {
// val title = title
// }
}
}.body()
override suspend fun updateCategory(id: Long, title: String): Category =
client.put(url("categories/$id")) {
// body = @Serializable object {
// val title = title
// }
}
}.body()
override suspend fun deleteCategory(id: Long): HttpResponse =
client.delete(url("categories/$id"))
@ -415,11 +416,11 @@ class KtorMinifluxApiService @Inject constructor(
headers {
header("Authorization", sharedPreferences.getString(PREF_KEY_AUTH_TOKEN, "").toString())
}
}
}.body()
override suspend fun getUser(id: Long): User = client.get(url("users/$id"))
override suspend fun getUser(id: Long): User = client.get(url("users/$id")).body()
override suspend fun getUserByName(name: String): User = client.get(url("users/$name"))
override suspend fun getUserByName(name: String): User = client.get(url("users/$name")).body()
override suspend fun getUses(): List<User> {
TODO("Not yet implemented")

View file

@ -3,6 +3,7 @@ package com.wbrawner.nanoflux.storage.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy.REPLACE
import androidx.room.Query
import com.wbrawner.nanoflux.storage.model.User
@ -14,7 +15,7 @@ interface UserDao {
@Query("SELECT * FROM User WHERE id in (:ids)")
suspend fun getAllByIds(vararg ids: Long): List<User>
@Insert
@Insert(onConflict = REPLACE)
suspend fun insertAll(vararg users: User)
@Delete

View file

@ -12,6 +12,8 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.lang.RuntimeException
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
@ -83,34 +85,31 @@ data class EntryAndFeed(
)
object ISODateSerializer : KSerializer<Date> {
val dateFormat = object : ThreadLocal<SimpleDateFormat>() {
override fun initialValue(): SimpleDateFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ", Locale.ENGLISH)
}
val altDateFormat = object : ThreadLocal<SimpleDateFormat>() {
override fun initialValue(): SimpleDateFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", Locale.ENGLISH)
}
val altDateFormat2 = object : ThreadLocal<SimpleDateFormat>() {
override fun initialValue(): SimpleDateFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH)
val dateFormats = object : ThreadLocal<List<SimpleDateFormat>>() {
override fun initialValue(): List<SimpleDateFormat> = listOf(
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ", Locale.ENGLISH),
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", Locale.ENGLISH),
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH),
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH),
)
}
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Date) =
encoder.encodeString(dateFormat.get()!!.format(value))
encoder.encodeString(dateFormats.get()!!.first().format(value))
override fun deserialize(decoder: Decoder): Date {
val dateString = decoder.decodeString()
return try {
dateFormat.get()!!.parse(dateString)!!
} catch (e: Exception) {
var exception: ParseException? = null
dateFormats.get()!!.forEach { dateFormat ->
try {
altDateFormat.get()!!.parse(dateString)!!
} catch (e: Exception) {
altDateFormat2.get()!!.parse(dateString)!!
return dateFormat.parse(dateString)!!
} catch (ignored: ParseException) {
// move onto the next format
exception = ignored
}
}
throw RuntimeException(exception)
}
}