diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt
index e4d8f50d..f04615c3 100644
--- a/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt
+++ b/favorites/src/main/java/de/mm20/launcher2/favorites/Module.kt
@@ -68,7 +68,7 @@ val favoritesModule = module {
return@factory ContactDeserializer(androidContext())
}
if (type == "wikipedia") {
- return@factory WikipediaDeserializer()
+ return@factory WikipediaDeserializer(androidContext())
}
if (type == "gdrive") {
return@factory GDriveFileDeserializer()
diff --git a/i18n/src/main/res/values-de/strings.xml b/i18n/src/main/res/values-de/strings.xml
index 65de1496..5e359cbb 100644
--- a/i18n/src/main/res/values-de/strings.xml
+++ b/i18n/src/main/res/values-de/strings.xml
@@ -454,6 +454,8 @@
Websuchen
Shortcuts zu verschiedenen Websuch-Engines anzeigen
+ Wikipedia-URL
+
%1$s spielt Medien
Bisher wurden keine Medien abgespielt
\ No newline at end of file
diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml
index 7306ee28..7e3f4c6b 100644
--- a/i18n/src/main/res/values/strings.xml
+++ b/i18n/src/main/res/values/strings.xml
@@ -492,6 +492,8 @@
Restrict to music apps
Ignore media sessions of apps that are not music apps
+ Wikipedia URL
+
%1$s is playing media
No media has been played yet
diff --git a/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt b/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
index 02e563c7..016385b9 100644
--- a/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
+++ b/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt
@@ -62,6 +62,7 @@ fun createFactorySettings(context: Context): Settings {
.setWikipediaSearch(Settings.WikipediaSearchSettings
.newBuilder()
.setEnabled(false)
+ .setImages(false)
.setCustomUrl(null)
)
.setWebsiteSearch(Settings.WebsiteSearchSettings
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/TextPreference.kt b/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/TextPreference.kt
new file mode 100644
index 00000000..d15ec75c
--- /dev/null
+++ b/ui/src/main/java/de/mm20/launcher2/ui/component/preferences/TextPreference.kt
@@ -0,0 +1,70 @@
+package de.mm20.launcher2.ui.component.preferences
+
+import androidx.compose.material.OutlinedTextField
+import androidx.compose.material.TextButton
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.*
+import androidx.compose.ui.res.stringResource
+
+@Composable
+fun TextPreference(
+ title: String,
+ value: String,
+ summary: String? = value,
+ onValueChanged: (String) -> Unit,
+ placeholder: String? = null
+) {
+ var showDialog by remember { mutableStateOf(false) }
+ Preference(
+ title = title,
+ summary = summary,
+ onClick = { showDialog = true }
+ )
+
+ if (showDialog) {
+ var textFieldValue by remember { mutableStateOf(value) }
+ AlertDialog(
+ onDismissRequest = { showDialog = false },
+ title = {
+ Text(text = title, style = MaterialTheme.typography.titleLarge)
+ },
+ text = {
+ OutlinedTextField(
+ value = textFieldValue,
+ onValueChange = { textFieldValue = it },
+ placeholder = placeholder?.let {
+ {
+ Text(
+ text = it,
+ style = MaterialTheme.typography.bodyLarge
+ )
+ }
+ },
+ )
+ },
+ confirmButton = {
+ TextButton(onClick = {
+ onValueChanged(textFieldValue)
+ showDialog = false
+ }) {
+ Text(
+ text = stringResource(android.R.string.ok),
+ style = MaterialTheme.typography.labelLarge
+ )
+ }
+ },
+ dismissButton = {
+ TextButton(onClick = {
+ showDialog = false
+ }) {
+ Text(
+ text = stringResource(android.R.string.cancel),
+ style = MaterialTheme.typography.labelLarge
+ )
+ }
+ }
+ )
+ }
+}
\ No newline at end of file
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt
index 9c53a5a2..17004db8 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt
@@ -32,6 +32,7 @@ import de.mm20.launcher2.ui.settings.musicwidget.MusicWidgetSettingsScreen
import de.mm20.launcher2.ui.settings.search.SearchSettingsScreen
import de.mm20.launcher2.ui.settings.weatherwidget.WeatherWidgetSettingsScreen
import de.mm20.launcher2.ui.settings.widgets.WidgetsSettingsScreen
+import de.mm20.launcher2.ui.settings.wikipedia.WikipediaSettingsScreen
class SettingsActivity : BaseActivity() {
@@ -90,6 +91,9 @@ class SettingsActivity : BaseActivity() {
composable("settings/search") {
SearchSettingsScreen()
}
+ composable("settings/search/wikipedia") {
+ WikipediaSettingsScreen()
+ }
composable("settings/widgets") {
WidgetsSettingsScreen()
}
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt
index 7c625292..b4dc0356 100644
--- a/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/search/SearchSettingsScreen.kt
@@ -17,6 +17,7 @@ import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.MissingPermissionBanner
import de.mm20.launcher2.ui.component.preferences.*
import de.mm20.launcher2.ui.icons.Wikipedia
+import de.mm20.launcher2.ui.locals.LocalNavController
@Composable
fun SearchSettingsScreen() {
@@ -24,6 +25,8 @@ fun SearchSettingsScreen() {
val viewModel: SearchSettingsScreenVM = viewModel()
val context = LocalContext.current
+ val navController = LocalNavController.current
+
PreferenceScreen(title = stringResource(R.string.preference_screen_search)) {
item {
PreferenceCategory {
@@ -116,6 +119,9 @@ fun SearchSettingsScreen() {
switchValue = wikipedia == true,
onSwitchChanged = {
viewModel.setWikipedia(it)
+ },
+ onClick = {
+ navController?.navigate("settings/search/wikipedia")
}
)
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/wikipedia/WikipediaSettingsScreen.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/wikipedia/WikipediaSettingsScreen.kt
new file mode 100644
index 00000000..11a17c06
--- /dev/null
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/wikipedia/WikipediaSettingsScreen.kt
@@ -0,0 +1,49 @@
+package de.mm20.launcher2.ui.settings.wikipedia
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.viewmodel.compose.viewModel
+import de.mm20.launcher2.ui.R
+import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
+import de.mm20.launcher2.ui.component.preferences.SwitchPreference
+import de.mm20.launcher2.ui.component.preferences.TextPreference
+
+@Composable
+fun WikipediaSettingsScreen() {
+ val viewModel: WikipediaSettingsScreenVM = viewModel()
+ PreferenceScreen(title = stringResource(R.string.preference_search_wikipedia)) {
+ item {
+ val wikipedia by viewModel.wikipedia.observeAsState()
+ SwitchPreference(
+ title = stringResource(R.string.preference_search_wikipedia),
+ summary = stringResource(R.string.preference_search_wikipedia_summary),
+ value = wikipedia == true,
+ onValueChanged = {
+ viewModel.setWikipedia(it)
+ }
+ )
+ val images by viewModel.images.observeAsState()
+ SwitchPreference(
+ title = stringResource(R.string.preference_search_wikipedia_pictures),
+ summary = stringResource(R.string.preference_search_wikipedia_pictures_summary),
+ enabled = wikipedia == true,
+ value = images == true,
+ onValueChanged = {
+ viewModel.setImages(it)
+ }
+ )
+ val customUrl by viewModel.customUrl.observeAsState("")
+ TextPreference(
+ title = stringResource(R.string.preference_wikipedia_customurl),
+ value = customUrl,
+ placeholder = stringResource(id = R.string.wikipedia_url),
+ summary = customUrl.takeIf { !it.isNullOrBlank() }
+ ?: stringResource(id = R.string.wikipedia_url),
+ onValueChanged = {
+ viewModel.setCustomUrl(it)
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/wikipedia/WikipediaSettingsScreenVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/wikipedia/WikipediaSettingsScreenVM.kt
new file mode 100644
index 00000000..f93997ce
--- /dev/null
+++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/wikipedia/WikipediaSettingsScreenVM.kt
@@ -0,0 +1,56 @@
+package de.mm20.launcher2.ui.settings.wikipedia
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.asLiveData
+import androidx.lifecycle.viewModelScope
+import de.mm20.launcher2.preferences.LauncherDataStore
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
+
+class WikipediaSettingsScreenVM: ViewModel(), KoinComponent {
+ private val dataStore: LauncherDataStore by inject()
+
+ val wikipedia = dataStore.data.map { it.wikipediaSearch.enabled }.asLiveData()
+ fun setWikipedia(wikipedia: Boolean) {
+ viewModelScope.launch {
+ dataStore.updateData {
+ it.toBuilder()
+ .setWikipediaSearch(
+ it.wikipediaSearch.toBuilder()
+ .setEnabled(wikipedia)
+ )
+ .build()
+ }
+ }
+ }
+
+ val images = dataStore.data.map { it.wikipediaSearch.images }.asLiveData()
+ fun setImages(images: Boolean) {
+ viewModelScope.launch {
+ dataStore.updateData {
+ it.toBuilder()
+ .setWikipediaSearch(
+ it.wikipediaSearch.toBuilder()
+ .setImages(images)
+ )
+ .build()
+ }
+ }
+ }
+
+ val customUrl = dataStore.data.map { it.wikipediaSearch.customUrl }.asLiveData()
+ fun setCustomUrl(customUrl: String) {
+ viewModelScope.launch {
+ dataStore.updateData {
+ it.toBuilder()
+ .setWikipediaSearch(
+ it.wikipediaSearch.toBuilder()
+ .setCustomUrl(customUrl)
+ )
+ .build()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt b/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt
index 7dcbe705..fc264f3f 100644
--- a/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt
+++ b/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt
@@ -25,9 +25,10 @@ class Wikipedia(
override val label: String,
val id: Long,
val text: String,
- val image: String?
+ val image: String?,
+ val wikipediaUrl: String,
) : Searchable() {
- override val key = "wikipedia://$id"
+ override val key = "wikipedia://$wikipediaUrl:$id"
override suspend fun loadIcon(context: Context, size: Int): LauncherIcon? {
return null
@@ -47,70 +48,12 @@ class Wikipedia(
.enableUrlBarHiding()
.setShowTitle(true)
.build()
- val uri = "${context.getString(R.string.wikipedia_url)}/wiki?curid=$id"
+ val uri = "${wikipediaUrl}/wiki?curid=$id"
intent.intent.data = Uri.parse(uri)
return intent.intent
}
companion object {
- fun search(context: Context, query: String, client: OkHttpClient): Wikipedia? {
- mutableListOf()
- if (query.length < 4) return null
- val prefs = LauncherPreferences.instance
- if (!prefs.searchWikipedia ||
- NetworkUtils.isOffline(context, prefs.searchWikipediaMobileData)) return null
- val url = (context.getString(R.string.wikipedia_url) + "/w/api.php?action=query&"
- + "generator=search&redirects=true&gsrlimit=1&prop=extracts&format=json&gsrsearch="
- + query)
- val request = Request.Builder()
- .url(url)
- .tag("onlinesearch")
- .build()
- try {
- val response = client.newCall(request).execute()
- val json = JSONObject(response.body?.string() ?: return null)
- val pages = json.getJSONObject("query")
- .getJSONObject("pages")
- val it = pages.keys()
- if (it.hasNext()) {
- val key = it.next()
- val id = pages.getJSONObject(key).getLong("pageid")
- val title = pages.getJSONObject(key).getString("title")
- val text = pages.getJSONObject(key).getString("extract").also{
- it.substring(0, min(500, it.length)) + "…"
- }
- val image = getArticleImage(context, id, client)
- return Wikipedia(
- label = title,
- text = text,
- id = id,
- image = image
- )
- }
- } catch (e: IOException) {
- } catch (e: JSONException) {
- }
-
- return null
- }
-
- private fun getArticleImage(context: Context, id: Long, client: OkHttpClient): String? {
- if (!LauncherPreferences.instance.searchWikipediaPictures) return null
- val width = context.resources.displayMetrics.widthPixels / 2
- val url = (context.getString(R.string.wikipedia_url) + "/w/api.php?action=query&"
- + "prop=pageimages&format=json&pageids=$id&pithumbsize=$width")
- val request = Request.Builder()
- .url(url)
- .tag("onlinesearch")
- .build()
- val response = client.newCall(request).execute()
- val json = JSONObject(response.body?.string() ?: return null)
- return json.getJSONObject("query")
- .getJSONObject("pages")
- .getJSONObject(id.toString())
- .optJSONObject("thumbnail")
- ?.getString("source")
- }
}
}
\ No newline at end of file
diff --git a/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt b/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt
index 81a99961..9440229b 100644
--- a/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt
+++ b/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt
@@ -1,15 +1,12 @@
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.Dispatchers
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.channelFlow
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.withContext
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
import okhttp3.OkHttpClient
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
@@ -25,28 +22,40 @@ class WikipediaRepositoryImpl(
private val context: Context
) : WikipediaRepository, KoinComponent {
+ private val scope = CoroutineScope(Dispatchers.Main + Job())
+
private val dataStore: LauncherDataStore by inject()
- private val httpClient by lazy {
- OkHttpClient
- .Builder()
- .connectTimeout(200, TimeUnit.MILLISECONDS)
- .readTimeout(3000, TimeUnit.MILLISECONDS)
- .writeTimeout(1000, TimeUnit.MILLISECONDS)
- .build()
+ 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 {
+ 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)
+ }
+ }
}
- private val retrofit by lazy {
- Retrofit.Builder()
- .client(httpClient)
- .baseUrl(context.getString(R.string.wikipedia_url))
- .addConverterFactory(GsonConverterFactory.create())
- .build()
- }
-
- private val wikipediaService by lazy {
+ private lateinit var wikipediaService: WikipediaApi
+ /*by lazy {
retrofit.create(WikipediaApi::class.java)
- }
+ }*/
override fun search(query: String): Flow = channelFlow {
@@ -54,6 +63,8 @@ class WikipediaRepositoryImpl(
withContext(Dispatchers.IO) {
httpClient.dispatcher.cancelAll()
}
+
+ if (!::wikipediaService.isInitialized) return@channelFlow
if (query.isBlank()) return@channelFlow
dataStore.data.map { it.wikipediaSearch }.collectLatest {
@@ -67,6 +78,8 @@ class WikipediaRepositoryImpl(
private suspend fun queryWikipedia(query: String, loadImages: Boolean): Wikipedia? {
+ val wikipediaService = wikipediaService
+ val wikipediaUrl = retrofit.baseUrl().toString()
val result = try {
wikipediaService.search(query)
@@ -92,7 +105,8 @@ class WikipediaRepositoryImpl(
label = page.title,
id = page.pageid,
text = page.extract,
- image = image
+ image = image,
+ wikipediaUrl = wikipediaUrl
)
}
diff --git a/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt b/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt
index 6d602913..0746f9a9 100644
--- a/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt
+++ b/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt
@@ -1,5 +1,6 @@
package de.mm20.launcher2.wikipedia
+import android.content.Context
import de.mm20.launcher2.search.SearchableDeserializer
import de.mm20.launcher2.search.SearchableSerializer
import de.mm20.launcher2.search.data.Searchable
@@ -14,6 +15,7 @@ class WikipediaSerializer : SearchableSerializer {
json.put("text", searchable.text)
json.put("id", searchable.id)
json.put("image", searchable.image)
+ json.put("wikipedia_url", searchable.wikipediaUrl)
return json.toString()
}
@@ -21,14 +23,15 @@ class WikipediaSerializer : SearchableSerializer {
get() = "wikipedia"
}
-class WikipediaDeserializer : SearchableDeserializer {
+class WikipediaDeserializer(val context: Context) : SearchableDeserializer {
override fun deserialize(serialized: String): Searchable? {
val json = JSONObject(serialized)
return Wikipedia(
label = json.getString("label"),
text = json.getString("text"),
id = json.getLong("id"),
- image = json.optString("image")
+ image = json.optString("image"),
+ wikipediaUrl = json.optString("wikipedia_url").takeIf { !it.isNullOrBlank() } ?: return null,
)
}
}
\ No newline at end of file