Skip to content
Snippets Groups Projects
Verified Commit 7250a3e1 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Allow choosing language in-app

parent a60f920a
Branches
Tags
No related merge requests found
Pipeline #
Showing
with 187 additions and 49 deletions
......@@ -19,6 +19,7 @@
package de.kuschku.quasseldroid
import android.content.Context
import android.os.Build
import android.os.StrictMode
import com.squareup.leakcanary.LeakCanary
......@@ -35,6 +36,7 @@ import de.kuschku.quasseldroid.util.backport.AndroidThreeTenBackport
import de.kuschku.quasseldroid.util.compatibility.AndroidCompatibilityUtils
import de.kuschku.quasseldroid.util.compatibility.AndroidLoggingHandler
import de.kuschku.quasseldroid.util.compatibility.AndroidStreamChannelFactory
import de.kuschku.quasseldroid.util.ui.LocaleHelper
class Quasseldroid : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<Quasseldroid> =
......@@ -226,4 +228,8 @@ class Quasseldroid : DaggerApplication() {
)
}
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleHelper.setLocale(base))
}
}
......@@ -25,7 +25,8 @@ import de.kuschku.quasseldroid.R
data class AppearanceSettings(
val inputEnter: InputEnterMode = InputEnterMode.EMOJI,
val showLag: Boolean = true,
val theme: Theme = Theme.MATERIAL_LIGHT
val theme: Theme = Theme.MATERIAL_LIGHT,
val language: String = ""
) {
enum class InputEnterMode {
EMOJI,
......
......@@ -43,6 +43,10 @@ object Settings {
showLag = getBoolean(
context.getString(R.string.preference_show_lag_key),
AppearanceSettings.DEFAULT.showLag
),
language = getString(
context.getString(R.string.preference_language_key),
AppearanceSettings.DEFAULT.language
)
)
}
......
......@@ -29,6 +29,7 @@ import de.kuschku.libquassel.protocol.Buffer_Type
import de.kuschku.libquassel.quassel.syncables.IrcChannel
import de.kuschku.libquassel.util.IrcUserUtils
import de.kuschku.libquassel.util.flag.hasFlag
import de.kuschku.libquassel.util.helpers.nullIf
import de.kuschku.libquassel.util.helpers.value
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.settings.AutoCompleteSettings
......@@ -152,15 +153,15 @@ class AutoCompleteHelper(
}.mapNotNull { info ->
networks[info.networkId]?.let { info to it }
}.map { (info, network) ->
val channel = network.ircChannel(info.bufferName) ?: IrcChannel.NULL
val channel = network.ircChannel(info.bufferName).nullIf { it == IrcChannel.NULL }
AutoCompleteItem.ChannelItem(
info = info,
network = network.networkInfo(),
bufferStatus = when (channel) {
IrcChannel.NULL -> BufferStatus.OFFLINE
null -> BufferStatus.OFFLINE
else -> BufferStatus.ONLINE
},
description = channel.topic()
description = channel?.topic() ?: ""
)
}
val nicks = users.asSequence().map { user ->
......
......@@ -63,7 +63,9 @@ class ClientSettingsFragment : DaggerPreferenceFragmentCompat(),
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
updateSummary(findPreference(key))
if (appearanceSettings.theme != Settings.appearance(context!!).theme) {
val appearanceSettings = Settings.appearance(context!!)
if (this.appearanceSettings.theme != appearanceSettings.theme ||
this.appearanceSettings.language != appearanceSettings.language) {
activity?.recreate()
}
}
......
......@@ -21,6 +21,8 @@ package de.kuschku.quasseldroid.ui.setup
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Observer
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Parcelable
import android.support.annotation.ColorRes
......@@ -35,6 +37,7 @@ import android.view.ViewGroup
import butterknife.BindView
import butterknife.ButterKnife
import dagger.android.support.DaggerAppCompatActivity
import de.kuschku.libquassel.util.helpers.nullIf
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.ui.clientsettings.about.AboutActivity
import de.kuschku.quasseldroid.ui.clientsettings.client.ClientSettingsActivity
......@@ -44,6 +47,7 @@ import de.kuschku.quasseldroid.util.helper.observeSticky
import de.kuschku.quasseldroid.util.helper.or
import de.kuschku.quasseldroid.util.helper.switchMap
import de.kuschku.quasseldroid.util.helper.updateRecentsHeaderIfExisting
import de.kuschku.quasseldroid.util.ui.LocaleHelper
abstract class SetupActivity : DaggerAppCompatActivity() {
@BindView(R.id.menu_view)
......@@ -104,6 +108,8 @@ abstract class SetupActivity : DaggerAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_SetupTheme)
super.onCreate(savedInstanceState)
packageManager.getActivityInfo(componentName, PackageManager.GET_META_DATA).labelRes
.nullIf { it == 0 }?.let(this::setTitle)
setContentView(R.layout.activity_setup)
ButterKnife.bind(this)
......@@ -158,6 +164,10 @@ abstract class SetupActivity : DaggerAppCompatActivity() {
updateRecentsHeader()
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.setLocale(newBase))
}
private fun onDoneInternal() {
onDone(adapter.result)
}
......
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.quasseldroid.util.ui
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import de.kuschku.quasseldroid.settings.Settings
import java.util.*
object LocaleHelper {
fun setLocale(context: Context): Context {
return updateResources(context, Settings.appearance(context).language)
}
private fun updateResources(context: Context, language: String) = if (language.isNotEmpty()) {
val locale = Locale(language)
Locale.setDefault(locale)
val config = Configuration(context.resources.configuration)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
config.setLocale(locale)
context.createConfigurationContext(config)
} else {
config.locale = locale
context.resources.updateConfiguration(config, context.resources.displayMetrics)
context
}
} else context
}
......@@ -19,6 +19,8 @@
package de.kuschku.quasseldroid.util.ui
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
......@@ -27,6 +29,7 @@ import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasFragmentInjector
import dagger.android.support.HasSupportFragmentInjector
import de.kuschku.libquassel.util.helpers.nullIf
import de.kuschku.quasseldroid.settings.AppearanceSettings
import javax.inject.Inject
......@@ -45,6 +48,12 @@ abstract class ThemedActivity : AppCompatActivity(), HasSupportFragmentInjector,
AndroidInjection.inject(this)
setTheme(appearanceSettings.theme.style)
super.onCreate(savedInstanceState)
packageManager.getActivityInfo(componentName, PackageManager.GET_META_DATA).labelRes
.nullIf { it == 0 }?.let(this::setTitle)
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.setLocale(newBase))
}
override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
......
......@@ -74,6 +74,25 @@
<string name="preference_show_lag_title">Show lag</string>
<string name="preference_show_lag_summary">Displays the lag between client and core in the action bar</string>
<string name="preference_language_key" translatable="false">language</string>
<string name="preference_language_title">Language</string>
<string name="preference_language_entry_auto">System Default</string>
<string name="preference_language_entry_en" translatable="false">English</string>
<string name="preference_language_entry_de" translatable="false">Deutsch</string>
<string name="preference_language_entry_lt" translatable="false">Lithuanian</string>
<string-array name="preference_language_entries">
<item>@string/preference_language_entry_auto</item>
<item>@string/preference_language_entry_en</item>
<item>@string/preference_language_entry_de</item>
<item>@string/preference_language_entry_lt</item>
</string-array>
<string-array name="preference_language_entryvalues" translatable="false">
<item />
<item>en</item>
<item>de</item>
<item>lt</item>
</string-array>
<string name="preference_notifications_title">Notifications</string>
......
......@@ -39,6 +39,13 @@
android:key="@string/preference_show_lag_key"
android:summary="@string/preference_show_lag_summary"
android:title="@string/preference_show_lag_title" />
<DropDownPreference
android:defaultValue=""
android:entries="@array/preference_language_entries"
android:entryValues="@array/preference_language_entryvalues"
android:key="@string/preference_language_key"
android:title="@string/preference_language_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/preference_notifications_title">
......
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.libquassel.util.helpers
inline fun <T> T.nullIf(f: (T) -> Boolean): T? = if (f(this)) null else this
......@@ -41,6 +41,18 @@ fun <T : Any, U : Any> Observable<Optional<T>>.mapMapNullable(
}
}
fun <T : Any, U : Any> Observable<T>.mapNullable(
nullableValue: T,
mapper: (T?) -> U): Observable<U> = map {
mapper(it.nullIf { it == nullableValue })
}
fun <T : Any, U : Any> Observable<T>.switchMapNullable(
nullableValue: T,
mapper: (T?) -> Observable<U>): Observable<U> = switchMap {
mapper(it.nullIf { it == nullableValue })
}
fun <T : Any, U : Any> Observable<Optional<T>>.mapSwitchMap(
mapper: (T) -> Observable<U>): Observable<Optional<U>> = switchMap {
if (it.isPresent()) {
......
......@@ -26,6 +26,7 @@ import de.kuschku.libquassel.quassel.syncables.IrcUser
import de.kuschku.libquassel.session.ISession
import de.kuschku.libquassel.util.Optional
import de.kuschku.libquassel.util.flag.hasFlag
import de.kuschku.libquassel.util.helpers.mapNullable
import de.kuschku.quasseldroid.util.helper.combineLatest
import de.kuschku.quasseldroid.viewmodel.data.AutoCompleteItem
import de.kuschku.quasseldroid.viewmodel.data.BufferStatus
......@@ -76,15 +77,15 @@ class EditorViewModel : ViewModel() {
network.liveIrcChannel(
info.bufferName
).switchMap { channel ->
channel.updates().map {
channel.updates().mapNullable(IrcChannel.NULL) {
AutoCompleteItem.ChannelItem(
info = info,
network = network.networkInfo(),
bufferStatus = when (it) {
IrcChannel.NULL -> BufferStatus.OFFLINE
null -> BufferStatus.OFFLINE
else -> BufferStatus.ONLINE
},
description = it.topic()
description = it?.topic() ?: ""
)
}
}
......
......@@ -201,9 +201,8 @@ class QuasselViewModel : ViewModel() {
if (bufferInfo?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) {
session.liveNetworks().switchMap { networks ->
val network = networks[bufferInfo.networkId]
network?.liveIrcChannel(bufferInfo.bufferName)?.switchMap { ircChannel ->
if (ircChannel != IrcChannel.NULL) {
ircChannel.liveIrcUsers().switchMap { users ->
network?.liveIrcChannel(bufferInfo.bufferName)?.switchMapNullable(IrcChannel.NULL) { ircChannel ->
ircChannel?.liveIrcUsers()?.switchMap { users ->
combineLatest<IrcUserItem>(
users.map<IrcUser, Observable<IrcUserItem>?> {
it.updates().map { user ->
......@@ -226,10 +225,7 @@ class QuasselViewModel : ViewModel() {
}
}
)
}
} else {
Observable.just(emptyList())
}
} ?: Observable.just(emptyList())
}
}
} else {
......@@ -294,10 +290,10 @@ class QuasselViewModel : ViewModel() {
} ?: Observable.just(SelectedBufferItem(info, hiddenState = hiddenState))
}
Buffer_Type.ChannelBuffer -> {
network?.liveIrcChannel(info.bufferName)?.map {
network?.liveIrcChannel(info.bufferName)?.mapNullable(IrcChannel.NULL) {
SelectedBufferItem(
info,
joined = it != IrcChannel.NULL,
joined = it != null,
hiddenState = hiddenState
)
} ?: Observable.just(SelectedBufferItem(info, hiddenState = hiddenState))
......@@ -359,17 +355,17 @@ class QuasselViewModel : ViewModel() {
network.liveNetworkInfo().switchMap { networkInfo ->
network.liveConnectionState().switchMap { connectionState ->
network.liveIrcUser(info.bufferName).switchMap {
it.updates().map { user ->
it.updates().mapNullable(IrcUser.NULL) { user ->
BufferProps(
info = info,
network = networkInfo,
networkConnectionState = connectionState,
bufferStatus = when {
user == IrcUser.NULL -> BufferStatus.OFFLINE
user == null -> BufferStatus.OFFLINE
user.isAway() -> BufferStatus.AWAY
else -> BufferStatus.ONLINE
},
description = user.realName(),
description = user?.realName() ?: "",
activity = activity,
highlights = highlights,
hiddenState = state
......@@ -383,16 +379,16 @@ class QuasselViewModel : ViewModel() {
network.liveNetworkInfo().switchMap { networkInfo ->
network.liveConnectionState().switchMap { connectionState ->
network.liveIrcChannel(info.bufferName).switchMap { channel ->
channel.updates().map {
channel.updates().mapNullable(IrcChannel.NULL) {
BufferProps(
info = info,
network = networkInfo,
networkConnectionState = connectionState,
bufferStatus = when (it) {
IrcChannel.NULL -> BufferStatus.OFFLINE
null -> BufferStatus.OFFLINE
else -> BufferStatus.ONLINE
},
description = it.topic(),
description = it?.topic() ?: "",
activity = activity,
highlights = highlights,
hiddenState = state
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment