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

Fixes concurrency bugs

parent 1c6ec321
Branches
Tags
No related merge requests found
......@@ -22,6 +22,8 @@ package de.kuschku.quasseldroid.ui.clientsettings.client
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
......@@ -29,6 +31,7 @@ import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceGroup
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
import de.kuschku.quasseldroid.settings.AppearanceSettings
import de.kuschku.quasseldroid.settings.Settings
import de.kuschku.quasseldroid.ui.clientsettings.about.AboutActivity
......@@ -43,9 +46,21 @@ class ClientSettingsFragment : DaggerPreferenceFragmentCompat(),
@Inject
lateinit var appearanceSettings: AppearanceSettings
private lateinit var handlerThread: HandlerThread
private lateinit var handler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
handlerThread = HandlerThread("ClientSettings")
handlerThread.start()
handler = Handler(handlerThread.looper)
}
override fun onDestroy() {
super.onDestroy()
handlerThread.quit()
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
......@@ -57,6 +72,14 @@ class ClientSettingsFragment : DaggerPreferenceFragmentCompat(),
} else {
findPreference(getString(R.string.preference_notification_configure_key)).isVisible = false
}
findPreference(getString(R.string.preference_clear_cache_key)).setOnPreferenceClickListener {
activity?.let {
handler.post {
QuasselDatabase.Creator.init(it).message().clearMessages()
}
}
true
}
}
override fun onStart() {
......
......@@ -299,6 +299,8 @@
<string name="preference_initial_amount_title">Initial Amount</string>
<string name="preference_initial_amount_summary">Number of messages to load when opening a buffer for the first time</string>
<string name="preference_clear_cache_key" translatable="false">clear_cache_key</string>
<string name="preference_clear_cache_title">Clear Backlog Cache</string>
<string name="preference_connection_title">Connection</string>
......
......@@ -306,6 +306,9 @@
android:key="@string/preference_initial_amount_key"
android:summary="@string/preference_initial_amount_summary"
android:title="@string/preference_initial_amount_title" />
<PreferenceScreen
android:key="@string/preference_clear_cache_key"
android:title="@string/preference_clear_cache_title" />
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/widget_preference_divider" />
......
......@@ -17,6 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@file:Suppress("NOTHING_TO_INLINE")
package de.kuschku.libquassel.quassel.syncables
import de.kuschku.libquassel.protocol.*
......@@ -79,9 +80,11 @@ class IrcChannel(
"D" to QVariant.of(_D_channelModes.joinToString(), Type.QString)
)
override fun initUserModes(): QVariantMap = _userModes.entries.map { (key, value) ->
override fun initUserModes(): QVariantMap = synchronized(_userModes) {
_userModes.entries.map { (key, value) ->
key.nick() to QVariant.of(value, Type.QString)
}.toMap()
}
override fun initProperties(): QVariantMap = mapOf(
"name" to QVariant.of(name(), Type.QString),
......@@ -120,8 +123,8 @@ class IrcChannel(
setEncrypted(properties["encrypted"].indexed(i).valueOr(this::encrypted))
}
fun isKnownUser(ircUser: IrcUser): Boolean {
return _userModes.contains(ircUser)
fun isKnownUser(ircUser: IrcUser) = synchronized(_userModes) {
_userModes.contains(ircUser)
}
fun isValidChannelUserMode(mode: String): Boolean {
......@@ -133,14 +136,22 @@ class IrcChannel(
fun password() = _password
fun encrypted() = _encrypted
fun network() = _network
fun ircUsers() = _userModes.keys
fun liveIrcUsers(): Observable<MutableSet<IrcUser>> =
live_userModes.map { _userModes }.map(MutableMap<IrcUser, String>::keys)
fun ircUsers() = synchronized(_userModes) {
_userModes.keys.toSet()
}
fun liveIrcUsers(): Observable<Set<IrcUser>> =
live_userModes.map { ircUsers() }
fun userModes(ircUser: IrcUser) = synchronized(_userModes) {
_userModes.getOr(ircUser, "")
}
fun userModes(ircUser: IrcUser) = _userModes.getOr(ircUser, "")
fun liveUserModes(ircUser: IrcUser) = live_userModes.map {
synchronized(_userModes) {
_userModes.getOr(ircUser, "")
}
}
fun userCount() = _userCount
......@@ -248,6 +259,7 @@ class IrcChannel(
}
private fun joinIrcUsersInternal(rawUsers: List<IrcUser>, rawModes: List<String>) {
synchronized(_userModes) {
val users = rawUsers.zip(rawModes)
val newNicks = users.filter { !_userModes.contains(it.first) }
val oldNicks = users.filter { _userModes.contains(it.first) }
......@@ -262,12 +274,14 @@ class IrcChannel(
}
updateUsers()
}
}
override fun joinIrcUser(ircuser: IrcUser) {
joinIrcUsersInternal(listOf(ircuser), listOf(""))
}
override fun part(ircuser: IrcUser?) {
synchronized(_userModes) {
if (ircuser == null)
return
if (!isKnownUser(ircuser))
......@@ -284,17 +298,20 @@ class IrcChannel(
}
updateUsers()
}
}
override fun part(nick: String?) {
part(network().ircUser(nick))
}
override fun setUserModes(ircuser: IrcUser?, modes: String?) {
synchronized(_userModes) {
if (ircuser == null || !isKnownUser(ircuser))
return
_userModes[ircuser] = modes ?: ""
updateUsers()
}
}
override fun setUserModes(nick: String?, modes: String?) {
setUserModes(network().ircUser(nick), modes ?: "")
......@@ -305,6 +322,7 @@ class IrcChannel(
}
override fun addUserMode(ircuser: IrcUser?, mode: String?) {
synchronized(_userModes) {
val userMode = mode ?: ""
if (ircuser == null || !isKnownUser(ircuser) || !isValidChannelUserMode(userMode))
return
......@@ -313,12 +331,14 @@ class IrcChannel(
_userModes[ircuser] = _userModes.getOr(ircuser, "") + userMode
updateUsers()
}
}
override fun addUserMode(nick: String?, mode: String?) {
addUserMode(network().ircUser(nick), mode ?: "")
}
override fun removeUserMode(ircuser: IrcUser?, mode: String?) {
synchronized(_userModes) {
val userMode = mode ?: ""
if (ircuser == null || !isKnownUser(ircuser) || !isValidChannelUserMode(userMode))
return
......@@ -328,6 +348,7 @@ class IrcChannel(
.replace(userMode, "", ignoreCase = true)
updateUsers()
}
}
override fun removeUserMode(nick: String?, mode: String?) {
removeUserMode(network().ircUser(nick), mode ?: "")
......@@ -398,7 +419,7 @@ class IrcChannel(
live_updates.onNext(Unit)
}
private fun updateUsers() {
private fun updateUsers() = synchronized(_userModes) {
_userCount = _userModes.size
live_userModes.onNext(Unit)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment