Initial integration.

This commit is contained in:
aminecmi 2022-11-30 20:53:11 +01:00
parent 7b68264dd7
commit c3ff894027
24 changed files with 151 additions and 13 deletions

View File

@ -1,6 +1,7 @@
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
val ignoreGitVersion: String by project val ignoreGitVersion: String by project
val acraVersion = "5.9.7"
plugins { plugins {
id("com.android.application") id("com.android.application")
@ -187,6 +188,9 @@ dependencies {
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("ch.acra:acra-http:$acraVersion")
implementation("ch.acra:acra-toast:$acraVersion")
// Matomo // Matomo
implementation("com.github.matomo-org:matomo-sdk-android:4.1.4") implementation("com.github.matomo-org:matomo-sdk-android:4.1.4")
} }

View File

@ -59,11 +59,15 @@ import com.mikepenz.materialdrawer.util.updateBadge
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.acra.ACRA
import org.acra.ktx.sendSilentlyWithAcra
import org.acra.ktx.sendWithAcra
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
import org.matomo.sdk.Tracker import org.matomo.sdk.Tracker
import org.matomo.sdk.extra.TrackHelper import org.matomo.sdk.extra.TrackHelper
import java.security.MessageDigest
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -306,6 +310,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
handleBottomBarActions() handleBottomBarActions()
handleGDPRDialog(appSettingsService.settings.getBoolean("GDPR_shown", false))
handleRecurringTask() handleRecurringTask()
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
@ -315,6 +321,26 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
getElementsAccordingToTab() getElementsAccordingToTab()
} }
private fun handleGDPRDialog(GDPRShown: Boolean) {
val messageDigest: MessageDigest = MessageDigest.getInstance("SHA-256")
messageDigest.update(appSettingsService.getBaseUrl().toByteArray())
ACRA.errorReporter.putCustomData("unique_id", String(messageDigest.digest()))
if (!GDPRShown) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle(getString(R.string.gdpr_dialog_title))
alertDialog.setMessage(getString(R.string.gdpr_dialog_message))
alertDialog.setButton(
AlertDialog.BUTTON_NEUTRAL,
"OK"
) { dialog, _ ->
appSettingsService.settings.putBoolean("GDPR_shown", true)
dialog.dismiss()
}
alertDialog.show()
}
}
private fun initDrawer() { private fun initDrawer() {
DrawerImageLoader.init(object : AbstractDrawerImageLoader() { DrawerImageLoader.init(object : AbstractDrawerImageLoader() {
override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) { override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String?) {
@ -487,6 +513,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
val gdColor = try { val gdColor = try {
Color.parseColor(it.color) Color.parseColor(it.color)
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
e.sendSilentlyWithAcra()
resources.getColor(R.color.colorPrimary) resources.getColor(R.color.colorPrimary)
} }
gd.setColor(gdColor) gd.setColor(gdColor)

View File

@ -29,6 +29,12 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.acra.ReportField
import org.acra.config.httpSender
import org.acra.config.toast
import org.acra.data.StringFormat
import org.acra.ktx.initAcra
import org.acra.sender.HttpSender
import org.kodein.di.* import org.kodein.di.*
import org.matomo.sdk.Matomo import org.matomo.sdk.Matomo
import org.matomo.sdk.Tracker import org.matomo.sdk.Tracker
@ -85,6 +91,35 @@ class MyApp : MultiDexApplication(), DIAware {
} }
} }
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
initAcra {
//core configuration:
buildConfigClass = BuildConfig::class.java
reportFormat = StringFormat.JSON
reportContent = listOf(
ReportField.REPORT_ID, ReportField.INSTALLATION_ID,
ReportField.APP_VERSION_CODE, ReportField.APP_VERSION_NAME,
ReportField.BUILD, ReportField.ANDROID_VERSION, ReportField.BRAND, ReportField.PHONE_MODEL,
ReportField.AVAILABLE_MEM_SIZE, ReportField.TOTAL_MEM_SIZE,
ReportField.STACK_TRACE, ReportField.APPLICATION_LOG, ReportField.LOGCAT,
ReportField.INITIAL_CONFIGURATION, ReportField.CRASH_CONFIGURATION, ReportField.IS_SILENT,
ReportField.USER_APP_START_DATE, ReportField.USER_COMMENT, ReportField.USER_CRASH_DATE, ReportField.USER_EMAIL, ReportField.CUSTOM_DATA)
toast {
//required
text = getString(R.string.crash_toast_text)
length = Toast.LENGTH_LONG
}
httpSender {
uri = "https://your.server.com/report"
httpMethod = HttpSender.Method.POST
compress = false
}
}
}
private fun handleNotificationChannels() { private fun handleNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

View File

@ -44,6 +44,8 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.acra.ktx.sendSilentlyWithAcra
import org.acra.ktx.sendWithAcra
import org.kodein.di.DI import org.kodein.di.DI
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI import org.kodein.di.android.x.closestDI
@ -112,6 +114,7 @@ class ArticleFragment : Fragment(), DIAware {
typeface = try { typeface = try {
ResourcesCompat.getFont(requireContext(), resId)!! ResourcesCompat.getFont(requireContext(), resId)!!
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
e.sendSilentlyWithAcra()
// Just to be sure // Just to be sure
null null
} }
@ -217,6 +220,7 @@ class ArticleFragment : Fragment(), DIAware {
) )
} catch (e: InflateException) { } catch (e: InflateException) {
e.sendSilentlyWithAcra()
AlertDialog.Builder(requireContext()) AlertDialog.Builder(requireContext())
.setMessage(requireContext().getString(R.string.webview_dialog_issue_message)) .setMessage(requireContext().getString(R.string.webview_dialog_issue_message))
.setTitle(requireContext().getString(R.string.webview_dialog_issue_title)) .setTitle(requireContext().getString(R.string.webview_dialog_issue_title))
@ -264,15 +268,18 @@ class ArticleFragment : Fragment(), DIAware {
URL(response.data!!.url) URL(response.data!!.url)
url = response.data!!.url url = response.data!!.url
} catch (e: MalformedURLException) { } catch (e: MalformedURLException) {
// Mercury returned a relative url. We do nothing. // Mercury returned a relative url
e.sendSilentlyWithAcra()
} }
} catch (e: Exception) { } catch (e: Exception) {
e.sendSilentlyWithAcra()
} }
try { try {
contentText = response.data!!.content.orEmpty() contentText = response.data!!.content.orEmpty()
htmlToWebview() htmlToWebview()
} catch (e: Exception) { } catch (e: Exception) {
e.sendSilentlyWithAcra()
} }
try { try {
@ -288,13 +295,13 @@ class ArticleFragment : Fragment(), DIAware {
.apply(RequestOptions.fitCenterTransform()) .apply(RequestOptions.fitCenterTransform())
.into(binding.imageView) .into(binding.imageView)
} catch (e: Exception) { } catch (e: Exception) {
e.sendSilentlyWithAcra()
} }
} else { } else {
binding.imageView.visibility = View.GONE binding.imageView.visibility = View.GONE
} }
} catch (e: Exception) { } catch (e: Exception) {
if (context != null) { e.sendSilentlyWithAcra()
}
} }
try { try {
@ -302,20 +309,17 @@ class ArticleFragment : Fragment(), DIAware {
binding.progressBar.visibility = View.GONE binding.progressBar.visibility = View.GONE
} catch (e: Exception) { } catch (e: Exception) {
if (context != null) { e.sendSilentlyWithAcra()
}
} }
} else { } else {
try { try {
openInBrowserAfterFailing() openInBrowserAfterFailing()
} catch (e: Exception) { } catch (e: Exception) {
if (context != null) { e.sendSilentlyWithAcra()
}
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
if (context != null) { e.sendSilentlyWithAcra()
}
} }
} else { } else {
openInBrowserAfterFailing() openInBrowserAfterFailing()
@ -359,19 +363,25 @@ class ArticleFragment : Fragment(), DIAware {
try { try {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG)) return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG))
}catch ( e : ExecutionException) {} } catch ( e : ExecutionException) {
e.sendSilentlyWithAcra()
}
} }
else if (url.lowercase(Locale.US).contains(".png")) { else if (url.lowercase(Locale.US).contains(".png")) {
try { try {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG)) return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG))
}catch ( e : ExecutionException) {} } catch ( e : ExecutionException) {
e.sendSilentlyWithAcra()
}
} }
else if (url.lowercase(Locale.US).contains(".webp")) { else if (url.lowercase(Locale.US).contains(".webp")) {
try { try {
val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get() val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP)) return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP))
}catch ( e : ExecutionException) {} } catch ( e : ExecutionException) {
e.sendSilentlyWithAcra()
}
} }
return super.shouldInterceptRequest(view, url) return super.shouldInterceptRequest(view, url)
@ -395,6 +405,7 @@ class ArticleFragment : Fragment(), DIAware {
val itemUrl = URL(url) val itemUrl = URL(url)
baseUrl = itemUrl.protocol + "://" + itemUrl.host baseUrl = itemUrl.protocol + "://" + itemUrl.host
} catch (e: MalformedURLException) { } catch (e: MalformedURLException) {
e.sendSilentlyWithAcra()
} }
val fontName = when (font) { val fontName = when (font) {

View File

@ -7,6 +7,7 @@ import bou.amine.apps.readerforselfossv2.utils.getImages
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import org.acra.ktx.sendSilentlyWithAcra
fun SelfossModel.Item.preloadImages(context: Context) : Boolean { fun SelfossModel.Item.preloadImages(context: Context) : Boolean {
val imageUrls = this.getImages() val imageUrls = this.getImages()
@ -23,6 +24,7 @@ fun SelfossModel.Item.preloadImages(context: Context) : Boolean {
} }
} }
} catch (e : Error) { } catch (e : Error) {
e.sendSilentlyWithAcra()
return false return false
} }
@ -35,7 +37,7 @@ fun String.toTextDrawableString(): String {
try { try {
textDrawable.append(s[0]) textDrawable.append(s[0])
} catch (e: StringIndexOutOfBoundsException) { } catch (e: StringIndexOutOfBoundsException) {
// We do nothing e.sendSilentlyWithAcra()
} }
} }
return textDrawable.toString() return textDrawable.toString()

View File

@ -17,6 +17,8 @@ import androidx.preference.PreferenceFragmentCompat
import bou.amine.apps.readerforselfossv2.android.R import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding
import bou.amine.apps.readerforselfossv2.service.AppSettingsService import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import org.acra.ktx.sendSilentlyWithAcra
import org.acra.ktx.sendWithAcra
import org.kodein.di.DIAware import org.kodein.di.DIAware
import org.kodein.di.android.closestDI import org.kodein.di.android.closestDI
import org.kodein.di.instance import org.kodein.di.instance
@ -117,6 +119,7 @@ class SettingsActivity : AppCompatActivity(),
val input: Int = (dest.toString() + source.toString()).toInt() val input: Int = (dest.toString() + source.toString()).toInt()
if (input in 1..200) return@InputFilter null if (input in 1..200) return@InputFilter null
} catch (nfe: NumberFormatException) { } catch (nfe: NumberFormatException) {
nfe.sendSilentlyWithAcra()
Toast.makeText(activity, R.string.items_number_should_be_number, Toast.LENGTH_LONG).show() Toast.makeText(activity, R.string.items_number_should_be_number, Toast.LENGTH_LONG).show()
} }
"" ""
@ -140,6 +143,7 @@ class SettingsActivity : AppCompatActivity(),
try { try {
editText.textSize = editable.toString().toInt().toFloat() editText.textSize = editable.toString().toInt().toFloat()
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
e.sendSilentlyWithAcra()
} }
} }
} } } }
@ -149,6 +153,7 @@ class SettingsActivity : AppCompatActivity(),
val input = (dest.toString() + source.toString()).toInt() val input = (dest.toString() + source.toString()).toInt()
if (input > 0) return@InputFilter null if (input > 0) return@InputFilter null
} catch (nfe: NumberFormatException) { } catch (nfe: NumberFormatException) {
nfe.sendSilentlyWithAcra()
} }
"" ""
} }

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Thème clair</string> <string name="mode_light">Thème clair</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">浅色模式</string> <string name="mode_light">浅色模式</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -134,4 +134,7 @@
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="drawer_error_loading_sources">Error loading sources…</string> <string name="drawer_error_loading_sources">Error loading sources…</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>

View File

@ -137,4 +137,7 @@
<string name="mode_system">Follow the system setting</string> <string name="mode_system">Follow the system setting</string>
<string name="mode_light">Light mode</string> <string name="mode_light">Light mode</string>
<string name="pref_switch_enable_analytics">Enable analytics</string> <string name="pref_switch_enable_analytics">Enable analytics</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="gdpr_dialog_message"><![CDATA[Crash reports sending is now enabled. It can be disabled from the settings page (Settings > Debug). Keep in mind that crash reports are essential for the app development.]]></string>
<string name="crash_toast_text">A crash occured. Sending the details to the developper.</string>
</resources> </resources>