diff --git a/Building.md b/Building.md index e80c100..c7659fd 100644 --- a/Building.md +++ b/Building.md @@ -10,7 +10,7 @@ ## Using CLI and Gradle -Follow theese steps if you don't have installed IntelliJ/Andoid Studio and want to build `Smupe!` using Gradle CLI. +Follow these steps if you don't have installed IntelliJ/Android Studio and want to build `Smupe!` using Gradle CLI. 1. Verify installation of JDK before you begin: @@ -44,11 +44,11 @@ Follow theese steps if you don't have installed IntelliJ/Andoid Studio and want ## Using Android Studio or IntelliJ IDEA -If you prefer to use IDE to build, follow theese steps: +If you prefer to use IDE to build, follow these steps: 1. Open IDE and clone project by clicking `Get from VCS` 2. Select `Repository URL` -> `Git` and enter the repo URL 3. Click `Clone` and wait when project load -4. Android plugin will show an Android SDK selector pop-up message, where you should select installed Andoid SDK. If there's nothing, follow instructions to install correct SDK. +4. Android plugin will show an Android SDK selector pop-up message, where you should select installed Android SDK. If there's nothing, follow instructions to install correct SDK. 5. After that, click on `Build` > `Build APKs` 6. If build succeeds, click to `locate` in notification. The APK will be available in `debug` directory diff --git a/Contributing.md b/Contributing.md index aca1276..dd4aa81 100644 --- a/Contributing.md +++ b/Contributing.md @@ -16,7 +16,7 @@ I was added experimental ACRA support to the project, but now it is disabled. So * device model and OS version * logcat output for `net.blusutils.smupe.foss` (search in the Internet how to collect it) * screen recording -* additional context (e. g. Internet connection, app permissions or anything you think is relevant) +* additional context (e.g. Internet connection, app permissions or anything you think is relevant) ## Proposing Enhancements @@ -26,21 +26,22 @@ Describe your idea in details, as clear as possible. If you can, attach screensh ## Pull Requests (changes in code) -If you want to contribute code to the project, remember: +If you want to contribute code to the project, please: * split your PRs to small ones (if possible) -* if you decided to change the UI, please attach screenshots or mockups +* if you decided to change the UI, attach screenshots or mockups * if you decided to change app architecture, create a *draft* PR, and, until we confirm the changes, don't turn it to normal PR * if you want to add a new translation, also create a draft PR -* PRs with very small changes will be rejected (create issue instead) - * small changes is: a typo fix, a comment change, a small UI change (like padding intervals), etc. - * in issue just copy link to line(s) that should be changed in the code and add changes codeblock +* PRs with very small changes will be rejected (create an issue instead) + * small changes is: a typo fix, a small comment change or addition, a small UI change (like padding intervals), etc. + * when create issue just copy permalink to line(s) that should be changed in the code and add changes to fenced (\```) codeblock * PRs that add or change code comments is allowed, but only if it useful enough * adding new dependencies is disallowed, unless it is absolutely necessary (we will try to decide it in conversation) -* **don't propose breaking changes in PRs!!!** I mean +* **don't propose breaking changes in PRs!!!** +* I mean: * breaking API changes (so app update cannot be installed above the current version) * global and big UI changes (it will confuse users) - * anything that may be harmful for the user experience (including ADS, spyware, etc.) + * anything that may be harmful for the user experience (including advertisements, spyware, etc.) * ProtoBufs messages and Room DB entities changes without defined migrations * never use destructive migrations * for ProtoBufs please use reserved fields if it really necessary diff --git a/Readme.md b/Readme.md index e3b2938..1b68003 100644 --- a/Readme.md +++ b/Readme.md @@ -1,7 +1,7 @@ # Smupe! > [!WARNING] -> **Smupe!** currently in early early alpha stage. Report any bugs to issues and contribute! +> **Smupe!** currently in early, really early alpha stage. Report any bugs to issues and contribute! "Show me 'ur pictures, eternally!" @@ -13,9 +13,9 @@ Choose from a variety of image sources, from art & landscapes to memes & animals **Smupe!** is easy to use. Just swipe to get a new image! -Found something interesting? Tap ~~twice~~ on heart to save it to Favourites! +Found something interesting? Tap twice or on heart to save it to Favourites! -Want to share or view original? ~~Swipe right~~ tap on action button to show context buttons! +Want to share or view original? Tap on action button to show context buttons! Get bored with such stream of images? Switch to another one, the API-DEFs tab contain some built-in, and you can add your own. @@ -61,19 +61,19 @@ You can download release APK from [GitHub releases](https://github.com/EgorBron/ There is no release in any app stores yet, but soon, I will prepare for publishing in Play Market and F-Droid. -#### Will there be versions for Watch OS/Android TV/desktop platforms/iOS/Web? +#### Will there be versions for WearOS/Android TV/desktop platforms/iOS/Web? Support for Watch OS & Android TV is planned, but not in the near future. Web version is also will be done. Stay tuned for updates! Desktop and iOS versions will require migration to the Compose Multiplatform (or the more radical way - Flutter). -To do so, I need to rewirite some parts of app logic entirely. +To do so, I need to rewrite some parts of app logic entirely. That's really time-consuming, so I'm not going to do it soon. #### Can I use \? -Proably! As long as it matches all requirements of API-DEF specs. You'll need to write a new API-DEF (i.e. request schema processor) for it. +Probably! As long as it matches all requirements of API-DEF specs. You'll need to write a new API-DEF (i.e. request schema processor) for it. If you about the copyright... Use at your own risk. I have no warranty or liability for any claim, damage or any other kind, because app is just an interface to interact with such. It's not mine or app's job to check, the images are safe to retrieve or use, or not. @@ -124,11 +124,11 @@ So, finally, I decided: #### The code is bad 😬! No best practices used! -Calm down! That's my first expirience in Compose! +Calm down! That's my first experience in Compose! Instead of throwing rotten tomatoes at me, better help improve the app! -> For example, I want to get rid of side effects and buisness logic in composables, properly share data between them, use coroutines much more, etc. +> For example, I want to get rid of side effects and business logic in @Composables, properly share data between them, use coroutines much more, etc. See [Contributing](./Contributing.md) to know how you can help! diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c64dcb4..e928290 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -37,8 +37,8 @@ android { isDebuggable = true } release { - isMinifyEnabled = true - isShrinkResources = true +// isMinifyEnabled = true +// isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") signingConfig = signingConfigs.getByName("debug") } @@ -95,21 +95,20 @@ tasks.withType().configureEach { dependencies { - implementation(platform("androidx.compose:compose-bom:2023.08.00")) - androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00")) + implementation(platform("androidx.compose:compose-bom:2024.02.00")) + implementation(project(":common")) + androidTestImplementation(platform("androidx.compose:compose-bom:2024.02.00")) // Documentation dokkaPlugin("org.jetbrains.dokka:android-documentation-plugin:1.9.10") // AndroidX (Jetpack) dependencies - implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.core:core-ktx:1.13.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") - implementation("androidx.activity:activity-compose:1.8.2") - implementation(platform("androidx.compose:compose-bom:2024.02.00")) -// implementation(platform("androidx.compose:compose-bom:2023.06.01")) + implementation("androidx.activity:activity-compose:1.9.0") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3:1.2.0") + implementation("androidx.compose.material3:material3:1.2.1") // Room DB implementation("androidx.room:room-runtime:2.6.1") @@ -129,14 +128,14 @@ dependencies { implementation("io.coil-kt:coil-compose:2.5.0") implementation("io.coil-kt:coil-gif:2.5.0") + implementation(project(":composeblurhash")) // Blurhash support for Compose + implementation("io.github.aghajari:LazySwipeCards:1.0.1") // Swipeable Cards // implementation(project(":LazySwipeCards")) implementation("androidx.compose.foundation:foundation:1.6.1") // For... what? implementation("androidx.navigation:navigation-compose:2.7.7") // For NavController support implementation("org.burnoutcrew.composereorderable:reorderable:0.7.0") // For Modifier.reorderable -// val composeBom = platform("androidx.compose:compose-bom:2023.10.01") -// implementation(composeBom) implementation("androidx.compose.material:material-icons-extended") // Material icons (all) implementation("com.airbnb.android:lottie-compose:6.2.0") // Lottie @@ -151,7 +150,7 @@ dependencies { implementation("com.google.accompanist:accompanist-permissions:0.33.2-alpha") // Accompanist Permissions - implementation("ch.acra:acra-http:5.11.3") // Android Crash Reports via HTTP + implementation("ch.acra:acra-mail:5.11.3") // Android Crash Reports via HTTP // Dev dependencies testImplementation("junit:junit:4.13.2") diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index bdcb249..2052b9d 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -7,47 +7,4 @@ -keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite { ; -} - --dontwarn com.squareup.javapoet.AnnotationSpec$Builder --dontwarn com.squareup.javapoet.AnnotationSpec --dontwarn com.squareup.javapoet.ClassName --dontwarn javax.lang.model.SourceVersion --dontwarn javax.lang.model.element.AnnotationMirror --dontwarn javax.lang.model.element.AnnotationValue --dontwarn javax.lang.model.element.AnnotationValueVisitor --dontwarn javax.lang.model.element.Element --dontwarn javax.lang.model.element.ElementKind --dontwarn javax.lang.model.element.ElementVisitor --dontwarn javax.lang.model.element.ExecutableElement --dontwarn javax.lang.model.element.Modifier --dontwarn javax.lang.model.element.Name --dontwarn javax.lang.model.element.PackageElement --dontwarn javax.lang.model.element.QualifiedNameable --dontwarn javax.lang.model.element.TypeElement --dontwarn javax.lang.model.element.TypeParameterElement --dontwarn javax.lang.model.element.VariableElement --dontwarn javax.lang.model.type.ArrayType --dontwarn javax.lang.model.type.DeclaredType --dontwarn javax.lang.model.type.ErrorType --dontwarn javax.lang.model.type.ExecutableType --dontwarn javax.lang.model.type.IntersectionType --dontwarn javax.lang.model.type.NoType --dontwarn javax.lang.model.type.NullType --dontwarn javax.lang.model.type.PrimitiveType --dontwarn javax.lang.model.type.TypeKind --dontwarn javax.lang.model.type.TypeMirror --dontwarn javax.lang.model.type.TypeVariable --dontwarn javax.lang.model.type.TypeVisitor --dontwarn javax.lang.model.type.WildcardType --dontwarn javax.lang.model.util.AbstractElementVisitor8 --dontwarn javax.lang.model.util.ElementFilter --dontwarn javax.lang.model.util.Elements --dontwarn javax.lang.model.util.SimpleAnnotationValueVisitor8 --dontwarn javax.lang.model.util.SimpleElementVisitor8 --dontwarn javax.lang.model.util.SimpleTypeVisitor8 --dontwarn javax.lang.model.util.Types --dontwarn javax.tools.Diagnostic$Kind --dontwarn javax.tools.FileObject --dontwarn javax.tools.JavaFileManager$Location --dontwarn javax.tools.StandardLocation \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/androidTest/java/net/blusutils/smupe/ExampleInstrumentedTest.kt b/app/src/androidTest/java/net/blusutils/smupe/ExampleInstrumentedTest.kt index 7e1ce47..48a66e4 100644 --- a/app/src/androidTest/java/net/blusutils/smupe/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/net/blusutils/smupe/ExampleInstrumentedTest.kt @@ -1,13 +1,11 @@ package net.blusutils.smupe -import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 - +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith -import org.junit.Assert.* - /** * Instrumented test, which will execute on an Android device. * diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8807e51..50aa80c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,6 +17,7 @@ ( + net.blusutils.smupe.common.api_definitions.data.network.service.CatApi, Gallery + ) +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/ErrorActivity.kt b/app/src/main/java/net/blusutils/smupe/ErrorActivity.kt index 7090a61..594780e 100644 --- a/app/src/main/java/net/blusutils/smupe/ErrorActivity.kt +++ b/app/src/main/java/net/blusutils/smupe/ErrorActivity.kt @@ -1,6 +1,7 @@ package net.blusutils.smupe import android.os.Bundle +import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column @@ -14,14 +15,16 @@ import androidx.compose.material3.* import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.unit.dp -import net.blusutils.smupe.ui.SmupeTheme +import net.blusutils.smupe.presentation.theme.SmupeTheme +import org.acra.ktx.sendWithAcra class ErrorActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val thread = intent.extras?.getString("thread") ?: "unknown" - val exception = intent.extras?.getString("exception") ?: "unknown" + val exception = intent.extras?.getString("exception") ?: "" + Log.d("ERR", exception) setContent { SmupeTheme { @@ -31,19 +34,21 @@ class ErrorActivity : ComponentActivity() { }, icon = { Icon(Icons.Default.BugReport, "Bug icon", Modifier.scale(1.2f)) }, dismissButton = { TextButton(onClick = { this.finish() }) { Text("Exit") } }, - confirmButton = { Button({}) { Text("Report") } }, + confirmButton = { Button({ Exception(exception).sendWithAcra(); this.finish() }) { Text("Report") } }, title = { Text(getString(R.string.well_that_s_a_bug)) }, text = { Column( Modifier - .fillMaxHeight(.5f) + .fillMaxHeight(.7f) + .verticalScroll(rememberScrollState()) .padding(4.dp)) { Text(getString(R.string.unhandled_error_dialog_message)) Text("~~~~~~") Text("Unhandled exception occurred in $thread thread.") - Text("The exception stacktrace shown below:") + if (exception.isNotBlank()) + Text("The exception stacktrace shown below:") Card( Modifier .padding(4.dp) @@ -51,7 +56,6 @@ class ErrorActivity : ComponentActivity() { ) { Text(exception, Modifier - .verticalScroll(rememberScrollState()) .padding(8.dp)) } } diff --git a/app/src/main/java/net/blusutils/smupe/MainActivity.kt b/app/src/main/java/net/blusutils/smupe/MainActivity.kt index 4da434b..613cf3c 100644 --- a/app/src/main/java/net/blusutils/smupe/MainActivity.kt +++ b/app/src/main/java/net/blusutils/smupe/MainActivity.kt @@ -10,12 +10,12 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import jonathanfinerty.once.Once -import net.blusutils.smupe.data.image_sources.ApiDefFileWrapper.loadAllApiDefs -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.data.room.AppDatabase.Companion.initDb -import net.blusutils.smupe.ui.App -import net.blusutils.smupe.ui.SmupeTheme +import net.blusutils.smupe.logic.api_definitions.domain.utils.implementation.AndroidApiDefWrapper +import net.blusutils.smupe.logic.db.database.AppDatabase.Companion.initDb +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.theme.SmupeTheme +import net.blusutils.smupe.presentation.ui.root.App import java.lang.Thread.UncaughtExceptionHandler class MainActivity : AppCompatActivity(), UncaughtExceptionHandler { @@ -25,7 +25,7 @@ class MainActivity : AppCompatActivity(), UncaughtExceptionHandler { this.initDb() - this.loadAllApiDefs() + AndroidApiDefWrapper(this).loadAllApiDefs() Once.initialise(this) diff --git a/app/src/main/java/net/blusutils/smupe/SmupeApplication.kt b/app/src/main/java/net/blusutils/smupe/SmupeApplication.kt new file mode 100644 index 0000000..643efca --- /dev/null +++ b/app/src/main/java/net/blusutils/smupe/SmupeApplication.kt @@ -0,0 +1,27 @@ +package net.blusutils.smupe + +import android.app.Application +import android.content.Context +import android.util.Log +import org.acra.ACRA +import org.acra.config.mailSender +import org.acra.data.StringFormat +import org.acra.ktx.initAcra + +class SmupeApplication : Application() { + override fun attachBaseContext(base: Context) { + super.attachBaseContext(base) +Log.d("SMUPEAPP","works") + ACRA.DEV_LOGGING = true + initAcra { + //core configuration: + buildConfigClass = BuildConfig::class.java + reportFormat = StringFormat.JSON + mailSender { + mailTo = "egorbron@inbox.ru" + reportFileName = "smupe_crash_report.txt" + body = "Test" + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/ApiDefFileWrapper.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/ApiDefFileWrapper.kt deleted file mode 100644 index 3ba04bc..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/ApiDefFileWrapper.kt +++ /dev/null @@ -1,69 +0,0 @@ -package net.blusutils.smupe.data.image_sources - -import android.content.Context -import android.util.Log -import com.squareup.moshi.Moshi -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import net.blusutils.smupe.data.image_sources.models.sources.BaseImageSource -import net.blusutils.smupe.data.image_sources.models.sources.InternetImageSource -import net.blusutils.smupe.data.image_sources.models.sources.SourceMode -import net.blusutils.smupe.data.image_sources.repository.DirectLinkRepository -import net.blusutils.smupe.data.image_sources.repository.JsonRepository -import net.blusutils.smupe.data.image_sources.repository.LocalRepository -import net.blusutils.smupe.data.image_sources.repository.PlainTextRepository -import java.io.File - -object ApiDefFileWrapper { - - val Context.apiDefDirectory: File - get() = File(filesDir, "api_def") - - fun Context.loadAllApiDefs() { - apiDefDirectory.listFiles()?.let { - if (it.isEmpty()) { - Log.d("loadAllApiDefs", "No api defs found") - } else - it.forEach { - if (it.extension == "json") - readFile(this, it.name)?.let { - CurrentApiDefParams.dynamicRepos.add(it) - } - } - } - } - - fun readFile(context: Context, filename: String): BaseImageSource? { - context.apiDefDirectory.mkdirs() - - val file = File(context.apiDefDirectory, filename) - val adapter = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build() - - return file.run { - if (!exists()) null - else { - val txt = readText() -// if (txt.matches("^\\s*\\{".toRegex())) { - val regexMatches = "\"mode\":\\s*\"\\w*?\"".toRegex().find(txt) - regexMatches?.let { - SourceMode.Local - val cls = when (regexMatches.value.split(":")[1].trim()) { - "\"Local\"" -> LocalRepository::class.java - "\"Internet\"" -> InternetImageSource::class.java - "\"InternetDirectLink\"" -> DirectLinkRepository::class.java - "\"InternetPlainText\"" -> PlainTextRepository::class.java - else -> JsonRepository::class.java - } - adapter.adapter(cls).fromJson(txt) - } - } - } - } - - fun writeFile(context: Context, filename: String, apiDef: T, cls: Class) { - context.apiDefDirectory.mkdirs() - - val file = File(context.apiDefDirectory, filename) - val adapter = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build().adapter(cls) - file.writeText(adapter.toJson(apiDef)) - } -} diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/CurrentApiDefParams.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/CurrentApiDefParams.kt deleted file mode 100644 index 4e8934f..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/CurrentApiDefParams.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.blusutils.smupe.data.image_sources - -import net.blusutils.smupe.data.image_sources.models.sources.BaseImageSource -import net.blusutils.smupe.data.image_sources.repository.CatApi -import net.blusutils.smupe.data.image_sources.repository.Gallery - -object CurrentApiDefParams { - var currentApi: BaseImageSource? = null - var currentSearchQuery = "" - var dynamicRepos = mutableListOf(CatApi, Gallery) -} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/contents/BaseImageContent.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/models/contents/BaseImageContent.kt deleted file mode 100644 index d46e6f4..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/contents/BaseImageContent.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.blusutils.smupe.data.image_sources.models.contents - -open class BaseImageContent( - open val url: String?, - open val occurredException: Exception? -) \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/AuthType.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/AuthType.kt deleted file mode 100644 index 388d04c..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/AuthType.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.blusutils.smupe.data.image_sources.models.sources - -enum class AuthType { - None, - AuthHeader, - AuthHeaderBearer, - AuthHeaderToken, - AuthHeaderOther, // see "defining custom auth in API-DEF" - JSON -} diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BasicLocalSource.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BasicLocalSource.kt deleted file mode 100644 index cacdd5d..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BasicLocalSource.kt +++ /dev/null @@ -1,58 +0,0 @@ -package net.blusutils.smupe.data.image_sources.models.sources -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import okhttp3.Response - -abstract class BasicLocalSource( - override var name: String = "Local", - override var icon: String? = null, - override var description: String? = null, - override var apiLink: String = "/storage/emulated/0/" -) : LocalImageSource( - name, - icon, - description, - apiLink = apiLink -) { - override var authorization: Authorization? - get() = null - set(_) {} - - override suspend fun requestRawAsync(): Uri? = - requestAsync()?.url.run { - if (this != null) - Uri.parse(this) - else - null - } - - - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { - requestWithCallback { - callback(Uri.parse(it?.url)) - } - } - - override fun serializeResponse(response: Response): ImageResponse = - throw UnsupportedOperationException("Local sources not need to be serialized") - - override fun serializeResponse(input: String): ImageResponse { - throw UnsupportedOperationException("Local sources not need to be serialized") - } - - - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) = - throw SearchUnavailable() - - override suspend fun searchAsync(query: String): ImageResponse = - ImageResponse("", source = name, url = null, occurredException = SearchUnavailable()) - - override suspend fun searchRawAsync(query: String): Uri? = throw SearchUnavailable() - - override fun serializeSearchResponse(response: Response): ImageResponse = throw SearchUnavailable() - - override fun serializeSearchResponse(input: String): ImageResponse = throw SearchUnavailable() - - override fun searchWithCallback(query: String, callback: (response: ImageResponse?) -> Unit) = - callback(ImageResponse("", source = name, url = null, occurredException = SearchUnavailable())) -} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BuiltinSource.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BuiltinSource.kt deleted file mode 100644 index 197be49..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BuiltinSource.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.blusutils.smupe.data.image_sources.models.sources - -interface BuiltinSource \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/Extra.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/Extra.kt deleted file mode 100644 index c736496..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/Extra.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.blusutils.smupe.data.image_sources.models.sources - -class Extra { -} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/CatApiRepository.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/CatApiRepository.kt deleted file mode 100644 index 019dab8..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/CatApiRepository.kt +++ /dev/null @@ -1,115 +0,0 @@ -package net.blusutils.smupe.data.image_sources.repository - -import android.net.Uri -import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.JsonClass -import com.squareup.moshi.Moshi -import com.squareup.moshi.Types -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import net.blusutils.smupe.data.image_sources.models.sources.BuiltinSource -import net.blusutils.smupe.data.image_sources.models.sources.InternetImageSource -import net.blusutils.smupe.data.image_sources.models.sources.SearchInfo -import net.blusutils.smupe.data.image_sources.models.sources.SearchUnavailable -import net.blusutils.smupe.util.OkHttpUtils -import okhttp3.Response -import java.io.IOException -import java.lang.reflect.Type - -object CatApi : InternetImageSource( - "Cats As A Service", - null, null, - apiLink = "https://api.thecatapi.com/v1/images/search", - sourcePath = "", - dataPathSource = null, - search = SearchInfo(true, "https://api.thecatapi.com/v1/images/search", "","") // TODO! -), BuiltinSource { - - // IDK why it didn't work directly with generics - private val listOfCatsType: Type = - Types.newParameterizedType( - MutableList::class.java, - CatImageInfo::class.java - ) - private val catAdapter: JsonAdapter> = - Moshi.Builder() - .addLast(KotlinJsonAdapterFactory()) - .build() - .adapter(listOfCatsType) - - override suspend fun requestAsync(): ImageResponse? { - var err: IOException? = null - val resp = - try { - OkHttpUtils.getAsync(apiLink) - } catch (e: IOException) { - err = e - null - } - return resp?.let { - if (it.isSuccessful) - (serializeResponse(it)).apply { occurredException = err } - else - ImageResponse("", source = "cataas", url = null, occurredException = err) - } - } - - override suspend fun requestRawAsync(): Uri? = - requestAsync()?.url?.run { Uri.parse(this) } - - - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { - requestWithCallback { - callback(Uri.parse(it?.url)) - } - } - - override fun requestWithCallback(callback: (response: ImageResponse?) -> Unit) { - OkHttpUtils.get(apiLink) { resp, err -> - var catResp: ImageResponse? = null - if (err == null && resp != null && resp.isSuccessful) - catResp = serializeResponse(resp) - callback( - catResp?.apply { occurredException = err } - ?: ImageResponse("", source = "cataas", url = null, occurredException = err) - ) - } - } - - override fun serializeResponse(response: Response): ImageResponse = - serializeResponse(response.body!!.source().readUtf8()) - - override fun serializeResponse(input: String): ImageResponse { - return catAdapter.fromJson(input)?.getOrNull(0) as ImageResponse - } - - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) = - callback(null) - - override suspend fun searchAsync(query: String): ImageResponse = - ImageResponse("", source = "cataas", url = null, occurredException = SearchUnavailable()) - - override suspend fun searchRawAsync(query: String): Uri? = null - - override fun serializeSearchResponse(response: Response): ImageResponse? = null - - override fun serializeSearchResponse(input: String): ImageResponse? = null - - override fun searchWithCallback(query: String, callback: (response: ImageResponse?) -> Unit) = - callback(ImageResponse("", source = "cataas", url = null, occurredException = SearchUnavailable())) -} - -@JsonClass(generateAdapter = true) -data class CatImageInfo( - override val source: String = "cataas", - override val id: String, - override val url: String, - val width: Int, - val height: Int, - @Transient - override var occurredException: Exception? = null -) : ImageResponse( - source = source, - id = id, - url = url -) diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/GalleryRepository.kt b/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/GalleryRepository.kt deleted file mode 100644 index a1777d3..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/GalleryRepository.kt +++ /dev/null @@ -1,52 +0,0 @@ -package net.blusutils.smupe.data.image_sources.repository - -import android.os.Environment -import android.util.Log -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import net.blusutils.smupe.data.image_sources.models.sources.BasicLocalSource -import net.blusutils.smupe.data.image_sources.models.sources.BuiltinSource -import okio.FileNotFoundException -import java.io.File - -object Gallery : BasicLocalSource( - "Gallery", - null, null, - "/storage/emulated/0/${Environment.DIRECTORY_DCIM}/Camera", -), BuiltinSource { - override suspend fun requestAsync(): ImageResponse { - var files = File(apiLink).listFiles()?.filter { it.isFile && !it.name.startsWith(".") } - if (files!=null && files.isEmpty()) { files = null } - // Iterate through the files in the directory and return random one - return files?.random()?.let { - Log.d("Gallery", "Found file ${it.name}") - GalleryImageInfo( - id = it.name, - url = it.absolutePath - ) - } ?: ImageResponse("", source = "localgallery", url = null, occurredException = FileNotFoundException("No files found in gallery")) - } - - override fun requestWithCallback(callback: (response: ImageResponse?) -> Unit) { - var files = File(apiLink).listFiles()?.filter { it.isFile && !it.name.startsWith(".") } - if (files!=null && files.isEmpty()) { files = null } - callback( - files?.random()?.let { - Log.d("Gallery", "Found file ${it.name}") - GalleryImageInfo( - id = it.name, - url = it.absolutePath - ) - } ?: ImageResponse("", source = "localgallery", url = null, occurredException = FileNotFoundException("No files found in gallery")) - ) - } -} - -data class GalleryImageInfo( - override val source: String = "localgallery", - override val id: String, - override val url: String -) : ImageResponse( - source, - id, - url -) diff --git a/app/src/main/java/net/blusutils/smupe/data/licenses/License.kt b/app/src/main/java/net/blusutils/smupe/data/licenses/License.kt deleted file mode 100644 index 6fd298f..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/licenses/License.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.blusutils.smupe.data.licenses - -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource - -data class License( - val title: String, - val copyright: String, - val link: String, - val text: String -) { - companion object { - @Composable - fun fromLicenseInResources(license: LicenseInResources): License { - return License( - stringResource(license.title), - license.stringCopyright ?: stringResource(license.copyright), - license.stringLink ?: stringResource(license.link), - stringResource(license.text) - ) - } - } -} - diff --git a/app/src/main/java/net/blusutils/smupe/data/licenses/LicenseInResources.kt b/app/src/main/java/net/blusutils/smupe/data/licenses/LicenseInResources.kt deleted file mode 100644 index 9b2025b..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/licenses/LicenseInResources.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.blusutils.smupe.data.licenses - -data class LicenseInResources( - val title: Int, - val copyright: Int, - val link: Int, - val text: Int, - val stringCopyright: String? = null, - val stringLink: String? = null -) \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/licenses/LicensedObject.kt b/app/src/main/java/net/blusutils/smupe/data/licenses/LicensedObject.kt deleted file mode 100644 index 56ad788..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/licenses/LicensedObject.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.blusutils.smupe.data.licenses - -data class LicensedObject( - val title: String, - val license: LicenseInResources -) \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/licenses/LicensesRepo.kt b/app/src/main/java/net/blusutils/smupe/data/licenses/LicensesRepo.kt deleted file mode 100644 index bd1365a..0000000 --- a/app/src/main/java/net/blusutils/smupe/data/licenses/LicensesRepo.kt +++ /dev/null @@ -1,171 +0,0 @@ -package net.blusutils.smupe.data.licenses - -import net.blusutils.smupe.R - -// Never ever do like this -object LicensesRepo { - - private val gh = "https://github.com" - val apache = R.string.apache2_license_title - val apache_text = R.string.apache2_license_text_appendix - private val aosp = "2024 The Android Open Source Project" - private val jb = "2024 JetBrains" - private val googleProto = "2008 Google Inc." - private val google = "2024 Google Inc." - private val square = "2019 Square, Inc." - private val coil = "2023 Coil Contributors" - private val gildor = "2019 gildor (Andrey Mischenko)" - private val once = "2021 Jon Finerty" - private val reorderable = "2022 André Claßen" - private val swipecards = "2023 Amir Hossein Aghajari" - private val android_repo = "https://android.googlesource.com/platform/frameworks/support/+/refs/heads" - private val aosp_jetpack = "$android_repo/androidx-main/LICENSE.txt" - private val aosp_room = "$android_repo/android-room-release/LICENSE.txt" - - // TODO use Flows - val licenses = listOf( - LicensedObject( - "Kotlin", - LicenseInResources( - apache, 0, 0, apache_text, jb, - "$gh/JetBrains/kotlin/blob/master/license/LICENSE.txt" - ) - ), - LicensedObject( - "AndroidX", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Coil", - LicenseInResources( - apache, 0, 0, apache_text, - coil, "$gh/coil-kt/coil/blob/master/LICENSE.txt" - ) - ), - LicensedObject( - "Protocol Buffers", - LicenseInResources( - R.string.protobufs_license_title, - 0, - 0, - R.string.protobufs_license_text, - googleProto, - "$gh/protocolbuffers/protobuf/blob/main/LICENSE" - ) - ), - LicensedObject( - "Material Icons", - LicenseInResources( - apache, 0, 0, apache_text, google, - "$gh/google/material-design-icons/blob/master/LICENSE" - ) - ), - LicensedObject( - "ComponentActivity, AppCompatActivity", - LicenseInResources(apache, 0, 0, apache_text, google, aosp_jetpack) - ), - LicensedObject( - "Jetpack Compose Libraries BOM", - LicenseInResources(apache, 0, 0, apache_text, google, aosp_jetpack) - ), - LicensedObject( - "Compose Foundation", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose UI", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose Navigation", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose Graphics", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose UI Preview Tooling", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose Material3 Components", - LicenseInResources(apache, 0, 0, apache_text, google, aosp_jetpack) - ), - LicensedObject( - "AndroidX Test Library", - LicenseInResources(apache, 0, 0, apache_text, google, aosp_jetpack) - ), - LicensedObject( - "Compose Testing For JUnit4", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose Tooling", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Compose Testing Manifest Dependency", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "Room Database", - LicenseInResources( - apache, 0, 0, apache_text, aosp, aosp_room - ) - ), - LicensedObject( - "Proto DataStore", - LicenseInResources(apache, 0, 0, apache_text, aosp, aosp_jetpack) - ), - LicensedObject( - "KSP API", - LicenseInResources( - apache, 0, 0, apache_text, - google, "$gh/google/ksp/blob/main/LICENSE" - ) - ), - LicensedObject( - "LazySwipeCards", - LicenseInResources( - apache, 0, 0, apache_text, - swipecards, "$gh/Aghajari/LazySwipeCards/blob/main/LICENSE" - ) - ), - LicensedObject( - "OkHttp", - LicenseInResources( - apache, 0, 0, apache_text, - square, "$gh/square/okhttp/blob/master/LICENSE.txt" - ) - ), - LicensedObject( - "Moshi", - LicenseInResources( - apache, 0, 0, apache_text, - square, "$gh/square/moshi/blob/master/LICENSE.txt" - ) - ), - LicensedObject( - "Kotlin Coroutines OkHttp", - LicenseInResources( - apache, 0, 0, apache_text, - gildor, "$gh/gildor/kotlin-coroutines-okhttp/blob/master/LICENSE.txt" - ) - ), - LicensedObject( - "Once", - LicenseInResources( - apache, 0, 0, apache_text, - once, "$gh/jonfinerty/Once/blob/master/LICENSE.txt" - ) - ), - LicensedObject( - "Compose LazyList/Grid reorder", - LicenseInResources( - apache, 0, 0, apache_text, - reorderable, "$gh/aclassen/ComposeReorderable/blob/main/LICENSE" - ) - ) - ) -} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/logic/api_definitions/data/network/service/implementation/GalleryService.kt b/app/src/main/java/net/blusutils/smupe/logic/api_definitions/data/network/service/implementation/GalleryService.kt new file mode 100644 index 0000000..b0b9f0f --- /dev/null +++ b/app/src/main/java/net/blusutils/smupe/logic/api_definitions/data/network/service/implementation/GalleryService.kt @@ -0,0 +1,53 @@ +package net.blusutils.smupe.logic.api_definitions.data.network.service.implementation + +import android.os.Environment +import android.util.Log +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.LocalImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BuiltinSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.SampleLocalSource +import okio.FileNotFoundException +import java.io.File + +object Gallery : SampleLocalSource( + "Gallery", + null, null, + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath, +), BuiltinSource { + override suspend fun requestAsync(): ImageResponse { + var files = File(apiLink).listFiles()?.filter { it.isFile && !it.name.startsWith(".") } + if (files!=null && files.isEmpty()) { files = null } + // Iterate through the files in the directory and return random one + return files?.random()?.let { + Log.d("Gallery", "Found file ${it.name}") + LocalImageResponse( + id = it.name, + url = it.absolutePath + ) + } ?: ImageResponse( + "", + source = "localgallery", + url = null, + occurredException = FileNotFoundException("No files found in gallery") + ) + } + + override fun requestWithCallback(callback: (response: ImageResponse?) -> Unit) { + var files = File(apiLink).listFiles()?.filter { it.isFile && !it.name.startsWith(".") } + if (files!=null && files.isEmpty()) { files = null } + callback( + files?.random()?.let { + Log.d("Gallery", "Found file ${it.name}") + LocalImageResponse( + id = it.name, + url = it.absolutePath + ) + } ?: ImageResponse( + "", + source = "localgallery", + url = null, + occurredException = FileNotFoundException("No files found in gallery") + ) + ) + } +} diff --git a/app/src/main/java/net/blusutils/smupe/logic/api_definitions/domain/utils/implementation/AndroidApiDefWrapper.kt b/app/src/main/java/net/blusutils/smupe/logic/api_definitions/domain/utils/implementation/AndroidApiDefWrapper.kt new file mode 100644 index 0000000..8c20e9a --- /dev/null +++ b/app/src/main/java/net/blusutils/smupe/logic/api_definitions/domain/utils/implementation/AndroidApiDefWrapper.kt @@ -0,0 +1,71 @@ +package net.blusutils.smupe.logic.api_definitions.domain.utils.implementation + +import android.content.Context +import android.util.Log +import androidx.core.content.ContextCompat +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import net.blusutils.smupe.CurrentApiDefParams +import net.blusutils.smupe.common.api_definitions.data.network.service.DirectLinkImageService +import net.blusutils.smupe.common.api_definitions.data.network.service.JsonImageService +import net.blusutils.smupe.common.api_definitions.data.network.service.LocalRepository +import net.blusutils.smupe.common.api_definitions.data.network.service.PlainTextImageService +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.utils.ApiDefinitionFileWrapper +import java.io.File + +class AndroidApiDefWrapper(val context: Context) : ApiDefinitionFileWrapper { + override val apiDefinitionsDirectory: File + get() = ContextCompat.getExternalFilesDirs(context, "api_def").first() + + override fun loadAllApiDefs() { + apiDefinitionsDirectory.listFiles()?.let { + if (it.isEmpty()) { + Log.d("loadAllApiDefs", "No api defs found") + } else + it.forEach { + if (it.extension == "json") + readFile(it.name)?.let { + CurrentApiDefParams.dynamicRepos.add(it) + } + } + } + } + + override fun readFile(filename: String): BaseImageSource? { + apiDefinitionsDirectory.mkdirs() + + val file = File(apiDefinitionsDirectory, filename) + val adapter = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build() + + return file.run { + if (!exists()) null + else { + val txt = readText() +// if (txt.matches("^\\s*\\{".toRegex())) { + val regexMatches = "\"mode\":\\s*\"\\w*?\"".toRegex().find(txt) + regexMatches?.let { + SourceMode.Local + val cls = when (regexMatches.value.split(":")[1].trim()) { + "\"Local\"" -> LocalRepository::class.java + "\"Internet\"" -> BaseInternetImageSource::class.java + "\"InternetDirectLink\"" -> DirectLinkImageService::class.java + "\"InternetPlainText\"" -> PlainTextImageService::class.java + else -> JsonImageService::class.java + } + adapter.adapter(cls).fromJson(txt) + } + } + } + } + + override fun writeFile(filename: String, apiDef: T, cls: Class) { + apiDefinitionsDirectory.mkdirs() + + val file = File(apiDefinitionsDirectory, filename) + val adapter = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build().adapter(cls) + file.writeText(adapter.toJson(apiDef)) + } +} diff --git a/app/src/main/java/net/blusutils/smupe/data/room/dao/FavoritesDao.kt b/app/src/main/java/net/blusutils/smupe/logic/db/dao/FavoritesDao.kt similarity index 88% rename from app/src/main/java/net/blusutils/smupe/data/room/dao/FavoritesDao.kt rename to app/src/main/java/net/blusutils/smupe/logic/db/dao/FavoritesDao.kt index 25b5d37..faa628a 100644 --- a/app/src/main/java/net/blusutils/smupe/data/room/dao/FavoritesDao.kt +++ b/app/src/main/java/net/blusutils/smupe/logic/db/dao/FavoritesDao.kt @@ -1,10 +1,10 @@ -package net.blusutils.smupe.data.room.dao +package net.blusutils.smupe.logic.db.dao import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert import androidx.room.Query -import net.blusutils.smupe.data.room.entities.Favorite +import net.blusutils.smupe.logic.db.entity.Favorite @Dao interface FavoritesDao { diff --git a/app/src/main/java/net/blusutils/smupe/data/room/Database.kt b/app/src/main/java/net/blusutils/smupe/logic/db/database/Database.kt similarity index 89% rename from app/src/main/java/net/blusutils/smupe/data/room/Database.kt rename to app/src/main/java/net/blusutils/smupe/logic/db/database/Database.kt index 2d64b07..d60ac42 100644 --- a/app/src/main/java/net/blusutils/smupe/data/room/Database.kt +++ b/app/src/main/java/net/blusutils/smupe/logic/db/database/Database.kt @@ -1,12 +1,12 @@ -package net.blusutils.smupe.data.room +package net.blusutils.smupe.logic.db.database import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.migration.Migration -import net.blusutils.smupe.data.room.dao.FavoritesDao -import net.blusutils.smupe.data.room.entities.Favorite +import net.blusutils.smupe.logic.db.dao.FavoritesDao +import net.blusutils.smupe.logic.db.entity.Favorite // TODO: https://stackoverflow.com/questions/44322178/room-schema-export-directory-is-not-provided-to-the-annotation-processor-so-we @Database(entities = [Favorite::class], version = 13) abstract class AppDatabase : RoomDatabase() { diff --git a/app/src/main/java/net/blusutils/smupe/data/room/entities/Favorite.kt b/app/src/main/java/net/blusutils/smupe/logic/db/entity/Favorite.kt similarity index 83% rename from app/src/main/java/net/blusutils/smupe/data/room/entities/Favorite.kt rename to app/src/main/java/net/blusutils/smupe/logic/db/entity/Favorite.kt index 007bdc7..4d22bfc 100644 --- a/app/src/main/java/net/blusutils/smupe/data/room/entities/Favorite.kt +++ b/app/src/main/java/net/blusutils/smupe/logic/db/entity/Favorite.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.room.entities +package net.blusutils.smupe.logic.db.entity import androidx.room.Entity import androidx.room.PrimaryKey diff --git a/app/src/main/java/net/blusutils/smupe/data/room/util/FavesUtil.kt b/app/src/main/java/net/blusutils/smupe/logic/db/util/FavesUtil.kt similarity index 84% rename from app/src/main/java/net/blusutils/smupe/data/room/util/FavesUtil.kt rename to app/src/main/java/net/blusutils/smupe/logic/db/util/FavesUtil.kt index f2c37b8..87393a7 100644 --- a/app/src/main/java/net/blusutils/smupe/data/room/util/FavesUtil.kt +++ b/app/src/main/java/net/blusutils/smupe/logic/db/util/FavesUtil.kt @@ -1,8 +1,8 @@ -package net.blusutils.smupe.data.room.util +package net.blusutils.smupe.logic.db.util -import net.blusutils.smupe.data.room.AppDatabase -import net.blusutils.smupe.data.room.entities.Favorite -import net.blusutils.smupe.util.calculateRoomResourceId +import net.blusutils.smupe.common.utils.calculateResourceId +import net.blusutils.smupe.logic.db.database.AppDatabase +import net.blusutils.smupe.logic.db.entity.Favorite /** * Helper class used as shorthand for [net.blusutils.smupe.data.room.AppDatabase.favesDao] @@ -15,7 +15,7 @@ object FavesUtil { * @return whether resource added to favorites or not */ suspend fun tryAddFave(fave: String): Boolean { - val id = calculateRoomResourceId(fave) + val id = calculateResourceId(fave) return tryAddFave( Favorite( id, @@ -57,7 +57,7 @@ object FavesUtil { */ suspend fun getFaveById(id: String): Boolean { return AppDatabase.favesDao.getFavoritesByID( - calculateRoomResourceId(id) + calculateResourceId(id) ).isNotEmpty() } } \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/logic/license_storage/domain/repository/implementation/AndroidLicensesRepository.kt b/app/src/main/java/net/blusutils/smupe/logic/license_storage/domain/repository/implementation/AndroidLicensesRepository.kt new file mode 100644 index 0000000..6016246 --- /dev/null +++ b/app/src/main/java/net/blusutils/smupe/logic/license_storage/domain/repository/implementation/AndroidLicensesRepository.kt @@ -0,0 +1,120 @@ +package net.blusutils.smupe.logic.license_storage.domain.repository.implementation + +import net.blusutils.smupe.common.license_storage.domain.implementation.ApacheLicense +import net.blusutils.smupe.common.license_storage.domain.implementation.ProtobufLicense +import net.blusutils.smupe.common.license_storage.domain.model.License +import net.blusutils.smupe.common.license_storage.domain.repository.LicenseRepository + +// Never ever do like this +object AndroidLicensesRepository : LicenseRepository { + + private val gh = "https://github.com" + private val aosp = "2024 The Android Open Source Project" + private val jb = "2024 JetBrains" + private val googleProto = "2008 Google Inc." + private val google = "2024 Google Inc." + private val square = "2019 Square, Inc." + private val coil = "2023 Coil Contributors" + private val gildor = "2019 gildor (Andrey Mischenko)" + private val once = "2021 Jon Finerty" + private val reorderable = "2022 André Claßen" + private val swipecards = "2023 Amir Hossein Aghajari" + private val android_repo = "https://android.googlesource.com/platform/frameworks/support/+/refs/heads" + private val aosp_jetpack = "$android_repo/androidx-main/LICENSE.txt" + private val aosp_room = "$android_repo/android-room-release/LICENSE.txt" + + private data class AospLicense( + val aospTitle: String, + val licenseLink: String = aosp_jetpack + ) : License( + aospTitle, + ApacheLicense.content, + aosp, + licenseLink + ) + + // TODO use Flows + override val licenses = listOf( + License( + title = "Kotlin", + text = ApacheLicense.content, + copyright = jb, + link = "$gh/JetBrains/kotlin/blob/master/license/LICENSE.txt" + ), + AospLicense("AndroidX"), + License( + title = "Coil", + text = ApacheLicense.content, + copyright = coil, + link = "$gh/coil-kt/coil/blob/master/LICENSE.txt" + ), + License( + title = "Protocol Buffers", + text = ProtobufLicense.content, + copyright = googleProto, + link = "$gh/protocolbuffers/protobuf/blob/main/LICENSE" + ), + License( + title = "Material Icons", + text = ApacheLicense.content, + copyright = google, + link = "$gh/google/material-design-icons/blob/master/LICENSE" + ), + AospLicense("AndroidX ComponentActivity, AppCompatActivity"), + AospLicense("Jetpack Compose Libraries BOM"), + AospLicense("Compose Foundation"), + AospLicense("Compose UI"), + AospLicense("Compose Navigation"), + AospLicense("Compose Graphics"), + AospLicense("Compose UI Preview Tooling"), + AospLicense("Compose Material3 Components"), + AospLicense("AndroidX Test Library"), + AospLicense("Compose Testing For JUnit4"), + AospLicense("Compose Tooling"), + AospLicense("Compose Testing Manifest Dependency"), + AospLicense("Room Database", aosp_room), + AospLicense("Proto DataStore"), + License( + title = "KSP API", + text = ApacheLicense.content, + copyright = google, + link = "$gh/google/ksp/blob/main/LICENSE" + ), + License( + title = "LazySwipeCards", + text = ApacheLicense.content, + copyright = swipecards, + link = "$gh/Aghajari/LazySwipeCards/blob/main/LICENSE" + ), + License( + title = "OkHttp", + text = ApacheLicense.content, + copyright = square, + link = "$gh/square/okhttp/blob/master/LICENSE.txt" + ), + License( + title = "Moshi", + text = ApacheLicense.content, + copyright = square, + link = "$gh/square/moshi/blob/master/LICENSE.txt" + ), + License( + title = "Kotlin Coroutines OkHttp", + text = ApacheLicense.content, + copyright = gildor, + link = "$gh/gildor/kotlin-coroutines-okhttp/blob/master/LICENSE.txt" + ), + License( + title = "Once", + text = ApacheLicense.content, + copyright = once, + link = "$gh/jonfinerty/Once/blob/master/LICENSE.txt" + ), + License( + title = "Compose LazyList/Grid reorder", + text = ApacheLicense.content, + copyright = reorderable, + link = "$gh/aclassen/ComposeReorderable/blob/main/LICENSE" + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/proto_datastore/SettingsProtobufSerializer.kt b/app/src/main/java/net/blusutils/smupe/logic/settings/domain/util/SettingsProtobufSerializer.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/data/proto_datastore/SettingsProtobufSerializer.kt rename to app/src/main/java/net/blusutils/smupe/logic/settings/domain/util/SettingsProtobufSerializer.kt index 2b8f826..dfde8b3 100644 --- a/app/src/main/java/net/blusutils/smupe/data/proto_datastore/SettingsProtobufSerializer.kt +++ b/app/src/main/java/net/blusutils/smupe/logic/settings/domain/util/SettingsProtobufSerializer.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.proto_datastore +package net.blusutils.smupe.logic.settings.domain.util import androidx.datastore.core.CorruptionException import androidx.datastore.core.Serializer diff --git a/app/src/main/java/net/blusutils/smupe/data/proto_datastore/contextProtoDataStoreExtension.kt b/app/src/main/java/net/blusutils/smupe/logic/settings/domain/util/contextProtoDataStoreExtension.kt similarity index 84% rename from app/src/main/java/net/blusutils/smupe/data/proto_datastore/contextProtoDataStoreExtension.kt rename to app/src/main/java/net/blusutils/smupe/logic/settings/domain/util/contextProtoDataStoreExtension.kt index c6e369c..1e4176a 100644 --- a/app/src/main/java/net/blusutils/smupe/data/proto_datastore/contextProtoDataStoreExtension.kt +++ b/app/src/main/java/net/blusutils/smupe/logic/settings/domain/util/contextProtoDataStoreExtension.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.proto_datastore +package net.blusutils.smupe.logic.settings.domain.util import android.content.Context import androidx.datastore.core.DataStore diff --git a/app/src/main/java/net/blusutils/smupe/ui/misc/CenteredContainer.kt b/app/src/main/java/net/blusutils/smupe/presentation/common/CenteredContainer.kt similarity index 96% rename from app/src/main/java/net/blusutils/smupe/ui/misc/CenteredContainer.kt rename to app/src/main/java/net/blusutils/smupe/presentation/common/CenteredContainer.kt index d10d62e..0bcfa43 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/misc/CenteredContainer.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/common/CenteredContainer.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.misc +package net.blusutils.smupe.presentation.common import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/net/blusutils/smupe/ui/Theme.kt b/app/src/main/java/net/blusutils/smupe/presentation/theme/Theme.kt similarity index 98% rename from app/src/main/java/net/blusutils/smupe/ui/Theme.kt rename to app/src/main/java/net/blusutils/smupe/presentation/theme/Theme.kt index 1913509..dcf2a63 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/Theme.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/theme/Theme.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui +package net.blusutils.smupe.presentation.theme import android.app.Activity import android.os.Build diff --git a/app/src/main/java/net/blusutils/smupe/ui/about/AboutScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/AboutScreen.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/ui/about/AboutScreen.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/about/AboutScreen.kt index 1b2bd2a..b9fab32 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/about/AboutScreen.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/AboutScreen.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.about +package net.blusutils.smupe.presentation.ui.about import android.content.pm.PackageManager import androidx.compose.foundation.Image @@ -22,9 +22,11 @@ import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import net.blusutils.smupe.R -import net.blusutils.smupe.data.licenses.License -import net.blusutils.smupe.data.licenses.LicenseInResources -import net.blusutils.smupe.data.licenses.LicensesRepo +import net.blusutils.smupe.common.license_storage.domain.implementation.ApacheLicense +import net.blusutils.smupe.common.license_storage.domain.model.License +import net.blusutils.smupe.presentation.ui.about.components.EasterEgg +import net.blusutils.smupe.presentation.ui.about.components.LicenseDialog +import net.blusutils.smupe.presentation.ui.about.components.LicensesList import net.blusutils.smupe.util.openLink @@ -55,13 +57,11 @@ fun AboutScreen(close: () -> Unit = {}) { if (shouldDialogBeShown) LicenseDialog( - License.fromLicenseInResources( - LicenseInResources( - LicensesRepo.apache, - R.string.copyright, - R.string.license, - LicensesRepo.apache_text - ) + License( + ApacheLicense.name, + stringResource(R.string.copyright), + stringResource(R.string.license), + ApacheLicense.content ) ) { shouldDialogBeShown = false } diff --git a/app/src/main/java/net/blusutils/smupe/ui/about/WelcomeScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/WelcomeScreen.kt similarity index 96% rename from app/src/main/java/net/blusutils/smupe/ui/about/WelcomeScreen.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/about/WelcomeScreen.kt index 5e03c0c..f1eb510 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/about/WelcomeScreen.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/WelcomeScreen.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.about +package net.blusutils.smupe.presentation.ui.about import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image @@ -27,9 +27,9 @@ import com.airbnb.lottie.compose.LottieConstants import com.airbnb.lottie.compose.rememberLottieComposition import kotlinx.coroutines.launch import net.blusutils.smupe.R -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.ui.misc.CenteredContainer +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.common.CenteredContainer @OptIn(ExperimentalFoundationApi::class) @Preview diff --git a/app/src/main/java/net/blusutils/smupe/ui/about/EasterEgg.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/components/EasterEgg.kt similarity index 96% rename from app/src/main/java/net/blusutils/smupe/ui/about/EasterEgg.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/about/components/EasterEgg.kt index 34c857b..4b8602e 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/about/EasterEgg.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/components/EasterEgg.kt @@ -1,8 +1,6 @@ -package net.blusutils.smupe.ui.about +package net.blusutils.smupe.presentation.ui.about.components import android.graphics.Typeface -import android.webkit.WebView -import android.webkit.WebViewClient import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState @@ -22,7 +20,6 @@ import androidx.compose.ui.text.drawText import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.window.Dialog import coil.compose.AsyncImage import net.blusutils.smupe.R diff --git a/app/src/main/java/net/blusutils/smupe/ui/about/LicenseDialog.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/components/LicenseDialog.kt similarity index 91% rename from app/src/main/java/net/blusutils/smupe/ui/about/LicenseDialog.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/about/components/LicenseDialog.kt index 47d0b7d..5c46277 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/about/LicenseDialog.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/about/components/LicenseDialog.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.about +package net.blusutils.smupe.presentation.ui.about.components import android.graphics.Typeface import androidx.compose.foundation.clickable @@ -19,8 +19,8 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import net.blusutils.smupe.R -import net.blusutils.smupe.data.licenses.License -import net.blusutils.smupe.data.licenses.LicensesRepo.licenses +import net.blusutils.smupe.common.license_storage.domain.model.License +import net.blusutils.smupe.logic.license_storage.domain.repository.implementation.AndroidLicensesRepository.licenses import net.blusutils.smupe.util.openLink @@ -53,12 +53,10 @@ fun LicensesList(closeDialog: () -> Unit) { .fillMaxHeight(.9f) ) { LazyColumn { - items(licenses) { - val license = License.fromLicenseInResources(it.license) + items(licenses) { license -> ListItem( - headlineContent = { Text(it.title) }, + headlineContent = { Text(license.title) }, Modifier.clickable { showLicenseDetails = license }, - supportingContent = { Text(license.title) } ) } } diff --git a/app/src/main/java/net/blusutils/smupe/ui/favorites/FavesScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/favorites/FavesScreen.kt similarity index 90% rename from app/src/main/java/net/blusutils/smupe/ui/favorites/FavesScreen.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/favorites/FavesScreen.kt index 5aebc99..2550cdd 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/favorites/FavesScreen.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/favorites/FavesScreen.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.favorites +package net.blusutils.smupe.presentation.ui.favorites import android.content.Intent import android.net.Uri @@ -34,14 +34,18 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberMultiplePermissionsState import kotlinx.coroutines.launch import net.blusutils.smupe.R -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.data.room.entities.Favorite -import net.blusutils.smupe.data.room.util.FavesUtil -import net.blusutils.smupe.ui.misc.CenteredColumn -import net.blusutils.smupe.ui.misc.CenteredContainer -import net.blusutils.smupe.ui.misc.CenteredRow -import net.blusutils.smupe.util.* +import net.blusutils.smupe.common.utils.formatByKeywords +import net.blusutils.smupe.logic.db.entity.Favorite +import net.blusutils.smupe.logic.db.util.FavesUtil +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.common.CenteredColumn +import net.blusutils.smupe.presentation.common.CenteredContainer +import net.blusutils.smupe.presentation.common.CenteredRow +import net.blusutils.smupe.util.downloadResourceWithSnackbarAsync +import net.blusutils.smupe.util.globalAppPermissions +import net.blusutils.smupe.util.shareImage +import net.blusutils.smupe.util.sharePlainText @OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class) @Preview @@ -167,15 +171,15 @@ fun FavesScreen(closeFavorites: () -> Unit = {}) { ) } } - } else downloadResourceWithSnackbarAsync( - scope, - snackbarHostState, - Uri.parse(currentImage?.link), - ctx, - downloadingText, - failedText, - doneText - ) + } else Uri.parse(currentImage?.link) + .downloadResourceWithSnackbarAsync( + scope, + snackbarHostState, + ctx, + downloadingText, + failedText, + doneText + ) }) { Icon(Icons.Default.SaveAlt, null) } diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/AddApiDefScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/AddApiDefScreen.kt similarity index 97% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/AddApiDefScreen.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/AddApiDefScreen.kt index fcaa08a..0585b31 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/AddApiDefScreen.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/AddApiDefScreen.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import android.util.Log import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/AddInternetApiDef.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/AddInternetApiDef.kt similarity index 97% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/AddInternetApiDef.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/AddInternetApiDef.kt index 54c55ce..7f6f913 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/AddInternetApiDef.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/AddInternetApiDef.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import androidx.compose.foundation.layout.* import androidx.compose.foundation.selection.selectable @@ -14,7 +14,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import net.blusutils.smupe.R -import net.blusutils.smupe.ui.misc.CenteredColumn +import net.blusutils.smupe.presentation.common.CenteredColumn @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsEditList.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsEditList.kt similarity index 93% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsEditList.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsEditList.kt index 8665b8d..14d85bd 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsEditList.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsEditList.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import android.util.Log import androidx.compose.animation.AnimatedVisibility @@ -21,11 +21,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import coil.compose.AsyncImage +import net.blusutils.smupe.CurrentApiDefParams import net.blusutils.smupe.R -import net.blusutils.smupe.data.image_sources.ApiDefFileWrapper.apiDefDirectory -import net.blusutils.smupe.data.image_sources.CurrentApiDefParams -import net.blusutils.smupe.data.image_sources.models.sources.BaseImageSource -import net.blusutils.smupe.data.image_sources.models.sources.BuiltinSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BuiltinSource +import net.blusutils.smupe.logic.api_definitions.domain.utils.implementation.AndroidApiDefWrapper import java.io.File @OptIn(ExperimentalMaterial3Api::class) @@ -48,7 +48,7 @@ fun ApiDefsEditList(navigator: NavHostController, close: () -> Unit) { Log.d("ApiDefsEditList", "Deleting $it") CurrentApiDefParams.dynamicRepos.remove(it) CurrentApiDefParams.currentApi = CurrentApiDefParams.dynamicRepos.random() - File(ctx.apiDefDirectory, "${it.name}.json").delete() + File(AndroidApiDefWrapper(ctx).apiDefinitionsDirectory, "${it.name}.json").delete() tmpSrc = null } Unit diff --git a/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsEditScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsEditScreen.kt new file mode 100644 index 0000000..4618015 --- /dev/null +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsEditScreen.kt @@ -0,0 +1,14 @@ +package net.blusutils.smupe.presentation.ui.image_sources + +import androidx.compose.runtime.Composable +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseLocalImageSource + +@Composable +fun ApiDefsEditScreen(src: BaseImageSource? = null, close: () -> Unit = {}) { + when (src) { + is BaseInternetImageSource? -> JsonApiDefsEditScreen(src, close) + is BaseLocalImageSource? -> LocalApiDefsEditScreen(src, close) + } +} diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsSelectorFlyout.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsSelectorFlyout.kt similarity index 98% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsSelectorFlyout.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsSelectorFlyout.kt index b0be21f..9767283 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsSelectorFlyout.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/ApiDefsSelectorFlyout.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import android.util.Log import androidx.compose.foundation.layout.* @@ -26,8 +26,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import kotlinx.coroutines.launch +import net.blusutils.smupe.CurrentApiDefParams import net.blusutils.smupe.R -import net.blusutils.smupe.data.image_sources.CurrentApiDefParams @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/JsonApiDefsEditScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/JsonApiDefsEditScreen.kt similarity index 90% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/JsonApiDefsEditScreen.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/JsonApiDefsEditScreen.kt index 19b7ebf..b796e0e 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/JsonApiDefsEditScreen.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/JsonApiDefsEditScreen.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import android.util.Log import androidx.compose.foundation.layout.fillMaxSize @@ -14,24 +14,30 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import kotlinx.coroutines.launch -import net.blusutils.smupe.data.image_sources.ApiDefFileWrapper -import net.blusutils.smupe.data.image_sources.CurrentApiDefParams -import net.blusutils.smupe.data.image_sources.models.sources.* -import net.blusutils.smupe.data.image_sources.repository.JsonRepository -import net.blusutils.smupe.ui.misc.CenteredRow -import net.blusutils.smupe.util.OkHttpUtils +import net.blusutils.smupe.CurrentApiDefParams +import net.blusutils.smupe.common.api_definitions.data.network.service.JsonImageService +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.BlurHashInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SearchInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.TagsInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.request.AuthType +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization +import net.blusutils.smupe.common.utils.OkHttpUtils +import net.blusutils.smupe.common.utils.getJsonValueFromPath +import net.blusutils.smupe.logic.api_definitions.domain.utils.implementation.AndroidApiDefWrapper +import net.blusutils.smupe.presentation.common.CenteredRow import net.blusutils.smupe.util.checkIsLink import net.blusutils.smupe.util.checkIsLinkAndNotBlank -import net.blusutils.smupe.util.getJsonValueFromPath @OptIn(ExperimentalMaterial3Api::class) @Preview @Composable -fun JsonApiDefsEditScreen(src: InternetImageSource? = null, close: () -> Unit = {}) { +fun JsonApiDefsEditScreen(src: BaseInternetImageSource? = null, close: () -> Unit = {}) { Log.d("ApiDefsEditScreen", "Appeared") val ctx = LocalContext.current + val apiDefWrapper = AndroidApiDefWrapper(ctx) val scope = rememberCoroutineScope() @@ -87,7 +93,7 @@ fun JsonApiDefsEditScreen(src: InternetImageSource? = null, close: () -> Unit = var pathDelimiterError by rememberSaveable { mutableStateOf(false) } var value by rememberSaveable { mutableStateOf("") } - var source by rememberSaveable { mutableStateOf(null) } + var source by rememberSaveable { mutableStateOf(null) } fun validate() : Boolean { nameError = name.isBlank() @@ -117,12 +123,17 @@ fun JsonApiDefsEditScreen(src: InternetImageSource? = null, close: () -> Unit = val launch: () -> Unit = { Log.d("ApiDefsEditScreen.Launch", "Launching") if(validate()) { - source = JsonRepository( + source = JsonImageService( name, icon, description, link, - SearchInfo(isSearch, searchUrl, searchPath, searchIdPath), + SearchInfo( + isSearch, + searchUrl, + searchPath, + searchIdPath + ), Authorization( authType, authPayload @@ -151,7 +162,7 @@ fun JsonApiDefsEditScreen(src: InternetImageSource? = null, close: () -> Unit = scope.launch { value = OkHttpUtils.getAsync(link).body?.source()?.readUtf8() ?: "ERROR!" Log.d("ApiDefsEditScreen.Launch", "Got response") - ApiDefFileWrapper.writeFile(ctx, "$name.json", source!!, InternetImageSource::class.java) + apiDefWrapper.writeFile("$name.json", source!!, BaseInternetImageSource::class.java) }.invokeOnCompletion { close() } @@ -160,11 +171,10 @@ fun JsonApiDefsEditScreen(src: InternetImageSource? = null, close: () -> Unit = val closeEntire = { if (source != null) - ApiDefFileWrapper.writeFile( - ctx, + apiDefWrapper.writeFile( "$name.json", - source as InternetImageSource, - InternetImageSource::class.java + source as BaseInternetImageSource, + BaseInternetImageSource::class.java ) close() } @@ -177,7 +187,7 @@ fun JsonApiDefsEditScreen(src: InternetImageSource? = null, close: () -> Unit = link = it.apiLink path = it.sourcePath it.dataPathSource?.let { dataPath = it } - (it as JsonRepository).sourceIdPath?.let { idPath = it } + (it as JsonImageService).sourceIdPath?.let { idPath = it } it.search?.let { isSearch = it.supported diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/LocalApiDefsEditScreen.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/LocalApiDefsEditScreen.kt similarity index 89% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/LocalApiDefsEditScreen.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/LocalApiDefsEditScreen.kt index 8500825..3b8b98a 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/LocalApiDefsEditScreen.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/LocalApiDefsEditScreen.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts @@ -19,17 +19,17 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberMultiplePermissionsState +import net.blusutils.smupe.CurrentApiDefParams import net.blusutils.smupe.R -import net.blusutils.smupe.data.image_sources.ApiDefFileWrapper -import net.blusutils.smupe.data.image_sources.CurrentApiDefParams -import net.blusutils.smupe.data.image_sources.models.sources.LocalImageSource -import net.blusutils.smupe.data.image_sources.repository.LocalRepository +import net.blusutils.smupe.common.api_definitions.data.network.service.LocalRepository +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseLocalImageSource +import net.blusutils.smupe.logic.api_definitions.domain.utils.implementation.AndroidApiDefWrapper import net.blusutils.smupe.util.globalAppPermissions @OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class) @Preview @Composable -fun LocalApiDefsEditScreen(src: LocalImageSource? = null, close: () -> Unit = {}) { +fun LocalApiDefsEditScreen(src: BaseLocalImageSource? = null, close: () -> Unit = {}) { val ctx = LocalContext.current val scope = rememberCoroutineScope() @@ -73,11 +73,10 @@ fun LocalApiDefsEditScreen(src: LocalImageSource? = null, close: () -> Unit = {} CurrentApiDefParams.dynamicRepos.remove(CurrentApiDefParams.dynamicRepos.find { src!!.name == it.name }) } CurrentApiDefParams.dynamicRepos.add(source!!) - ApiDefFileWrapper.writeFile( - ctx, + AndroidApiDefWrapper(ctx).writeFile( "$name.json", - source as LocalImageSource, - LocalImageSource::class.java + source as BaseLocalImageSource, + BaseLocalImageSource::class.java ) } } diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/Settings.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/Settings.kt similarity index 97% rename from app/src/main/java/net/blusutils/smupe/ui/image_sources/Settings.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/Settings.kt index 028bd3e..fddc7a8 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/Settings.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/image_sources/Settings.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.image_sources +package net.blusutils.smupe.presentation.ui.image_sources import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues diff --git a/app/src/main/java/net/blusutils/smupe/ui/images/IndefiniteImageDisplay.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/images/IndefiniteImageDisplay.kt similarity index 95% rename from app/src/main/java/net/blusutils/smupe/ui/images/IndefiniteImageDisplay.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/images/IndefiniteImageDisplay.kt index 7f7e540..aae1f4a 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/images/IndefiniteImageDisplay.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/images/IndefiniteImageDisplay.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.images +package net.blusutils.smupe.presentation.ui.images import android.os.Build import android.util.Log @@ -39,17 +39,18 @@ import com.airbnb.lottie.compose.rememberLottieComposition import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberMultiplePermissionsState import kotlinx.coroutines.launch +import net.blusutils.smupe.CurrentApiDefParams import net.blusutils.smupe.R -import net.blusutils.smupe.data.image_sources.CurrentApiDefParams -import net.blusutils.smupe.data.image_sources.models.contents.BaseImageContent -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.data.room.util.FavesUtil -import net.blusutils.smupe.ui.misc.CenteredContainer -import net.blusutils.smupe.ui.misc.CenteredRow +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.BaseImageContent +import net.blusutils.smupe.common.utils.isInternetAvailable +import net.blusutils.smupe.common.utils.reorder +import net.blusutils.smupe.logic.db.util.FavesUtil +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.common.CenteredContainer +import net.blusutils.smupe.presentation.common.CenteredRow +import net.blusutils.smupe.presentation.ui.images.components.* import net.blusutils.smupe.util.globalAppPermissions -import net.blusutils.smupe.util.isInternetAvailable -import net.blusutils.smupe.util.reorder @OptIn(ExperimentalFoundationApi::class, ExperimentalPermissionsApi::class) @Composable @@ -82,7 +83,9 @@ fun IndefiniteImageDisplay( snackbarHost = { SnackbarHost(snackbarState) } ) { LazySwipeCards( - modifier = Modifier.fillMaxSize().padding(it), + modifier = Modifier + .fillMaxSize() + .padding(it), cardShape = RoundedCornerShape(16.dp), cardShadowElevation = 4.dp, visibleItemCount = 3 diff --git a/app/src/main/java/net/blusutils/smupe/ui/images/ActionMenuButtons.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/images/components/ActionMenuButtons.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/ui/images/ActionMenuButtons.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/images/components/ActionMenuButtons.kt index 8371e73..e539d74 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/images/ActionMenuButtons.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/images/components/ActionMenuButtons.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.images +package net.blusutils.smupe.presentation.ui.images.components import android.content.Context import android.content.Intent @@ -15,9 +15,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import net.blusutils.smupe.R import net.blusutils.smupe.SmupeSettings -import net.blusutils.smupe.data.room.util.FavesUtil +import net.blusutils.smupe.common.utils.formatByKeywords +import net.blusutils.smupe.logic.db.util.FavesUtil import net.blusutils.smupe.util.downloadResourceWithSnackbarAsync -import net.blusutils.smupe.util.formatByKeywords import net.blusutils.smupe.util.shareImage import net.blusutils.smupe.util.sharePlainText @@ -131,10 +131,9 @@ fun getDownloadButtonTriple( ) } } - } else downloadResourceWithSnackbarAsync( + } else imageUrl.downloadResourceWithSnackbarAsync( scope, snackbarState, - imageUrl, ctx, downloadingText, failedText, diff --git a/app/src/main/java/net/blusutils/smupe/ui/images/Favorite.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/images/components/Favorite.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/ui/images/Favorite.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/images/components/Favorite.kt index 9b3055f..f5744f8 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/images/Favorite.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/images/components/Favorite.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.images +package net.blusutils.smupe.presentation.ui.images.components import android.net.Uri import android.util.Log @@ -16,8 +16,8 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.vectorResource import kotlinx.coroutines.delay import net.blusutils.smupe.R -import net.blusutils.smupe.data.room.util.FavesUtil -import net.blusutils.smupe.ui.misc.CenteredContainer +import net.blusutils.smupe.logic.db.util.FavesUtil +import net.blusutils.smupe.presentation.common.CenteredContainer @OptIn(ExperimentalAnimationApi::class) @Composable diff --git a/app/src/main/java/net/blusutils/smupe/ui/App.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/root/App.kt similarity index 91% rename from app/src/main/java/net/blusutils/smupe/ui/App.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/root/App.kt index 0432ab2..59226e2 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/App.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/root/App.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui +package net.blusutils.smupe.presentation.ui.root import android.util.Log import androidx.compose.foundation.layout.Arrangement @@ -14,14 +14,14 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import jonathanfinerty.once.Once -import net.blusutils.smupe.data.image_sources.CurrentApiDefParams -import net.blusutils.smupe.data.image_sources.repository.Gallery -import net.blusutils.smupe.ui.about.AboutScreen -import net.blusutils.smupe.ui.about.WelcomeScreen -import net.blusutils.smupe.ui.favorites.FavesScreen -import net.blusutils.smupe.ui.image_sources.* -import net.blusutils.smupe.ui.images.IndefiniteImageDisplay -import net.blusutils.smupe.ui.settings.SettingsMenu +import net.blusutils.smupe.CurrentApiDefParams +import net.blusutils.smupe.logic.api_definitions.data.network.service.implementation.Gallery +import net.blusutils.smupe.presentation.ui.about.AboutScreen +import net.blusutils.smupe.presentation.ui.about.WelcomeScreen +import net.blusutils.smupe.presentation.ui.favorites.FavesScreen +import net.blusutils.smupe.presentation.ui.image_sources.* +import net.blusutils.smupe.presentation.ui.images.IndefiniteImageDisplay +import net.blusutils.smupe.presentation.ui.settings.SettingsMenu @Composable fun App() { diff --git a/app/src/main/java/net/blusutils/smupe/ui/MainModalFlyout.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/root/MainModalFlyout.kt similarity index 99% rename from app/src/main/java/net/blusutils/smupe/ui/MainModalFlyout.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/root/MainModalFlyout.kt index 82cdc8e..ff40a8d 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/MainModalFlyout.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/root/MainModalFlyout.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui +package net.blusutils.smupe.presentation.ui.root import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/SettingsMenu.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/SettingsMenu.kt similarity index 98% rename from app/src/main/java/net/blusutils/smupe/ui/settings/SettingsMenu.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/SettingsMenu.kt index 6fb745a..2a51f05 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/SettingsMenu.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/SettingsMenu.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.* @@ -16,9 +16,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch import net.blusutils.smupe.R -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.ui.settings.SettingsCard +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.ui.settings.components.* @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable @@ -152,7 +152,7 @@ fun SettingsMenu( // item { AdultModeCard() } // item { ProxyServerCard() } // item { BumpFavesCard() } - item { EnableCrashReportsCard() } +// item { EnableCrashReportsCard() } } } } diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/LanguageDialog.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/LanguageDialog.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/ui/settings/LanguageDialog.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/LanguageDialog.kt index f872a68..647d6d2 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/LanguageDialog.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/LanguageDialog.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings.components import androidx.appcompat.app.AppCompatDelegate import androidx.compose.foundation.layout.* @@ -15,8 +15,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.core.os.LocaleListCompat import net.blusutils.smupe.R -import net.blusutils.smupe.ui.misc.CenteredColumn -import net.blusutils.smupe.util.languages +import net.blusutils.smupe.common.languages +import net.blusutils.smupe.presentation.common.CenteredColumn @Composable fun LanguageDialog(hideLanguageDialog: () -> Unit) { diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/MenuOrderDialog.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/MenuOrderDialog.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/ui/settings/MenuOrderDialog.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/MenuOrderDialog.kt index e4e2d69..76805fe 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/MenuOrderDialog.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/MenuOrderDialog.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings.components import android.util.Log import androidx.compose.foundation.layout.* @@ -18,10 +18,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import kotlinx.coroutines.launch import net.blusutils.smupe.R -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.ui.misc.CenteredRow -import net.blusutils.smupe.util.reorderList +import net.blusutils.smupe.common.utils.reorderList +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.common.CenteredRow import org.burnoutcrew.reorderable.* diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/SettingsCard.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/SettingsCard.kt similarity index 91% rename from app/src/main/java/net/blusutils/smupe/ui/settings/SettingsCard.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/SettingsCard.kt index 3343138..23fc5e4 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/SettingsCard.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/SettingsCard.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings.components import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp -import net.blusutils.smupe.ui.misc.CenteredRow +import net.blusutils.smupe.presentation.common.CenteredRow @Composable fun SettingsCard( diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/SettingsChips.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/SettingsChips.kt similarity index 88% rename from app/src/main/java/net/blusutils/smupe/ui/settings/SettingsChips.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/SettingsChips.kt index e314fce..bd3af5b 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/SettingsChips.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/SettingsChips.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings.components import androidx.compose.material3.FilterChip import androidx.compose.material3.MaterialTheme diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/TextTemplateDialog.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/TextTemplateDialog.kt similarity index 91% rename from app/src/main/java/net/blusutils/smupe/ui/settings/TextTemplateDialog.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/TextTemplateDialog.kt index 42025c3..7c34271 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/TextTemplateDialog.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/TextTemplateDialog.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings.components import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape @@ -13,10 +13,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import kotlinx.coroutines.launch import net.blusutils.smupe.R -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.ui.misc.CenteredColumn -import net.blusutils.smupe.util.formatByKeywords +import net.blusutils.smupe.common.utils.formatByKeywords +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.common.CenteredColumn @Preview @Composable diff --git a/app/src/main/java/net/blusutils/smupe/ui/settings/ThemeDialog.kt b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/ThemeDialog.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/ui/settings/ThemeDialog.kt rename to app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/ThemeDialog.kt index 577e02d..6940de0 100644 --- a/app/src/main/java/net/blusutils/smupe/ui/settings/ThemeDialog.kt +++ b/app/src/main/java/net/blusutils/smupe/presentation/ui/settings/components/ThemeDialog.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.ui.settings +package net.blusutils.smupe.presentation.ui.settings.components import android.os.Build import androidx.compose.foundation.clickable @@ -19,9 +19,9 @@ import androidx.compose.ui.window.Dialog import kotlinx.coroutines.launch import net.blusutils.smupe.R import net.blusutils.smupe.Theme -import net.blusutils.smupe.data.proto_datastore.SettingsProtobufSerializer -import net.blusutils.smupe.data.proto_datastore.settingsDataStore -import net.blusutils.smupe.ui.misc.CenteredColumn +import net.blusutils.smupe.logic.settings.domain.util.SettingsProtobufSerializer +import net.blusutils.smupe.logic.settings.domain.util.settingsDataStore +import net.blusutils.smupe.presentation.common.CenteredColumn val dynColorAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S diff --git a/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsEditScreen.kt b/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsEditScreen.kt deleted file mode 100644 index 53f0967..0000000 --- a/app/src/main/java/net/blusutils/smupe/ui/image_sources/ApiDefsEditScreen.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.blusutils.smupe.ui.image_sources - -import androidx.compose.runtime.Composable -import net.blusutils.smupe.data.image_sources.models.sources.BaseImageSource -import net.blusutils.smupe.data.image_sources.models.sources.InternetImageSource -import net.blusutils.smupe.data.image_sources.models.sources.LocalImageSource - -@Composable -fun ApiDefsEditScreen(src: BaseImageSource? = null, close: () -> Unit = {}) { - when (src) { - is InternetImageSource? -> JsonApiDefsEditScreen(src, close) - is LocalImageSource? -> LocalApiDefsEditScreen(src, close) - } -} diff --git a/app/src/main/java/net/blusutils/smupe/util/downloadResourceWithSnackbarAsync.kt b/app/src/main/java/net/blusutils/smupe/util/DownloadsUtil.kt similarity index 57% rename from app/src/main/java/net/blusutils/smupe/util/downloadResourceWithSnackbarAsync.kt rename to app/src/main/java/net/blusutils/smupe/util/DownloadsUtil.kt index f05dd54..a623fdb 100644 --- a/app/src/main/java/net/blusutils/smupe/util/downloadResourceWithSnackbarAsync.kt +++ b/app/src/main/java/net/blusutils/smupe/util/DownloadsUtil.kt @@ -1,43 +1,73 @@ package net.blusutils.smupe.util +import android.app.DownloadManager import android.content.Context import android.net.Uri +import android.os.Environment import android.util.Log import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarHostState +import androidx.core.content.ContextCompat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import net.blusutils.smupe.common.utils.FileTypeAnalyzer +import java.io.File + +/** + * Download a file from an [Uri]. + * @param path the path to save the file to. + * @param context the Android context to use. + * @throws IllegalArgumentException if [path] is null or empty. + */ +fun Uri.downloadObjectOnUri(path: String?, context: Context) { + if (!path.isNullOrBlank()) { + Log.d("Uri.downloadObjectOnUri", "$path") + val req = DownloadManager.Request(this) + req.setDestinationInExternalPublicDir( + Environment.DIRECTORY_DOWNLOADS, path + ) + req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) + val mgr = ContextCompat.getSystemService(context, DownloadManager::class.java) + mgr?.enqueue(req) + } else throw IllegalArgumentException("path is null or empty") +} + +/** + * Download a file from an [Uri] (and save to [File]). + * @see [downloadObjectOnUri] + */ +fun Uri.downloadObjectOnUri(path: File, context: Context) = + this.downloadObjectOnUri(path.path, context) /** * Tries to download a resource and shows a snackbar during process. * @param coroutineScope A coroutine scope to launch the process. * @param snackbarHostState The snackbar host state, allows to show a snackbar. - * @param uri The resource uri to download. - * @param context The activity context to download the resource. + * @param ctx The Android context (yes). * @param downloadingText The text to show in the snackbar while downloading. * @param failedText The text to show in the snackbar if the download failed. * @param doneText The text to show in the snackbar if the download succeeded. */ -fun downloadResourceWithSnackbarAsync( +fun Uri?.downloadResourceWithSnackbarAsync( coroutineScope: CoroutineScope, snackbarHostState: SnackbarHostState, - uri: Uri?, - context: Context, + ctx: Context, downloadingText: String, failedText: String, doneText: String ) { + val uri = this coroutineScope.launch { snackbarHostState.showSnackbar(downloadingText, duration = SnackbarDuration.Short) } coroutineScope.launch { Log.d("downloadResourceAsync", "$uri, ${uri == null}, ${uri?.let { it::class.qualifiedName }}") if (uri != null) { - val ext = FileTypeAnalyzer.getExtension(uri) + val ext = FileTypeAnalyzer.getExtension(uri.toString()) Log.d("downloadResourceAsync", "Downloading: barMsg") uri.downloadObjectOnUri( "smupe.$ext", - context + ctx ) } }.invokeOnCompletion { exception -> diff --git a/app/src/main/java/net/blusutils/smupe/util/checkIsLink.kt b/app/src/main/java/net/blusutils/smupe/util/LinkAndUriChecks.kt similarity index 100% rename from app/src/main/java/net/blusutils/smupe/util/checkIsLink.kt rename to app/src/main/java/net/blusutils/smupe/util/LinkAndUriChecks.kt diff --git a/app/src/main/java/net/blusutils/smupe/util/permissionUtil.kt b/app/src/main/java/net/blusutils/smupe/util/PermissionUtils.kt similarity index 100% rename from app/src/main/java/net/blusutils/smupe/util/permissionUtil.kt rename to app/src/main/java/net/blusutils/smupe/util/PermissionUtils.kt diff --git a/app/src/main/java/net/blusutils/smupe/util/downloadObjectOnUri.kt b/app/src/main/java/net/blusutils/smupe/util/downloadObjectOnUri.kt deleted file mode 100644 index cdfbc8f..0000000 --- a/app/src/main/java/net/blusutils/smupe/util/downloadObjectOnUri.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.blusutils.smupe.util - -import android.app.DownloadManager -import android.content.Context -import android.net.Uri -import android.os.Environment -import android.util.Log -import androidx.core.content.ContextCompat -import java.io.File - -/** - * Download a file from an [Uri]. - * @param path the path to save the file to. - * @param context the Android context to use. - * @throws IllegalArgumentException if [path] is null or empty. - */ -fun Uri.downloadObjectOnUri(path: String?, context: Context) { - if (!path.isNullOrBlank()) { - Log.d("Uri.downloadObjectOnUri", "$path") - val req = DownloadManager.Request(this) - req.setDestinationInExternalPublicDir( - Environment.DIRECTORY_DOWNLOADS, path - ) - req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) - val mgr = ContextCompat.getSystemService(context, DownloadManager::class.java) - mgr?.enqueue(req) - } else throw IllegalArgumentException("path is null or empty") -} - -/** - * Download a file from an [Uri] (and save to [File]). - * @see [downloadObjectOnUri] - */ -fun Uri.downloadObjectOnUri(path: File, context: Context) = - this.downloadObjectOnUri(path.path, context) \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index edb4071..1282fe6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -3,8 +3,10 @@ Не все права выданы Смотри-ка, что нашлось в {app}\n{link} Случилась ошибка! - Наш Котик-Баголов нашёл ошибку! И он очень зол!\nЧестно, мы не ожидали этого, так что сообщите нам об этой ошибке! Сделайте Котика счастливым! + Наш Котик-Баголов нашёл ошибку! Честно, мы не ожидали этого, так что сообщите нам об этой ошибке. Сделайте Котика счастливым! + Выйти + Сообщить %1$s: ошибка. Напишите что-нибудь… Поиск в текущем API diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4a3db69..63cbf04 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -28,7 +28,9 @@ Not all permissions granted Look what I found in {app}\n{link} Well, that\'s a bug! - Our Kitty the Bugcatcher found a bug! He is so angry!\nWe really didn\'t expect that, so please report about it to us! Make Kitty happy! + Our Cat the Bugcatcher found a bug! We really didn\'t expect that, so please report about it to us. Make Cat happy! + Exit + Report %1$s: error. Type something… Search in current API diff --git a/app/src/main/res/values/strings_licenses.xml b/app/src/main/res/values/strings_licenses.xml index 1f4e569..9c210b8 100644 --- a/app/src/main/res/values/strings_licenses.xml +++ b/app/src/main/res/values/strings_licenses.xml @@ -1,78 +1,6 @@ - - View 3rd-party licenses View license View full or original license file - - - MIT License - Apache License 2.0 - Google Protocol Buffers license - MIT License\n -Copyright © %1$s -\n\nPermission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -\n\nThe above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - Copyright %1$s\n -\n -Licensed under the Apache License, Version 2.0 (the \"License\"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at -\n -http://www.apache.org/licenses/LICENSE-2.0\n -\n -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an \"AS IS\" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - Copyright %1$s All rights reserved.\n -\n -Redistribution and use in source and binary forms, with or without\n -modification, are permitted provided that the following conditions are\n -met:\n -\n -* Redistributions of source code must retain the above copyright\n -notice, this list of conditions and the following disclaimer.\n -* Redistributions in binary form must reproduce the above\n -copyright notice, this list of conditions and the following disclaimer\n -in the documentation and/or other materials provided with the\n -distribution.\n -* Neither the name of Google Inc. nor the names of its\n -contributors may be used to endorse or promote products derived from\n -this software without specific prior written permission.\n -\n -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n -\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n -\n -Code generated by the Protocol Buffer compiler is owned by the owner\n -of the input file used when generating it. This code is not\n -standalone and requires a support library to be linked with it. This\n -support library is itself covered by the above license. - \ No newline at end of file diff --git a/app/src/test/java/net/blusutils/smupe/ExampleUnitTest.kt b/app/src/test/java/net/blusutils/smupe/ExampleUnitTest.kt index 8dd8b6e..a2810e2 100644 --- a/app/src/test/java/net/blusutils/smupe/ExampleUnitTest.kt +++ b/app/src/test/java/net/blusutils/smupe/ExampleUnitTest.kt @@ -1,9 +1,8 @@ package net.blusutils.smupe +import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.Assert.* - /** * Example local unit test, which will execute on the development machine (host). * diff --git a/build.gradle.kts b/build.gradle.kts index f6e1c0d..90a4352 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,4 +4,6 @@ plugins { id("org.jetbrains.kotlin.android") version "1.9.10" apply false id("com.google.devtools.ksp") version "1.9.10-1.0.13" apply false id("org.jetbrains.dokka") version "1.9.10" + id("com.android.library") version "8.2.0" apply false + id("io.gitlab.arturbosch.detekt") version("1.23.3") } diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/common/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 0000000..9214a5b --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + kotlin("jvm") +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + + implementation("com.squareup.okhttp3:okhttp:4.12.0") // HTTP client + implementation("ru.gildor.coroutines:kotlin-coroutines-okhttp:1.0") // And Coroutines support for it + + implementation("com.squareup.moshi:moshi:1.14.0") // JSON parser + implementation("com.squareup.moshi:moshi-kotlin:1.14.0") + + // tests + testImplementation("junit:junit:4.13.2") +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/util/languagesList.kt b/common/src/main/java/net/blusutils/smupe/common/LanguagesList.kt similarity index 56% rename from app/src/main/java/net/blusutils/smupe/util/languagesList.kt rename to common/src/main/java/net/blusutils/smupe/common/LanguagesList.kt index af131f8..0926f94 100644 --- a/app/src/main/java/net/blusutils/smupe/util/languagesList.kt +++ b/common/src/main/java/net/blusutils/smupe/common/LanguagesList.kt @@ -1,7 +1,7 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common val languages = mapOf( - "" to "default", + "" to "OS default", "en" to "English", "ru" to "Русский" ) \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SearchUnavailable.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/error/SearchUnavailable.kt similarity index 59% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SearchUnavailable.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/error/SearchUnavailable.kt index 8497ae5..c98ba68 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SearchUnavailable.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/error/SearchUnavailable.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.data.network.error import java.io.IOException diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/CatApiService.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/CatApiService.kt new file mode 100644 index 0000000..29f446a --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/CatApiService.kt @@ -0,0 +1,143 @@ +package net.blusutils.smupe.common.api_definitions.data.network.service + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonClass +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SearchInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BuiltinSource +import net.blusutils.smupe.common.utils.OkHttpUtils +import okhttp3.Response +import java.io.IOException +import java.lang.reflect.Type + +object CatApi : BaseInternetImageSource( + "Cats As A Service", + null, null, + apiLink = "https://api.thecatapi.com/v1/images/search", + sourcePath = "", + dataPathSource = null, + search = SearchInfo( + true, + "https://api.thecatapi.com/v1/images/search", + "", + "" + ) // TODO! +), BuiltinSource { + + // IDK why it didn't work directly with generics + private val listOfCatsType: Type = + Types.newParameterizedType( + MutableList::class.java, + net.blusutils.smupe.common.api_definitions.data.network.service.CatImageInfo::class.java + ) + private val catAdapter: JsonAdapter> = + Moshi.Builder() + .addLast(KotlinJsonAdapterFactory()) + .build() + .adapter(net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.listOfCatsType) + + override suspend fun requestAsync(): ImageResponse? { + var err: IOException? = null + val resp = + try { + OkHttpUtils.getAsync(apiLink) + } catch (e: IOException) { + err = e + null + } + return resp?.let { + if (it.isSuccessful) + (net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.serializeResponse(it)).apply { occurredException = err } + else + ImageResponse( + "", + source = "cataas", + url = null, + occurredException = err + ) + } + } + + override suspend fun requestRawAsync(): String? = + net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.requestAsync()?.url + + + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { + net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.requestWithCallback { + callback(it?.url) + } + } + + override fun requestWithCallback(callback: (response: ImageResponse?) -> Unit) { + OkHttpUtils.get(apiLink) { resp, err -> + var catResp: ImageResponse? = null + if (err == null && resp != null && resp.isSuccessful) + catResp = net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.serializeResponse(resp) + callback( + catResp?.apply { occurredException = err } + ?: ImageResponse( + "", + source = "cataas", + url = null, + occurredException = err + ) + ) + } + } + + override fun serializeResponse(response: Response): ImageResponse = + net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.serializeResponse( + response.body!!.source().readUtf8() + ) + + override fun serializeResponse(input: String): ImageResponse { + return net.blusutils.smupe.common.api_definitions.data.network.service.CatApi.catAdapter.fromJson(input)?.getOrNull(0) as ImageResponse + } + + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) = + callback(null) + + override suspend fun searchAsync(query: String): ImageResponse = + ImageResponse( + "", + source = "cataas", + url = null, + occurredException = SearchUnavailable() + ) + + override suspend fun searchRawAsync(query: String): String? = null + + override fun serializeSearchResponse(response: Response): ImageResponse? = null + + override fun serializeSearchResponse(input: String): ImageResponse? = null + + override fun searchWithCallback(query: String, callback: (response: ImageResponse?) -> Unit) = + callback( + ImageResponse( + "", + source = "cataas", + url = null, + occurredException = SearchUnavailable() + ) + ) +} + +@JsonClass(generateAdapter = true) +data class CatImageInfo( + override val source: String = "cataas", + override val id: String, + override val url: String, + val width: Int, + val height: Int, + @Transient + override var occurredException: Exception? = null +) : ImageResponse( + source = source, + id = id, + url = url +) diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/DirectLinkRepository.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/DirectLinkImageService.kt similarity index 63% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/repository/DirectLinkRepository.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/DirectLinkImageService.kt index a921b3a..9cb0a05 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/DirectLinkRepository.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/DirectLinkImageService.kt @@ -1,20 +1,18 @@ -package net.blusutils.smupe.data.image_sources.repository +package net.blusutils.smupe.common.api_definitions.data.network.service -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import net.blusutils.smupe.data.image_sources.models.sources.Authorization -import net.blusutils.smupe.data.image_sources.models.sources.InternetImageSource -import net.blusutils.smupe.data.image_sources.models.sources.SearchUnavailable -import net.blusutils.smupe.data.image_sources.models.sources.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization import okhttp3.Response -class DirectLinkRepository( +class DirectLinkImageService( override var name: String, override var icon: String?, override var description: String?, override var apiLink: String, override var authorization: Authorization?, -) : InternetImageSource( +) : BaseInternetImageSource( name, apiLink = apiLink, dataPathSource = null, @@ -26,7 +24,7 @@ class DirectLinkRepository( TODO() } override fun serializeSearchResponse(input: String): ImageResponse? { - throw SearchUnavailable() + throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() } @@ -34,7 +32,7 @@ class DirectLinkRepository( TODO("Not yet implemented") } - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -44,8 +42,8 @@ class DirectLinkRepository( occurredException = null ) - override suspend fun requestRawAsync(): Uri? = - requestAsync()?.url?.run { Uri.parse(this) } + override suspend fun requestRawAsync(): String? = + requestAsync()?.url override fun serializeResponse(response: Response): ImageResponse? = serializeResponse(response.body!!.source().readUtf8()) @@ -54,7 +52,7 @@ class DirectLinkRepository( TODO("Not yet implemented") } - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) { + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -62,7 +60,7 @@ class DirectLinkRepository( TODO("Not yet implemented") } - override suspend fun searchRawAsync(query: String): Uri? { + override suspend fun searchRawAsync(query: String): String? { TODO("Not yet implemented") } diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/JsonRepository.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/JsonImageService.kt similarity index 67% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/repository/JsonRepository.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/JsonImageService.kt index 8ba47d4..09287aa 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/JsonRepository.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/JsonImageService.kt @@ -1,14 +1,18 @@ -package net.blusutils.smupe.data.image_sources.repository +package net.blusutils.smupe.common.api_definitions.data.network.service -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import net.blusutils.smupe.data.image_sources.models.sources.* -import net.blusutils.smupe.util.OkHttpUtils -import net.blusutils.smupe.util.getJsonValueFromPath +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.BlurHashInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SearchInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.TagsInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization +import net.blusutils.smupe.common.utils.OkHttpUtils +import net.blusutils.smupe.common.utils.getJsonValueFromPath import okhttp3.Response import java.io.IOException -class JsonRepository( +class JsonImageService( override var name: String, override var icon: String?, override var description: String?, @@ -21,7 +25,7 @@ class JsonRepository( override var dataPathSource: String?, var sourceIdPath: String?, var pathDelimiter: String? -) : InternetImageSource( +) : BaseInternetImageSource( name, apiLink = apiLink, dataPathSource = dataPathSource, @@ -51,7 +55,7 @@ class JsonRepository( ) } } - } ?: if (search == null || !search!!.supported) null else throw SearchUnavailable() + } ?: if (search == null || !search!!.supported) null else throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() } @@ -59,7 +63,7 @@ class JsonRepository( TODO("Not yet implemented") } - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -76,12 +80,17 @@ class JsonRepository( if (it.isSuccessful) (serializeResponse(it))?.apply { occurredException = err } else - ImageResponse("", source = name, url = null, occurredException = err) + ImageResponse( + "", + source = name, + url = null, + occurredException = err + ) } } - override suspend fun requestRawAsync(): Uri? = - requestAsync()?.url?.run { Uri.parse(this) } + override suspend fun requestRawAsync(): String? = + requestAsync()?.url override fun serializeResponse(response: Response): ImageResponse? = serializeResponse(response.body!!.source().readUtf8()) @@ -90,7 +99,7 @@ class JsonRepository( TODO("Not yet implemented") } - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) { + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -98,7 +107,7 @@ class JsonRepository( TODO("Not yet implemented") } - override suspend fun searchRawAsync(query: String): Uri? { + override suspend fun searchRawAsync(query: String): String? { TODO("Not yet implemented") } diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/LocalRepository.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/LocalRepository.kt similarity index 62% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/repository/LocalRepository.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/LocalRepository.kt index c76987d..3ee8c12 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/LocalRepository.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/LocalRepository.kt @@ -1,11 +1,8 @@ -package net.blusutils.smupe.data.image_sources.repository +package net.blusutils.smupe.common.api_definitions.data.network.service -import android.net.Uri -import android.util.Log -import androidx.core.net.toFile -import androidx.core.net.toUri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import net.blusutils.smupe.data.image_sources.models.sources.LocalImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.LocalImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseLocalImageSource import okhttp3.Response import java.io.File import java.io.FileNotFoundException @@ -15,7 +12,7 @@ class LocalRepository( override var icon: String?, override var description: String?, override var apiLink: String -) : LocalImageSource( +) : BaseLocalImageSource( name, apiLink = apiLink, ) { @@ -32,26 +29,29 @@ class LocalRepository( TODO("Not yet implemented") } - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { TODO("Not yet implemented") } override suspend fun requestAsync(): ImageResponse? { - var files = apiLink.toUri().toFile().listFiles()?.filter { it.isFile && !it.name.startsWith(".") } - Log.d("srcsss", "$apiLink, $files") + var files = File(apiLink).listFiles()?.filter { it.isFile && !it.name.startsWith(".") } if (files!=null && files.isEmpty()) { files = null } // Iterate through the files in the directory and return random one return files?.random()?.let { - GalleryImageInfo( + LocalImageResponse( id = it.name, url = it.absolutePath ) - } ?: ImageResponse("", source = name, url = null, occurredException = FileNotFoundException("No files found in gallery")) - + } ?: ImageResponse( + "", + source = name, + url = null, + occurredException = FileNotFoundException("No files found in directory: $apiLink") + ) } - override suspend fun requestRawAsync(): Uri? = - requestAsync()?.url?.run { Uri.parse(this) } + override suspend fun requestRawAsync(): String? = + requestAsync()?.url override fun serializeResponse(response: Response): ImageResponse? { TODO("Not yet implemented") @@ -61,7 +61,7 @@ class LocalRepository( TODO("Not yet implemented") } - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) { + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -69,7 +69,7 @@ class LocalRepository( TODO("Not yet implemented") } - override suspend fun searchRawAsync(query: String): Uri? { + override suspend fun searchRawAsync(query: String): String? { TODO("Not yet implemented") } diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/PlainTextRepository.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/PlainTextImageService.kt similarity index 64% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/repository/PlainTextRepository.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/PlainTextImageService.kt index 2126c6b..49ce0fb 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/repository/PlainTextRepository.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/data/network/service/PlainTextImageService.kt @@ -1,22 +1,20 @@ -package net.blusutils.smupe.data.image_sources.repository +package net.blusutils.smupe.common.api_definitions.data.network.service -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse -import net.blusutils.smupe.data.image_sources.models.sources.Authorization -import net.blusutils.smupe.data.image_sources.models.sources.InternetImageSource -import net.blusutils.smupe.data.image_sources.models.sources.SearchUnavailable -import net.blusutils.smupe.data.image_sources.models.sources.SourceMode -import net.blusutils.smupe.util.OkHttpUtils +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseInternetImageSource +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization +import net.blusutils.smupe.common.utils.OkHttpUtils import okhttp3.Response import java.io.IOException -class PlainTextRepository( +class PlainTextImageService( override var name: String, override var icon: String?, override var description: String?, override var apiLink: String, override var authorization: Authorization?, -) : InternetImageSource( +) : BaseInternetImageSource( name, apiLink = apiLink, dataPathSource = null, @@ -28,7 +26,7 @@ class PlainTextRepository( TODO() } override fun serializeSearchResponse(input: String): ImageResponse? { - throw SearchUnavailable() + throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() } @@ -36,7 +34,7 @@ class PlainTextRepository( TODO("Not yet implemented") } - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -58,12 +56,17 @@ class PlainTextRepository( ) } else - ImageResponse("", source = name, url = null, occurredException = err) + ImageResponse( + "", + source = name, + url = null, + occurredException = err + ) } } - override suspend fun requestRawAsync(): Uri? = - requestAsync()?.url?.run { Uri.parse(this) } + override suspend fun requestRawAsync(): String? = + requestAsync()?.url override fun serializeResponse(response: Response): ImageResponse? = serializeResponse(response.body!!.source().readUtf8()) @@ -72,7 +75,7 @@ class PlainTextRepository( TODO("Not yet implemented") } - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) { + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -80,7 +83,7 @@ class PlainTextRepository( TODO("Not yet implemented") } - override suspend fun searchRawAsync(query: String): Uri? { + override suspend fun searchRawAsync(query: String): String? { TODO("Not yet implemented") } diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/BaseImageContent.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/BaseImageContent.kt new file mode 100644 index 0000000..ca85fe6 --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/BaseImageContent.kt @@ -0,0 +1,6 @@ +package net.blusutils.smupe.common.api_definitions.domain.model.image.content + +public open class BaseImageContent( + open val url: String?, + open val occurredException: Exception? +) \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/contents/ImageResponse.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/ImageResponse.kt similarity index 81% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/contents/ImageResponse.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/ImageResponse.kt index e22f2fe..6d33dc9 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/contents/ImageResponse.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/ImageResponse.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.contents +package net.blusutils.smupe.common.api_definitions.domain.model.image.content open class ImageResponse( open val id: String, diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/LocalImageResponse.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/LocalImageResponse.kt new file mode 100644 index 0000000..f9f6cc5 --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/content/LocalImageResponse.kt @@ -0,0 +1,11 @@ +package net.blusutils.smupe.common.api_definitions.domain.model.image.content + +data class LocalImageResponse( + override val source: String = "local", + override val id: String, + override val url: String +) : ImageResponse( + source, + id, + url +) diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BlurHashInfo.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/BlurHashInfo.kt similarity index 56% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BlurHashInfo.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/BlurHashInfo.kt index a257ac5..eb6bffe 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BlurHashInfo.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/BlurHashInfo.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.metadata class BlurHashInfo( supported: Boolean, diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/Extra.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/Extra.kt new file mode 100644 index 0000000..3e568cd --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/Extra.kt @@ -0,0 +1,4 @@ +package net.blusutils.smupe.common.api_definitions.domain.model.image.metadata + +class Extra { +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SearchInfo.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SearchInfo.kt similarity index 65% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SearchInfo.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SearchInfo.kt index 162f4ba..34d41fe 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SearchInfo.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SearchInfo.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.metadata class SearchInfo( supported: Boolean, diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SourceMode.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SourceMode.kt similarity index 59% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SourceMode.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SourceMode.kt index 8436ca0..c84f2e6 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SourceMode.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SourceMode.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.metadata enum class SourceMode { Local, diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SupportingApiFeature.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SupportingApiFeature.kt similarity index 54% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SupportingApiFeature.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SupportingApiFeature.kt index 5c4a789..4814fc6 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/SupportingApiFeature.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/SupportingApiFeature.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.metadata open class SupportingApiFeature( open val supported: Boolean, diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/TagsInfo.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/TagsInfo.kt similarity index 55% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/TagsInfo.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/TagsInfo.kt index 2d4e75f..756034d 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/TagsInfo.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/metadata/TagsInfo.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.metadata class TagsInfo( supported: Boolean, diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BaseImageSource.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseImageSource.kt similarity index 67% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BaseImageSource.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseImageSource.kt index 6281097..2f88d47 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/BaseImageSource.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseImageSource.kt @@ -1,7 +1,8 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.source -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.* +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization import okhttp3.Response abstract class BaseImageSource( @@ -20,11 +21,11 @@ abstract class BaseImageSource( ) { abstract fun requestWithCallback(callback: (response: ImageResponse?) -> Unit) - abstract fun requestRawWithCallback(callback: (response: Uri?) -> Unit) + abstract fun requestRawWithCallback(callback: (response: String?) -> Unit) abstract suspend fun requestAsync(): ImageResponse? - abstract suspend fun requestRawAsync(): Uri? + abstract suspend fun requestRawAsync(): String? abstract fun serializeResponse(response: Response): ImageResponse? @@ -32,11 +33,11 @@ abstract class BaseImageSource( abstract fun searchWithCallback(query: String, callback: (response: ImageResponse?) -> Unit) - abstract fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) + abstract fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) abstract suspend fun searchAsync(query: String): ImageResponse? - abstract suspend fun searchRawAsync(query: String): Uri? + abstract suspend fun searchRawAsync(query: String): String? abstract fun serializeSearchResponse(response: Response): ImageResponse? diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/InternetImageSource.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseInternetImageSource.kt similarity index 59% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/InternetImageSource.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseInternetImageSource.kt index 79b95e6..c667805 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/InternetImageSource.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseInternetImageSource.kt @@ -1,10 +1,14 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.source -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.BlurHashInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SearchInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.TagsInfo +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization import okhttp3.Response -open class InternetImageSource( +open class BaseInternetImageSource( override var name: String, override var icon: String? = null, override var description: String? = null, @@ -13,9 +17,20 @@ open class InternetImageSource( override var dataPathSource: String?, override var apiLink: String, override var authorization: Authorization? = null, - override var blurHash: BlurHashInfo? = BlurHashInfo(false, ""), - override var search: SearchInfo? = SearchInfo(false, "", "", ""), - override var tags: TagsInfo? = TagsInfo(false, ""), + override var blurHash: BlurHashInfo? = BlurHashInfo( + false, + "" + ), + override var search: SearchInfo? = SearchInfo( + false, + "", + "", + "" + ), + override var tags: TagsInfo? = TagsInfo( + false, + "" + ), ): BaseImageSource( name, icon, @@ -33,7 +48,7 @@ open class InternetImageSource( TODO("Not yet implemented") } - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -41,7 +56,7 @@ open class InternetImageSource( TODO("Not yet implemented") } - override suspend fun requestRawAsync(): Uri? { + override suspend fun requestRawAsync(): String? { TODO("Not yet implemented") } @@ -57,7 +72,7 @@ open class InternetImageSource( TODO("Not yet implemented") } - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) { + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -65,7 +80,7 @@ open class InternetImageSource( TODO("Not yet implemented") } - override suspend fun searchRawAsync(query: String): Uri? { + override suspend fun searchRawAsync(query: String): String? { TODO("Not yet implemented") } diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/LocalImageSource.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseLocalImageSource.kt similarity index 66% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/LocalImageSource.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseLocalImageSource.kt index 1a429f7..010036e 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/LocalImageSource.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BaseLocalImageSource.kt @@ -1,10 +1,13 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.image.source -import android.net.Uri -import net.blusutils.smupe.data.image_sources.models.contents.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.BlurHashInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SearchInfo +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.SourceMode +import net.blusutils.smupe.common.api_definitions.domain.model.image.metadata.TagsInfo import okhttp3.Response -open class LocalImageSource( +open class BaseLocalImageSource( override var name: String, override var icon: String? = null, override var description: String? = null, @@ -26,7 +29,7 @@ open class LocalImageSource( TODO("Not yet implemented") } - override fun requestRawWithCallback(callback: (response: Uri?) -> Unit) { + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -34,7 +37,7 @@ open class LocalImageSource( TODO("Not yet implemented") } - override suspend fun requestRawAsync(): Uri? { + override suspend fun requestRawAsync(): String? { TODO("Not yet implemented") } @@ -50,7 +53,7 @@ open class LocalImageSource( TODO("Not yet implemented") } - override fun searchRawWithCallback(query: String, callback: (response: Uri?) -> Unit) { + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) { TODO("Not yet implemented") } @@ -58,7 +61,7 @@ open class LocalImageSource( TODO("Not yet implemented") } - override suspend fun searchRawAsync(query: String): Uri? { + override suspend fun searchRawAsync(query: String): String? { TODO("Not yet implemented") } diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BuiltinSource.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BuiltinSource.kt new file mode 100644 index 0000000..1a6995f --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/BuiltinSource.kt @@ -0,0 +1,3 @@ +package net.blusutils.smupe.common.api_definitions.domain.model.image.source + +interface BuiltinSource \ No newline at end of file diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/SampleLocalSource.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/SampleLocalSource.kt new file mode 100644 index 0000000..fdab4d7 --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/image/source/SampleLocalSource.kt @@ -0,0 +1,66 @@ +package net.blusutils.smupe.common.api_definitions.domain.model.image.source +import net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable +import net.blusutils.smupe.common.api_definitions.domain.model.image.content.ImageResponse +import net.blusutils.smupe.common.api_definitions.domain.model.request.Authorization +import okhttp3.Response + +abstract class SampleLocalSource( + override var name: String = "Local", + override var icon: String? = null, + override var description: String? = null, + override var apiLink: String = "/" +) : BaseLocalImageSource( + name, + icon, + description, + apiLink = apiLink +) { + override var authorization: Authorization? + get() = null + set(_) {} + + override suspend fun requestRawAsync(): String? = + requestAsync()?.url + + + override fun requestRawWithCallback(callback: (response: String?) -> Unit) { + requestWithCallback { + callback(it?.url) + } + } + + override fun serializeResponse(response: Response): ImageResponse = + throw UnsupportedOperationException("Local sources not need to be serialized") + + override fun serializeResponse(input: String): ImageResponse { + throw UnsupportedOperationException("Local sources not need to be serialized") + } + + + override fun searchRawWithCallback(query: String, callback: (response: String?) -> Unit) = + throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() + + override suspend fun searchAsync(query: String): ImageResponse = + ImageResponse( + "", + source = name, + url = null, + occurredException = SearchUnavailable() + ) + + override suspend fun searchRawAsync(query: String): String? = throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() + + override fun serializeSearchResponse(response: Response): ImageResponse = throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() + + override fun serializeSearchResponse(input: String): ImageResponse = throw net.blusutils.smupe.common.api_definitions.data.network.error.SearchUnavailable() + + override fun searchWithCallback(query: String, callback: (response: ImageResponse?) -> Unit) = + callback( + ImageResponse( + "", + source = name, + url = null, + occurredException = SearchUnavailable() + ) + ) +} \ No newline at end of file diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/request/AuthType.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/request/AuthType.kt new file mode 100644 index 0000000..a62220b --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/request/AuthType.kt @@ -0,0 +1,10 @@ +package net.blusutils.smupe.common.api_definitions.domain.model.request + +enum class AuthType { + None, + AuthHeader, + AuthHeaderBearer, + AuthHeaderToken, + AuthHeaderOther, + JSON +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/Authorization.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/request/Authorization.kt similarity index 51% rename from app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/Authorization.kt rename to common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/request/Authorization.kt index fb05594..16b281e 100644 --- a/app/src/main/java/net/blusutils/smupe/data/image_sources/models/sources/Authorization.kt +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/model/request/Authorization.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.data.image_sources.models.sources +package net.blusutils.smupe.common.api_definitions.domain.model.request data class Authorization( val type: AuthType, diff --git a/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/utils/ApiDefinitionFileWrapper.kt b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/utils/ApiDefinitionFileWrapper.kt new file mode 100644 index 0000000..35b3af9 --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/api_definitions/domain/utils/ApiDefinitionFileWrapper.kt @@ -0,0 +1,11 @@ +package net.blusutils.smupe.common.api_definitions.domain.utils + +import net.blusutils.smupe.common.api_definitions.domain.model.image.source.BaseImageSource +import java.io.File + +interface ApiDefinitionFileWrapper { + val apiDefinitionsDirectory: File + fun loadAllApiDefs(): Unit + fun readFile(filename: String): BaseImageSource? + fun writeFile(filename: String, apiDef: T, cls: Class) +} \ No newline at end of file diff --git a/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/ApacheLicense.kt b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/ApacheLicense.kt new file mode 100644 index 0000000..4ec3abe --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/ApacheLicense.kt @@ -0,0 +1,23 @@ +package net.blusutils.smupe.common.license_storage.domain.implementation + +import net.blusutils.smupe.common.license_storage.domain.model.LicenseText + +object ApacheLicense : LicenseText { + override val name = "Apache License 2.0" + override val content = +""" +Copyright %1${"$"}s + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" +} \ No newline at end of file diff --git a/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/MitLicense.kt b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/MitLicense.kt new file mode 100644 index 0000000..8267232 --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/MitLicense.kt @@ -0,0 +1,30 @@ +package net.blusutils.smupe.common.license_storage.domain.implementation + +import net.blusutils.smupe.common.license_storage.domain.model.LicenseText + +object MitLicense : LicenseText { + override val name = "MIT License" + override val content = +""" +MIT License +Copyright © %1${"$"}s + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +""" +} \ No newline at end of file diff --git a/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/ProtobufLicense.kt b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/ProtobufLicense.kt new file mode 100644 index 0000000..472bcef --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/implementation/ProtobufLicense.kt @@ -0,0 +1,42 @@ +package net.blusutils.smupe.common.license_storage.domain.implementation + +import net.blusutils.smupe.common.license_storage.domain.model.LicenseText + +object ProtobufLicense : LicenseText { + override val name = "Protocol Buffers license" + override val content = +""" +Copyright %1${"$"}s All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. +* Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. +""" +} \ No newline at end of file diff --git a/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/model/License.kt b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/model/License.kt new file mode 100644 index 0000000..e1f677f --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/model/License.kt @@ -0,0 +1,9 @@ +package net.blusutils.smupe.common.license_storage.domain.model + +open class License( + val title: String, + val copyright: String, + val link: String, + val text: String +) + diff --git a/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/model/LicenseText.kt b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/model/LicenseText.kt new file mode 100644 index 0000000..5106acc --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/model/LicenseText.kt @@ -0,0 +1,6 @@ +package net.blusutils.smupe.common.license_storage.domain.model + +interface LicenseText { + val name: String + val content: String +} diff --git a/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/repository/LicenseRepository.kt b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/repository/LicenseRepository.kt new file mode 100644 index 0000000..2cc430a --- /dev/null +++ b/common/src/main/java/net/blusutils/smupe/common/license_storage/domain/repository/LicenseRepository.kt @@ -0,0 +1,7 @@ +package net.blusutils.smupe.common.license_storage.domain.repository + +import net.blusutils.smupe.common.license_storage.domain.model.License + +interface LicenseRepository { + val licenses: List +} \ No newline at end of file diff --git a/app/src/main/java/net/blusutils/smupe/util/startsWith.kt b/common/src/main/java/net/blusutils/smupe/common/utils/ArrayStartsWith.kt similarity index 89% rename from app/src/main/java/net/blusutils/smupe/util/startsWith.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/ArrayStartsWith.kt index 8030322..b0c4504 100644 --- a/app/src/main/java/net/blusutils/smupe/util/startsWith.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/ArrayStartsWith.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils /** * Checks whether the byte array starts with the specified bytes. diff --git a/app/src/main/java/net/blusutils/smupe/util/formatByKeyword.kt b/common/src/main/java/net/blusutils/smupe/common/utils/BraceKeywordFormatter.kt similarity index 94% rename from app/src/main/java/net/blusutils/smupe/util/formatByKeyword.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/BraceKeywordFormatter.kt index c022057..e9e4e6b 100644 --- a/app/src/main/java/net/blusutils/smupe/util/formatByKeyword.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/BraceKeywordFormatter.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils /** * Simply format a string with given keywords map. diff --git a/app/src/main/java/net/blusutils/smupe/util/FileTypeAnalyzer.kt b/common/src/main/java/net/blusutils/smupe/common/utils/FileTypeAnalyzer.kt similarity index 70% rename from app/src/main/java/net/blusutils/smupe/util/FileTypeAnalyzer.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/FileTypeAnalyzer.kt index 711c1d4..c2173c1 100644 --- a/app/src/main/java/net/blusutils/smupe/util/FileTypeAnalyzer.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/FileTypeAnalyzer.kt @@ -1,10 +1,7 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils -import android.graphics.Bitmap -import android.net.Uri -import android.util.Log -import net.blusutils.smupe.util.OkHttpUtils.getRequest -import net.blusutils.smupe.util.OkHttpUtils.okHttpClient +import net.blusutils.smupe.common.utils.OkHttpUtils.getRequest +import net.blusutils.smupe.common.utils.OkHttpUtils.okHttpClient import okio.IOException import ru.gildor.coroutines.okhttp.await import java.io.File @@ -17,18 +14,15 @@ object FileTypeAnalyzer { /** * Determines the file type of the given file. - * @param input The [Uri]/[String] with path or URI or file as [ByteArray]/[Bitmap] to determine the file type of. + * @param input The [String] with path or file as [ByteArray]/[Bitmap] to determine the file type of. * @return The file type extension. * @throws IllegalArgumentException if the file type could not be determined. * @throws IOException if the file could not be read. */ suspend fun getExtension(input: Any): String { - Log.d("FileTypeAnalyzer.getExtension", "$input") return when (input) { is String -> getExtensionFromUrlOrPath(input.toString()) - is Uri -> getExtensionFromUrlOrPath(input.toString()) is ByteArray -> getExtensionFromBytes(input) - is Bitmap -> getExtensionFromBitmap(input) else -> throw IllegalArgumentException("Unsupported input type: $input") } } @@ -62,13 +56,4 @@ object FileTypeAnalyzer { val magicBytes = bytes.slice(0..1024).toByteArray() return MagicNumberIdentifier.identify(magicBytes.toUByteArray()) } - - private fun getExtensionFromBitmap(bitmap: Bitmap): String { - // Extract format from Bitmap's config - return when (bitmap.config) { - Bitmap.Config.ARGB_8888 -> "png" - Bitmap.Config.RGB_565 -> "jpg" - else -> throw IllegalArgumentException("Unsupported bitmap config: ${bitmap.config}") - } - } } diff --git a/app/src/main/java/net/blusutils/smupe/util/getJsonValueFromPath.kt b/common/src/main/java/net/blusutils/smupe/common/utils/JsonPathProcessor.kt similarity index 90% rename from app/src/main/java/net/blusutils/smupe/util/getJsonValueFromPath.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/JsonPathProcessor.kt index 1d55788..672e696 100644 --- a/app/src/main/java/net/blusutils/smupe/util/getJsonValueFromPath.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/JsonPathProcessor.kt @@ -1,6 +1,5 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils -import android.util.Log import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi @@ -25,7 +24,6 @@ fun getJsonValueFromPath( for (key in keys) { when (currentValue) { is List<*> -> { - Log.d("getJsonValueFromPath", "$currentValue, $keys") currentValue = when (key) { "~" -> currentValue.random() else -> currentValue.getOrNull(key.toInt()) diff --git a/app/src/main/java/net/blusutils/smupe/util/reorderList.kt b/common/src/main/java/net/blusutils/smupe/common/utils/ListReorder.kt similarity index 97% rename from app/src/main/java/net/blusutils/smupe/util/reorderList.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/ListReorder.kt index 742e8dc..84f58f0 100644 --- a/app/src/main/java/net/blusutils/smupe/util/reorderList.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/ListReorder.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils /** * Tries to reorder a list based on a given order string. diff --git a/app/src/main/java/net/blusutils/smupe/util/MagicNumberIdentifier.kt b/common/src/main/java/net/blusutils/smupe/common/utils/MagicNumberIdentifier.kt similarity index 96% rename from app/src/main/java/net/blusutils/smupe/util/MagicNumberIdentifier.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/MagicNumberIdentifier.kt index b79caf0..2e4a741 100644 --- a/app/src/main/java/net/blusutils/smupe/util/MagicNumberIdentifier.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/MagicNumberIdentifier.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils /** * Helper object for identifying file types by their magic numbers. diff --git a/app/src/main/java/net/blusutils/smupe/util/isNetworkConnected.kt b/common/src/main/java/net/blusutils/smupe/common/utils/NetworkConnectionCheck.kt similarity index 89% rename from app/src/main/java/net/blusutils/smupe/util/isNetworkConnected.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/NetworkConnectionCheck.kt index f4b299c..e728664 100644 --- a/app/src/main/java/net/blusutils/smupe/util/isNetworkConnected.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/NetworkConnectionCheck.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils import java.net.InetAddress diff --git a/app/src/main/java/net/blusutils/smupe/util/OkHttpUtils.kt b/common/src/main/java/net/blusutils/smupe/common/utils/OkHttpUtils.kt similarity index 97% rename from app/src/main/java/net/blusutils/smupe/util/OkHttpUtils.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/OkHttpUtils.kt index 3e7088d..df220b9 100644 --- a/app/src/main/java/net/blusutils/smupe/util/OkHttpUtils.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/OkHttpUtils.kt @@ -1,4 +1,4 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils import okhttp3.* import okhttp3.RequestBody.Companion.toRequestBody diff --git a/app/src/main/java/net/blusutils/smupe/util/calculateRoomResourceId.kt b/common/src/main/java/net/blusutils/smupe/common/utils/ResourceIdCalculator.kt similarity index 90% rename from app/src/main/java/net/blusutils/smupe/util/calculateRoomResourceId.kt rename to common/src/main/java/net/blusutils/smupe/common/utils/ResourceIdCalculator.kt index 5b3d11a..a081ccf 100644 --- a/app/src/main/java/net/blusutils/smupe/util/calculateRoomResourceId.kt +++ b/common/src/main/java/net/blusutils/smupe/common/utils/ResourceIdCalculator.kt @@ -1,10 +1,10 @@ -package net.blusutils.smupe.util +package net.blusutils.smupe.common.utils import java.security.MessageDigest const val API_DEF_PREFIX = "API-DEF_" -fun calculateRoomResourceId(inputData: String): String { +fun calculateResourceId(inputData: String): String { // Extract the normal ID from the input data val normalId = when { inputData.startsWith("https://") diff --git a/common/src/test/java/net/blusutils/smupe/common/ExampleUnitTest.kt b/common/src/test/java/net/blusutils/smupe/common/ExampleUnitTest.kt new file mode 100644 index 0000000..f953101 --- /dev/null +++ b/common/src/test/java/net/blusutils/smupe/common/ExampleUnitTest.kt @@ -0,0 +1,16 @@ +package net.blusutils.smupe.common + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/composeblurhash/.gitignore b/composeblurhash/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/composeblurhash/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/src/main/java/com/devtamuno/composeblurhash/LICENSE.txt b/composeblurhash/LICENSE.txt similarity index 100% rename from app/src/main/java/com/devtamuno/composeblurhash/LICENSE.txt rename to composeblurhash/LICENSE.txt diff --git a/composeblurhash/build.gradle.kts b/composeblurhash/build.gradle.kts new file mode 100644 index 0000000..4675f60 --- /dev/null +++ b/composeblurhash/build.gradle.kts @@ -0,0 +1,47 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.devtamuno.composeblurhash" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.3" + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } +} + +dependencies { + implementation("androidx.core:core-ktx:1.13.0") + implementation(platform("androidx.compose:compose-bom:2024.02.00")) + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("androidx.core:core-ktx:1.13.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") + implementation("androidx.activity:activity-compose:1.9.0") + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") +} \ No newline at end of file diff --git a/composeblurhash/consumer-rules.pro b/composeblurhash/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/composeblurhash/proguard-rules.pro b/composeblurhash/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/composeblurhash/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/composeblurhash/src/main/AndroidManifest.xml b/composeblurhash/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ee047ef --- /dev/null +++ b/composeblurhash/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/devtamuno/composeblurhash/Annotations.kt b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/Annotations.kt similarity index 100% rename from app/src/main/java/com/devtamuno/composeblurhash/Annotations.kt rename to composeblurhash/src/main/java/com/devtamuno/composeblurhash/Annotations.kt diff --git a/app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHasDecoderRequest.kt b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHasDecoderRequest.kt similarity index 100% rename from app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHasDecoderRequest.kt rename to composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHasDecoderRequest.kt diff --git a/app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashDecoder.kt b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashDecoder.kt similarity index 100% rename from app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashDecoder.kt rename to composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashDecoder.kt diff --git a/app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashPainter.kt b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashPainter.kt similarity index 85% rename from app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashPainter.kt rename to composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashPainter.kt index 9a8cabd..432dee2 100644 --- a/app/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashPainter.kt +++ b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/BlurHashPainter.kt @@ -1,25 +1,16 @@ package com.devtamuno.composeblurhash.decoder -import androidx.compose.runtime.RememberObserver -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow +import androidx.compose.runtime.* import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import com.devtamuno.composeblurhash.ExperimentalComposeBlurHash -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel +import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.mapLatest -import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) @ExperimentalComposeBlurHash diff --git a/app/src/main/java/com/devtamuno/composeblurhash/decoder/ImageBitmapBrush.kt b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/ImageBitmapBrush.kt similarity index 68% rename from app/src/main/java/com/devtamuno/composeblurhash/decoder/ImageBitmapBrush.kt rename to composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/ImageBitmapBrush.kt index 708d92a..b02c464 100644 --- a/app/src/main/java/com/devtamuno/composeblurhash/decoder/ImageBitmapBrush.kt +++ b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/decoder/ImageBitmapBrush.kt @@ -1,11 +1,7 @@ package com.devtamuno.composeblurhash.decoder import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.ImageShader -import androidx.compose.ui.graphics.Shader -import androidx.compose.ui.graphics.ShaderBrush -import androidx.compose.ui.graphics.TileMode +import androidx.compose.ui.graphics.* internal class ImageBitmapBrush(private val imageBitmap: ImageBitmap) : ShaderBrush() { override val intrinsicSize: Size diff --git a/app/src/main/java/com/devtamuno/composeblurhash/ext/ComposeExt.kt b/composeblurhash/src/main/java/com/devtamuno/composeblurhash/ext/ComposeExt.kt similarity index 100% rename from app/src/main/java/com/devtamuno/composeblurhash/ext/ComposeExt.kt rename to composeblurhash/src/main/java/com/devtamuno/composeblurhash/ext/ComposeExt.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 4093497..021b420 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,4 +14,6 @@ dependencyResolutionManagement { } rootProject.name = "Smupe!" +include(":common") include(":app") +include(":composeblurhash")