This is a test if updates work
This commit is contained in:
Felitendo
2025-05-20 15:23:42 +02:00
parent e65e82c85b
commit ddff25a7c4
465 changed files with 37626 additions and 0 deletions

1
core/domain/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,8 @@
plugins {
alias(libs.plugins.looker.jvm.library)
alias(libs.plugins.looker.lint)
}
dependencies {
implementation(libs.kotlinx.coroutines.core)
}

View File

@@ -0,0 +1,24 @@
package com.looker.core.domain
import com.looker.core.domain.model.App
import com.looker.core.domain.model.Author
import com.looker.core.domain.model.Package
import com.looker.core.domain.model.PackageName
import kotlinx.coroutines.flow.Flow
interface AppRepository {
fun getApps(): Flow<List<App>>
fun getApp(packageName: PackageName): Flow<List<App>>
fun getAppFromAuthor(author: Author): Flow<List<App>>
fun getPackages(packageName: PackageName): Flow<List<Package>>
/**
* returns true is the app is added successfully
* returns false if the app was already in the favourites and so it is removed
*/
suspend fun addToFavourite(packageName: PackageName): Boolean
}

View File

@@ -0,0 +1,19 @@
package com.looker.core.domain
import com.looker.core.domain.model.Repo
import kotlinx.coroutines.flow.Flow
interface RepoRepository {
suspend fun getRepo(id: Long): Repo
fun getRepos(): Flow<List<Repo>>
suspend fun updateRepo(repo: Repo)
suspend fun enableRepository(repo: Repo, enable: Boolean)
suspend fun sync(repo: Repo): Boolean
suspend fun syncAll(): Boolean
}

View File

@@ -0,0 +1,74 @@
package com.looker.core.domain.model
data class App(
val repoId: Long,
val categories: List<String>,
val links: Links,
val metadata: Metadata,
val author: Author,
val screenshots: Screenshots,
val graphics: Graphics,
val donation: Donation,
val preferredSigner: String = "",
val packages: List<Package>
)
data class Author(
val name: String,
val email: String,
val web: String
)
data class Donation(
val regularUrl: String? = null,
val bitcoinAddress: String? = null,
val flattrId: String? = null,
val liteCoinAddress: String? = null,
val openCollectiveId: String? = null,
val librePayId: String? = null,
val librePayAddress: String? = null
)
data class Graphics(
val featureGraphic: String = "",
val promoGraphic: String = "",
val tvBanner: String = "",
val video: String = ""
)
data class Links(
val changelog: String = "",
val issueTracker: String = "",
val sourceCode: String = "",
val translation: String = "",
val webSite: String = ""
)
data class Metadata(
val name: String,
val packageName: PackageName,
val added: Long,
val description: String,
val icon: String,
val lastUpdated: Long,
val license: String,
val suggestedVersionCode: Long,
val suggestedVersionName: String,
val summary: String
)
data class Screenshots(
val phone: List<String> = emptyList(),
val sevenInch: List<String> = emptyList(),
val tenInch: List<String> = emptyList(),
val tv: List<String> = emptyList(),
val wear: List<String> = emptyList()
)
data class AppMinimal(
val name: String,
val summary: String,
val icon: String
)
fun App.minimal(): AppMinimal = AppMinimal(metadata.name, metadata.summary, metadata.icon)

View File

@@ -0,0 +1,7 @@
package com.looker.core.domain.model
interface DataFile {
val name: String
val hash: String
val size: Long
}

View File

@@ -0,0 +1,46 @@
package com.looker.core.domain.model
import com.looker.core.domain.model.Fingerprint.Companion.hex
import java.security.MessageDigest
import java.security.cert.Certificate
import java.util.Locale
@JvmInline
value class Fingerprint(val value: String) {
init {
require(value.isNotBlank() && value.length == DEFAULT_LENGTH) { "Invalid Fingerprint: $value" }
}
inline fun check(other: Fingerprint): Boolean {
return other.value.equals(value, ignoreCase = true)
}
override fun toString(): String {
return value.windowed(2, 2, false)
.take(DEFAULT_LENGTH / 2).joinToString(separator = " ") { it.uppercase(Locale.US) }
}
internal companion object {
const val DEFAULT_LENGTH = 64
fun ByteArray.hex(): String = joinToString(separator = "") { byte ->
"%02x".format(Locale.US, byte.toInt() and 0xff)
}
}
}
fun Certificate.fingerprint(): Fingerprint {
val bytes = encoded
return if (bytes.size >= 256) {
try {
val fingerprint = MessageDigest.getInstance("sha256").digest(bytes)
Fingerprint(fingerprint.hex().uppercase())
} catch (e: Exception) {
e.printStackTrace()
Fingerprint("")
}
} else {
Fingerprint("")
}
}

View File

@@ -0,0 +1,41 @@
package com.looker.core.domain.model
data class Package(
val installed: Boolean,
val added: Long,
val apk: ApkFile,
val platforms: Platforms,
val features: List<String>,
val antiFeatures: List<String>,
val manifest: Manifest,
val whatsNew: String
)
data class ApkFile(
override val name: String,
override val hash: String,
override val size: Long
) : DataFile
data class Manifest(
val versionCode: Long,
val versionName: String,
val usesSDKs: SDKs,
val signer: Set<String>,
val permissions: List<Permission>
)
@JvmInline
value class Platforms(val value: List<String>)
data class SDKs(
val min: Int = -1,
val max: Int = -1,
val target: Int = -1
)
// means the max sdk here and any sdk value as -1 means not valid
data class Permission(
val name: String,
val sdKs: SDKs
)

View File

@@ -0,0 +1,6 @@
package com.looker.core.domain.model
@JvmInline
value class PackageName(val name: String)
fun String.toPackageName() = PackageName(this)

View File

@@ -0,0 +1,50 @@
package com.looker.core.domain.model
data class Repo(
val id: Long,
val enabled: Boolean,
val address: String,
val name: String,
val description: String,
val fingerprint: Fingerprint?,
val authentication: Authentication,
val versionInfo: VersionInfo,
val mirrors: List<String>,
val antiFeatures: List<AntiFeature>,
val categories: List<Category>
) {
val shouldAuthenticate =
authentication.username.isNotEmpty() && authentication.password.isNotEmpty()
fun update(fingerprint: Fingerprint, timestamp: Long? = null, etag: String? = null): Repo {
return copy(
fingerprint = fingerprint,
versionInfo = timestamp?.let { VersionInfo(timestamp = it, etag = etag) } ?: versionInfo
)
}
}
val String.isOnion: Boolean
get() = endsWith(".onion")
data class AntiFeature(
val name: String,
val icon: String = "",
val description: String = ""
)
data class Category(
val name: String,
val icon: String = "",
val description: String = ""
)
data class Authentication(
val username: String,
val password: String
)
data class VersionInfo(
val timestamp: Long,
val etag: String?
)