~gardenapple/mitch

5bded8b482e90806600507f304808e9597574cd9 — gardenapple a month ago 136e6da
Implement language option, doesn't properly change at runtime
M app/src/main/java/ua/gardenapple/itchupdater/Mitch.kt => app/src/main/java/ua/gardenapple/itchupdater/Mitch.kt +40 -11
@@ 7,7 7,9 @@ import android.app.NotificationManager
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import androidx.work.*
import okhttp3.Cache


@@ 22,6 24,7 @@ import ua.gardenapple.itchupdater.database.DatabaseCleanup
import ua.gardenapple.itchupdater.files.*
import ua.gardenapple.itchupdater.install.InstallerDatabaseHandler
import ua.gardenapple.itchupdater.ui.CrashDialog
import ua.gardenapple.itchupdater.ui.MitchContextWrapper
import java.io.File
import java.util.concurrent.TimeUnit



@@ 56,6 59,9 @@ const val PREF_PALESTINE_LINK = "mitch.palestine"
const val PREF_PREFIX_PALESTINE_LINK = "mitch.palestine_"
const val PREF_PREFIX_PALESTINE_LAST_CHECK = "mitch.palestinetimestamp_"
const val PREF_WEB_ANDROID_FILTER = "ua.gardenapple.itchupdater.web_android_filter"
const val PREF_LANG = "mitch.lang"
const val PREF_LANG_LOCALE = "mitch.lang_locale"
const val PREF_LANG_SITE_LOCALE = "mitch.lang_site_locale"





@@ 64,8 70,8 @@ class Mitch : Application() {
    companion object {
        const val LOGGING_TAG: String = "MitchApp"

        // Used for lazy initialization
        private lateinit var applicationContext: Context
        // Used for lazy initialization, and for locale stuff
        private lateinit var mitchContext: MitchContextWrapper
        private lateinit var cacheDir: File

        val httpClient: OkHttpClient by lazy {


@@ 81,18 87,19 @@ class Mitch : Application() {
            }
        }
        val fileManager: DownloadFileManager by lazy {
            val downloadFileManager = DownloadFileManager(applicationContext)
            val downloadFileManager = DownloadFileManager(mitchContext)
            downloadFileManager.setup()
            return@lazy fileManager
        }
        val externalFileManager = ExternalFileManager()
        val databaseHandler: InstallerDatabaseHandler by lazy {
            InstallerDatabaseHandler(applicationContext)
            InstallerDatabaseHandler(mitchContext)
        }
    }

    private val preferenceChangeListener =
        SharedPreferences.OnSharedPreferenceChangeListener { prefs, key ->
            Log.d(LOGGING_TAG, "Changed $key !")
            when (key) {
                "preference_update_check_if_metered" -> {
                    registerUpdateCheckTask(prefs.getBoolean(key, false),


@@ 100,19 107,27 @@ class Mitch : Application() {
                }
                "preference_theme",
                "current_site_theme" -> setThemeFromPreferences(prefs)
                PREF_LANG,
                PREF_LANG_SITE_LOCALE -> setLangFromPreferences(prefs)
            }
        }


    override fun onCreate() {
        super.onCreate()
        if (ACRA.isACRASenderServiceProcess())
            return


        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        setThemeFromPreferences(sharedPreferences)
        setLangFromPreferences(sharedPreferences)

        mitchContext = MitchContextWrapper.wrap(applicationContext,
            sharedPreferences.getString(PREF_LANG_LOCALE, "en")!!)
        Mitch.cacheDir = cacheDir
        Mitch.applicationContext = applicationContext

        if (ACRA.isACRASenderServiceProcess())
            return

        setThemeFromPreferences(PreferenceManager.getDefaultSharedPreferences(this))

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            var name = getString(R.string.notification_channel_install)


@@ 156,14 171,11 @@ class Mitch : Application() {
            notificationManager.createNotificationChannel(channel)
        }


        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext)
        val workOnMetered = sharedPreferences.getBoolean("preference_update_check_if_metered", true)
        registerUpdateCheckTask(!workOnMetered, ExistingPeriodicWorkPolicy.KEEP)

        sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)


        WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork(
            DB_CLEAN_TASK_TAG,
            ExistingPeriodicWorkPolicy.KEEP,


@@ 209,6 221,23 @@ class Mitch : Application() {
        }
    }

    private fun setLangFromPreferences(prefs: SharedPreferences) {
        prefs.edit(true) {
            val newLocale = when (prefs.getString(PREF_LANG, "default")) {
                "system" -> Utils.getPreferredLocale(applicationContext).toLanguageTag()
                "site" -> prefs.getString(PREF_LANG_SITE_LOCALE, "en")
                else -> {
                    val siteLocale = prefs.getString(PREF_LANG_SITE_LOCALE, "en")
                    if (siteLocale == "en")
                        Utils.getPreferredLocale(applicationContext).toLanguageTag()
                    else
                        siteLocale
                }
            }
            putString(PREF_LANG_LOCALE, newLocale)
        }
    }

    /**
     * ACRA crash reports
     */

M app/src/main/java/ua/gardenapple/itchupdater/Utils.kt => app/src/main/java/ua/gardenapple/itchupdater/Utils.kt +14 -0
@@ 26,6 26,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.withContext
import java.io.*
import java.util.*
import kotlin.math.min




@@ 253,4 254,17 @@ object Utils {
        // https://stackoverflow.com/a/6540378/5701177
        return String.format("#%06X", 0xFFFFFF and color)
    }

    fun getPreferredLocale(config: Configuration): Locale {
        return if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
            return config.locales.get(0)
        } else {
            @Suppress("deprecation")
            return config.locale
        }
    }

    fun getPreferredLocale(context: Context): Locale {
        return getPreferredLocale(context.resources.configuration)
    }
}

M app/src/main/java/ua/gardenapple/itchupdater/client/ItchBrowseHandler.kt => app/src/main/java/ua/gardenapple/itchupdater/client/ItchBrowseHandler.kt +12 -6
@@ 3,6 3,7 @@ package ua.gardenapple.itchupdater.client
import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers


@@ 10,6 11,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jsoup.nodes.Document
import ua.gardenapple.itchupdater.ItchWebsiteUtils
import ua.gardenapple.itchupdater.PREF_LANG_SITE_LOCALE
import ua.gardenapple.itchupdater.R
import ua.gardenapple.itchupdater.data.JusticeBundleGameIDs
import ua.gardenapple.itchupdater.data.PalestineBundleGameIDs


@@ 97,14 99,18 @@ class ItchBrowseHandler(
            lastDownloadPageUrl = url
            tryStartDownload()
        }
        if (!ItchWebsiteUtils.isStylizedPage(doc)) {
            val preferences = PreferenceManager.getDefaultSharedPreferences(context)
            preferences.edit().also {
        val prefs = PreferenceManager.getDefaultSharedPreferences(context)
        prefs.edit(true) {
            if (!ItchWebsiteUtils.isStylizedPage(doc)) {
                if (ItchWebsiteUtils.isDarkTheme(doc))
                    it.putString("current_site_theme", "dark")
                    putString("current_site_theme", "dark")
                else
                    it.putString("current_site_theme", "light")
                it.apply()
                    putString("current_site_theme", "light")
            }
            val locale = ItchWebsiteParser.getLocale(doc)
            if (locale != ItchWebsiteParser.UNKNOWN_LOCALE) {
                Log.d(LOGGING_TAG, "Site locale is $locale")
                putString(PREF_LANG_SITE_LOCALE, locale)
            }
        }
        if (SpecialBundleHandler.checkIsBundleLink(context, doc, url)) {

M app/src/main/java/ua/gardenapple/itchupdater/ui/MitchActivity.kt => app/src/main/java/ua/gardenapple/itchupdater/ui/MitchActivity.kt +6 -1
@@ 2,9 2,14 @@ package ua.gardenapple.itchupdater.ui

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import ua.gardenapple.itchupdater.PREF_LANG_LOCALE

abstract class MitchActivity : AppCompatActivity() {
    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(MitchContextWrapper.wrap(newBase, "nb-NO"))
        val prefs = PreferenceManager.getDefaultSharedPreferences(newBase)

        super.attachBaseContext(MitchContextWrapper.wrap(newBase,
            prefs.getString(PREF_LANG_LOCALE, "en")!!))
    }
}
\ No newline at end of file

M app/src/main/java/ua/gardenapple/itchupdater/ui/MitchContextWrapper.kt => app/src/main/java/ua/gardenapple/itchupdater/ui/MitchContextWrapper.kt +5 -13
@@ 6,6 6,7 @@ import android.content.ContextWrapper
import android.content.res.Configuration
import android.os.Build
import android.util.Log
import ua.gardenapple.itchupdater.Utils
import java.util.*




@@ 19,12 20,12 @@ class MitchContextWrapper private constructor(val systemLocale: Locale, base: Co
        const val LOGGING_TAG = "MitchContextWrapper"

        @JvmStatic
        fun wrap(context: Context, language: String): ContextWrapper {
        fun wrap(context: Context, language: String): MitchContextWrapper {
            val config = context.resources.configuration

            val systemLocale = getLocale(config)
            Log.d(LOGGING_TAG, "Current locale: $systemLocale")
            Log.d(LOGGING_TAG, "Wrapper locale: $language")
            val systemLocale = Utils.getPreferredLocale(config)
//            Log.d(LOGGING_TAG, "Current locale: $systemLocale")
//            Log.d(LOGGING_TAG, "Wrapper locale: $language")

            if (language != "" && systemLocale.language != language) {
                val langComponents = language.split('_', '-')


@@ 47,15 48,6 @@ class MitchContextWrapper private constructor(val systemLocale: Locale, base: Co
            return MitchContextWrapper(systemLocale, wrappedContext)
        }

        private fun getLocale(config: Configuration): Locale {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
                return config.locales.get(0)
            } else {
                @Suppress("deprecation")
                return config.locale
            }
        }

        private fun setLocale(config: Configuration, locale: Locale) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                config.setLocale(locale)

M app/src/main/res/values/arrays.xml => app/src/main/res/values/arrays.xml +11 -0
@@ 40,4 40,15 @@
        <item>native</item>
        <item>session</item>
    </string-array>

    <string-array name="pref_lang_entries">
        <item>@string/settings_lang_default</item>
        <item>@string/settings_lang_site</item>
        <item>@string/settings_lang_system</item>
    </string-array>
    <string-array name="pref_lang_values">
        <item>default</item>
        <item>site</item>
        <item>system</item>
    </string-array>
</resources>
\ No newline at end of file

M app/src/main/res/xml/preferences.xml => app/src/main/res/xml/preferences.xml +7 -0
@@ 35,6 35,13 @@
                android:key="preference_theme"
                android:summary="%s"
                android:title="@string/settings_theme" />
        <ListPreference
                android:defaultValue="default"
                android:entries="@array/pref_lang_entries"
                android:entryValues="@array/pref_lang_values"
                android:key="mitch.lang"
                android:summary="%s"
                android:title="@string/settings_lang" />
    </PreferenceCategory>
    <PreferenceCategory android:title="@string/settings_category_advanced">
        <ListPreference