Reorganize and group modules

This commit is contained in:
MM20
2022-12-13 17:37:26 +01:00
parent bac24baad2
commit 3f8880a90a
995 changed files with 501 additions and 298 deletions
@@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
/
</manifest>
@@ -0,0 +1,66 @@
package de.mm20.launcher2.search.data
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import de.mm20.launcher2.icons.ColorLayer
import de.mm20.launcher2.icons.StaticLauncherIcon
import de.mm20.launcher2.icons.TintedIconLayer
import de.mm20.launcher2.ktx.tryStartActivity
import de.mm20.launcher2.search.SavableSearchable
import de.mm20.launcher2.wikipedia.R
data class Wikipedia(
override val label: String,
val id: Long,
val text: String,
val image: String?,
val wikipediaUrl: String,
override val labelOverride: String? = null,
) : SavableSearchable {
override val domain: String = Domain
override val preferDetailsOverLaunch: Boolean = false
override fun overrideLabel(label: String): Wikipedia {
return this.copy(labelOverride = label)
}
override val key = "$domain://$wikipediaUrl:$id"
override fun getPlaceholderIcon(context: Context): StaticLauncherIcon {
return StaticLauncherIcon(
foregroundLayer = TintedIconLayer(
icon = ContextCompat.getDrawable(context, R.drawable.ic_wikipedia)!!,
scale = 1f,
color = 0xFFC1C2C4.toInt(),
),
backgroundLayer = ColorLayer(0xFFC1C2C4.toInt())
)
}
private fun getLaunchIntent(): Intent {
val intent = CustomTabsIntent
.Builder()
.setToolbarColor(Color.BLACK)
.enableUrlBarHiding()
.setShowTitle(true)
.build()
val uri = "${wikipediaUrl.padEnd(1, '/')}wiki?curid=$id"
intent.intent.data = Uri.parse(uri)
return intent.intent
}
override fun launch(context: Context, options: Bundle?): Boolean {
return context.tryStartActivity(getLaunchIntent(), options)
}
companion object {
const val Domain = "wikipedia"
}
}
@@ -0,0 +1,8 @@
package de.mm20.launcher2.wikipedia
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
val wikipediaModule = module {
single<WikipediaRepository> { WikipediaRepositoryImpl(androidContext(), get()) }
}
@@ -0,0 +1,42 @@
package de.mm20.launcher2.wikipedia
import retrofit2.http.GET
import retrofit2.http.Query
data class WikipediaSearchResult(
val query: WikipediaSearchResultQuery?,
)
data class WikipediaSearchResultQuery(
val pages: Map<String, WikipediaSearchResultQueryPage>,
)
data class WikipediaSearchResultQueryPage(
val pageid: Long,
val title: String,
val extract: String,
)
data class WikipediaGetPageImageResult(
val query: WikipediaGetPageImageResultQuery?,
)
data class WikipediaGetPageImageResultQuery(
val pages: Map<String, WikipediaGetPageImageResultQueryPage>
)
data class WikipediaGetPageImageResultQueryPage(
val thumbnail: WikipediaGetPageImageResultQueryPageThumnail?
)
data class WikipediaGetPageImageResultQueryPageThumnail(
val source: String
)
interface WikipediaApi {
@GET("w/api.php?action=query&generator=search&redirects=true&gsrlimit=1&exchars=500&prop=extracts&exintro=true&format=json")
suspend fun search(@Query("gsrsearch") query: String): WikipediaSearchResult
@GET("w/api.php?action=query&prop=pageimages&format=json")
suspend fun getPageImage(@Query("pageids") pageId: Long, @Query("pithumbsize") thumbnailSize: Int): WikipediaGetPageImageResult
}
@@ -0,0 +1,106 @@
package de.mm20.launcher2.wikipedia
import android.content.Context
import android.util.Log
import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.search.data.Wikipedia
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import okhttp3.OkHttpClient
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
interface WikipediaRepository {
fun search(query: String, loadImages: Boolean = false): Flow<Wikipedia?>
}
internal class WikipediaRepositoryImpl(
private val context: Context,
private val dataStore: LauncherDataStore
) : WikipediaRepository, KoinComponent {
private val scope = CoroutineScope(Job() + Dispatchers.Default)
private val httpClient = OkHttpClient
.Builder()
.connectTimeout(200, TimeUnit.MILLISECONDS)
.readTimeout(3000, TimeUnit.MILLISECONDS)
.writeTimeout(1000, TimeUnit.MILLISECONDS)
.build()
private lateinit var retrofit: Retrofit
init {
scope.launch {
dataStore.data
.map { it.wikipediaSearch.customUrl }
.distinctUntilChanged()
.collectLatest {
try { retrofit = Retrofit.Builder()
.client(httpClient)
.baseUrl(it.takeIf { !it.isNullOrBlank() }
?: context.getString(R.string.wikipedia_url))
.addConverterFactory(GsonConverterFactory.create())
.build()
wikipediaService = retrofit.create(WikipediaApi::class.java)
} catch (e: IllegalArgumentException) {
CrashReporter.logException(e)
}
}
}
}
private lateinit var wikipediaService: WikipediaApi
override fun search(query: String, loadImages: Boolean): Flow<Wikipedia?> = channelFlow {
send(null)
withContext(Dispatchers.IO) {
httpClient.dispatcher.cancelAll()
}
if (!::wikipediaService.isInitialized) return@channelFlow
if (query.isBlank()) return@channelFlow
send(queryWikipedia(query, loadImages))
}
private suspend fun queryWikipedia(query: String, loadImages: Boolean): Wikipedia? {
val wikipediaService = wikipediaService
val wikipediaUrl = retrofit.baseUrl().toString()
val result = try {
wikipediaService.search(query)
} catch (e: Exception) {
CrashReporter.logException(e)
return null
}
val page = result.query?.pages?.values?.toList()?.getOrNull(0) ?: return null
val image = if (loadImages) {
val width = context.resources.displayMetrics.widthPixels / 2
val imageResult = try {
wikipediaService.getPageImage(page.pageid, width)
} catch (e: Exception) {
CrashReporter.logException(e)
return null
}
imageResult.query?.pages?.values?.toList()?.getOrNull(0)?.thumbnail?.source
} else null
return Wikipedia(
label = page.title,
id = page.pageid,
text = page.extract,
image = image,
wikipediaUrl = wikipediaUrl
)
}
}
@@ -0,0 +1,37 @@
package de.mm20.launcher2.wikipedia
import android.content.Context
import de.mm20.launcher2.search.SavableSearchable
import de.mm20.launcher2.search.SearchableDeserializer
import de.mm20.launcher2.search.SearchableSerializer
import de.mm20.launcher2.search.data.Wikipedia
import org.json.JSONObject
class WikipediaSerializer : SearchableSerializer {
override fun serialize(searchable: SavableSearchable): String {
searchable as Wikipedia
val json = JSONObject()
json.put("label", searchable.label)
json.put("text", searchable.text)
json.put("id", searchable.id)
json.put("image", searchable.image)
json.put("wikipedia_url", searchable.wikipediaUrl)
return json.toString()
}
override val typePrefix: String
get() = "wikipedia"
}
class WikipediaDeserializer(val context: Context) : SearchableDeserializer {
override fun deserialize(serialized: String): SavableSearchable? {
val json = JSONObject(serialized)
return Wikipedia(
label = json.getString("label"),
text = json.getString("text"),
id = json.getLong("id"),
image = json.optString("image"),
wikipediaUrl = json.optString("wikipedia_url").takeIf { !it.isNullOrBlank() } ?: return null,
)
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB