diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt index 8e0a46f20d62472ecc259bd3b8cbde69d3311da6..0f4fd291d11aad2ff69d106c2501fcc45445a9e8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ToolbarFragment.kt @@ -171,6 +171,7 @@ class ToolbarFragment : ServiceBoundFragment() { UserInfoActivity.launch( requireContext(), bufferId = info.bufferId, + networkId = info.networkId, openBuffer = true ) } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt index 99fe0be42caddb5633968b6caab41a8298694f8e..9b8d20995df1dcd3511932b1e07028e929180812 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/messages/MessageListFragment.kt @@ -132,13 +132,14 @@ class MessageListFragment : ServiceBoundFragment() { UserInfoActivity.launch( requireContext(), openBuffer = false, + networkId = networkId, bufferId = bufferSyncer.find( bufferName = HostmaskHelper.nick(msg.original.sender), networkId = networkId, type = Buffer_Type.of(Buffer_Type.QueryBuffer) )?.let(BufferInfo::bufferId), - nick = HostmaskHelper.nick(msg.original.sender), - networkId = networkId + hostmask = msg.original.sender, + realname = msg.original.realName ) } } @@ -287,13 +288,14 @@ class MessageListFragment : ServiceBoundFragment() { UserInfoActivity.launch( requireContext(), openBuffer = false, + networkId = networkId, bufferId = bufferSyncer.find( bufferName = HostmaskHelper.nick(msg.sender), networkId = networkId, type = Buffer_Type.of(Buffer_Type.QueryBuffer) )?.let(BufferInfo::bufferId), - nick = HostmaskHelper.nick(msg.sender), - networkId = networkId + hostmask = msg.sender, + realname = msg.realName ) } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt index aaaed06dbf9b8dc16d707df8aa91c9a3a4be797f..2bb55426f7c97c917224fc85d97fd8db36220441 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/nicks/NickListFragment.kt @@ -186,7 +186,7 @@ class NickListFragment : ServiceBoundFragment() { networkId = networkId, type = Buffer_Type.of(Buffer_Type.QueryBuffer) )?.let(BufferInfo::bufferId), - nick = nick, + hostmask = nick, networkId = networkId ) } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserInfo.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserLiveMeta.kt similarity index 82% rename from app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserInfo.kt rename to app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserLiveMeta.kt index 11c089b78837c2c3ad04f1de4c1193f9dcf7c3d8..73abc62b92238efa92535b119283c41c1ce75fde 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserInfo.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserLiveMeta.kt @@ -26,20 +26,12 @@ import de.kuschku.libquassel.quassel.syncables.IrcUser import de.kuschku.libquassel.quassel.syncables.Network import de.kuschku.quasseldroid.viewmodel.data.BufferProps -data class IrcUserInfo( - val networkId: NetworkId, - val nick: String, - val user: String? = null, - val host: String? = null, - val account: String? = null, - val server: String? = null, - val realName: String? = null, - val isAway: Boolean? = false, - val awayMessage: String? = null, - val network: Network? = null, +data class IrcUserLiveMeta( + val meta: IrcUserMeta, val knownToCore: Boolean = false, - val info: BufferInfo? = null, val ircUser: IrcUser? = null, + val network: Network? = null, + val info: BufferInfo? = null, val channels: List<BufferProps> = emptyList(), val ignoreListItems: List<IgnoreListManager.IgnoreListItem> = emptyList() ) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserMeta.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserMeta.kt new file mode 100644 index 0000000000000000000000000000000000000000..b4f3ffbaa9a7e9fa59d0beaee6b07a605ac94967 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/IrcUserMeta.kt @@ -0,0 +1,37 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2023 Janne Mareike Koschinski + * Copyright (c) 2023 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.ui.info.user + +import de.kuschku.libquassel.protocol.NetworkId +import de.kuschku.libquassel.quassel.syncables.IrcUser + +data class IrcUserMeta( + val networkId: NetworkId, + val nick: String, + val knownToCore: Boolean = false, + val user: String? = null, + val host: String? = null, + val account: String? = null, + val server: String? = null, + val realName: String? = null, + val isAway: Boolean? = false, + val awayMessage: String? = null, + val ircUser: IrcUser? = null, +) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoActivity.kt index 16b0ac145674716da9e6f098f7cad2b49e086b56..c1d19c00ce2d6c60c82f8bffddcdd281d17bfed2 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoActivity.kt @@ -31,27 +31,32 @@ class UserInfoActivity : ServiceBoundSettingsActivity(UserInfoFragment()) { context: Context, openBuffer: Boolean, bufferId: BufferId? = null, - nick: String? = null, - networkId: NetworkId? = null - ) = context.startActivity(intent(context, openBuffer, bufferId, nick, networkId)) + networkId: NetworkId? = null, + hostmask: String? = null, + realname: String? = null + ) = context.startActivity(intent(context, openBuffer, bufferId, networkId, hostmask, realname)) fun intent( context: Context, openBuffer: Boolean, bufferId: BufferId? = null, - nick: String? = null, - networkId: NetworkId? = null + networkId: NetworkId? = null, + hostmask: String? = null, + realname: String? = null ) = Intent(context, UserInfoActivity::class.java).apply { putExtra("openBuffer", openBuffer) if (bufferId != null) { putExtra("bufferId", bufferId.id) } - if (nick != null) { - putExtra("nick", nick) - } if (networkId != null) { putExtra("networkId", networkId.id) } + if (hostmask != null) { + putExtra("hostmask", hostmask) + } + if (realname != null) { + putExtra("realname", realname) + } } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt index 766524dd5e936760147a86f97f4032fd0602593f..b41846198511340366a4b2b5bf7693a607ffe6a7 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt @@ -19,12 +19,14 @@ package de.kuschku.quasseldroid.ui.info.user +import android.content.Context import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle import android.text.SpannableString import android.view.LayoutInflater +import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.Button @@ -42,10 +44,9 @@ import de.kuschku.libquassel.protocol.Buffer_Type import de.kuschku.libquassel.protocol.Message_Type import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.quassel.BufferInfo -import de.kuschku.libquassel.quassel.syncables.BufferSyncer -import de.kuschku.libquassel.quassel.syncables.IgnoreListManager import de.kuschku.libquassel.quassel.syncables.IrcChannel import de.kuschku.libquassel.quassel.syncables.IrcUser +import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.util.Optional import de.kuschku.libquassel.util.helper.* import de.kuschku.libquassel.util.irc.HostmaskHelper @@ -59,6 +60,7 @@ import de.kuschku.quasseldroid.util.ShortcutCreationHelper import de.kuschku.quasseldroid.util.avatars.AvatarHelper import de.kuschku.quasseldroid.util.avatars.MatrixApi import de.kuschku.quasseldroid.util.avatars.MatrixAvatarInfo +import de.kuschku.quasseldroid.util.avatars.MatrixAvatarResponse import de.kuschku.quasseldroid.util.helper.* import de.kuschku.quasseldroid.util.irc.format.ContentFormatter import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer @@ -71,6 +73,7 @@ import de.kuschku.quasseldroid.viewmodel.data.BufferProps import de.kuschku.quasseldroid.viewmodel.data.BufferStatus import de.kuschku.quasseldroid.viewmodel.helper.EditorViewModelHelper import io.reactivex.Observable +import java.util.* import javax.inject.Inject class UserInfoFragment : ServiceBoundFragment() { @@ -157,15 +160,12 @@ class UserInfoFragment : ServiceBoundFragment() { val bufferId = BufferId(arguments?.getInt("bufferId") ?: -1) val networkId = NetworkId(arguments?.getInt("networkId") ?: -1) - val nickName = arguments?.getString("nick") + val hostMask = arguments?.getString("hostmask") ?: "" + val fallbackRealname = arguments?.getString("realname") ?: "" var currentBufferInfo: BufferInfo? = null var currentIrcUser: IrcUser? - fun updateShortcutVisibility() { - actionShortcut.visibleIf(currentBufferInfo != null) - } - val commonChannelsAdapter = ChannelAdapter() commonChannels.layoutManager = LinearLayoutManager(context) commonChannels.itemAnimator = DefaultItemAnimator() @@ -181,294 +181,278 @@ class UserInfoFragment : ServiceBoundFragment() { getColor(0, 0) } - combineLatest(modelHelper.connectedSession, - modelHelper.networks).safeSwitchMap { (sessionOptional, networks) -> - fun processUser(user: IrcUser, bufferSyncer: BufferSyncer? = null, info: BufferInfo? = null, - ignoreItems: List<IgnoreListManager.IgnoreListItem>? = null): Observable<Optional<IrcUserInfo>> { - actionShortcut.post(::updateShortcutVisibility) - return when { - user == IrcUser.NULL && info != null -> Observable.just(Optional.of(IrcUserInfo( - networkId = info.networkId, - nick = info.bufferName ?: "", + combineLatest(modelHelper.connectedSession, modelHelper.networks).safeSwitchMap { (sessionOptional, networks) -> + val session = sessionOptional?.orNull() + val ignoreListManager = session?.ignoreListManager + val bufferSyncer = session?.bufferSyncer + + val bufferInfo: Observable<Optional<BufferInfo>> = bufferSyncer?.liveBufferInfo(bufferId) + ?: Observable.just(Optional.empty()) + + val nick: Observable<String> = if (openBuffer == true) { + bufferInfo.map { (it.orNull()?.bufferName ?: "").ifEmpty { HostmaskHelper.nick(hostMask) } } + } else Observable.just(HostmaskHelper.nick(hostMask)) + + val user: Observable<IrcUser> = nick.safeSwitchMap { + networks[networkId]?.liveIrcUser(it) + ?.safeSwitchMap(IrcUser::updates) + ?: Observable.just(IrcUser.NULL) + } + + val ignoreRules = user.safeSwitchMap { + ignoreListManager?.liveMatchingRules(it.hostMask().ifEmpty { hostMask }) + ?: Observable.just(emptyList()) + } + + val userMeta = combineLatest(nick, user).map { (nick, user) -> + if (user == IrcUser.NULL) { + IrcUserMeta( + networkId = networkId, + nick = nick, + knownToCore = false, + user = HostmaskHelper.user(hostMask), + host = HostmaskHelper.host(hostMask), + realName = fallbackRealname, + ) + } else { + IrcUserMeta( + networkId = user.network().networkId(), + nick = user.nick(), knownToCore = true, - info = info - ))) - user == IrcUser.NULL -> Observable.just(Optional.empty()) - else -> { - fun buildUserInfo(channels: List<BufferProps>) = IrcUserInfo( - networkId = user.network().networkId(), - nick = user.nick(), - user = user.user(), - host = user.host(), - account = user.account(), - server = user.server(), - realName = user.realName(), - isAway = user.isAway(), - awayMessage = user.awayMessage(), - network = user.network(), - knownToCore = true, - info = info, - ircUser = user, - channels = channels.sortedBy { - IrcCaseMappers.unicode.toLowerCaseNullable(it.info.bufferName) - }, - ignoreListItems = ignoreItems.orEmpty() - ) + user = user.user(), + host = user.host(), + account = user.account(), + server = user.server(), + realName = user.realName(), + isAway = user.isAway(), + awayMessage = user.awayMessage(), + ircUser = user, + ) + } + } - if (user.channels().isEmpty()) { - Observable.just(Optional.of( - buildUserInfo(emptyList()) - )) - } else { - combineLatest(user.channels().map { channelName -> - user.network().liveIrcChannel( - channelName - ).safeSwitchMap { channel -> - channel.updates().map { - Optional.ofNullable( - bufferSyncer?.find( - bufferName = channelName, - networkId = user.network().networkId() - )?.let { info -> - val bufferStatus = - if (it == IrcChannel.NULL) BufferStatus.OFFLINE - else BufferStatus.ONLINE - val color = - if (bufferStatus == BufferStatus.ONLINE) colorAccent - else colorAway - val fallbackDrawable = colorContext.buildTextDrawable("#", color) - - BufferProps( - info = info, - network = user.network().networkInfo(), - description = it.topic(), - activity = Message_Type.of(), - bufferStatus = bufferStatus, - networkConnectionState = user.network().connectionState(), - fallbackDrawable = fallbackDrawable - ) - } + combineLatest(bufferInfo, userMeta, ignoreRules).safeSwitchMap { (bufferInfo, meta, ignoreItems) -> + val channels = if (meta.ircUser == null) { + Observable.just(emptyList()) + } else { + combineLatest(meta.ircUser.channels().map { channelName -> + meta.ircUser.network().liveIrcChannel(channelName).safeSwitchMap { channel -> + channel.updates().map { + Optional.ofNullable( + bufferSyncer?.find( + bufferName = channelName, + networkId = meta.ircUser.network().networkId() + )?.let { info -> + val bufferStatus = + if (it == IrcChannel.NULL) BufferStatus.OFFLINE + else BufferStatus.ONLINE + val color = + if (bufferStatus == BufferStatus.ONLINE) colorAccent + else colorAway + val fallbackDrawable = colorContext.buildTextDrawable("#", color) + + BufferProps( + info = info, + network = meta.ircUser.network().networkInfo(), + description = it.topic(), + activity = Message_Type.of(), + bufferStatus = bufferStatus, + networkConnectionState = meta.ircUser.network().connectionState(), + fallbackDrawable = fallbackDrawable ) } - } - }).map { - it.mapNotNull(Optional<BufferProps>::orNull) - }.map { - Optional.of(buildUserInfo(it)) + ) } } - } + }).map { it.mapNotNull(Optional<BufferProps>::orNull) } } - } - val session = sessionOptional?.orNull() - if (openBuffer == true) { - val bufferSyncer = session?.bufferSyncer - val bufferInfo = bufferSyncer?.bufferInfo(bufferId) - bufferInfo?.let { - networks[it.networkId]?.liveIrcUser(it.bufferName)?.safeSwitchMap(IrcUser::updates)?.safeSwitchMap { - processUser(it, bufferSyncer, bufferInfo) - } + channels.map { + IrcUserLiveMeta( + meta = meta, + network = meta.ircUser?.network(), + info = bufferInfo.orNull(), + channels = it.sortedBy { IrcCaseMappers.unicode.toLowerCaseNullable(it.info.bufferName) }, + ignoreListItems = ignoreItems.orEmpty() + ) } - } else { - val ignoreListManager = session?.ignoreListManager - - networks[networkId] - ?.liveIrcUser(nickName) - ?.safeSwitchMap(IrcUser::updates) - ?.safeSwitchMap { user -> - ignoreListManager?.liveMatchingRules(user.hostMask())?.map { - Pair(user, it) - } ?: Observable.just(Pair(user, emptyList())) - }?.safeSwitchMap { (user, ignoreItems) -> - processUser(user, - sessionOptional?.orNull()?.bufferSyncer, - ignoreItems = ignoreItems) - } - } ?: Observable.just(IrcUser.NULL).safeSwitchMap { user -> processUser(user, null, null) } + } }.toLiveData().observe(viewLifecycleOwner, Observer { - val user = it.orNull() - if (user != null) { - currentBufferInfo = user.info - currentIrcUser = user.ircUser - actionShortcut.visibleIf(currentBufferInfo != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - - avatar.post { - avatar.visibility = View.GONE - actualUrl = null - avatar.loadAvatars( - AvatarHelper.avatar(messageSettings, user, maxOf(avatar.width, avatar.height)), - crop = false - ) { model -> - avatar.visibility = View.VISIBLE - when (model) { - is String -> { - actualUrl = model - } - is Avatar.MatrixAvatar -> { - runInBackground { - matrixApi.avatarUrl(model.userId).execute().body()?.let { + val live = it + val user = it.meta + + currentBufferInfo = live.info + currentIrcUser = user.ircUser + actionShortcut.visibleIf(currentBufferInfo != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + avatar.post { + avatar.visibility = View.GONE + actualUrl = null + avatar.loadAvatars( + AvatarHelper.avatar(messageSettings, user, maxOf(avatar.width, avatar.height)), + crop = false + ) { model -> + avatar.visibility = View.VISIBLE + when (model) { + is String -> { + actualUrl = model + } + is Avatar.MatrixAvatar -> { + runInBackground { + matrixApi.avatarUrl(model.userId).execute().body() + ?.let<MatrixAvatarResponse, Unit> { it.avatarUrl?.let { val avatarInfo = MatrixAvatarInfo(it, model.size) val url = Uri.parse(avatarInfo.avatarUrl) - val imageUrl = matrixApi.avatarImage(server = url.host ?: "", - id = url.pathSegments.first()).request().url() + val imageUrl = matrixApi.avatarImage( + server = url.host ?: "", + id = url.pathSegments.first() + ).request().url() actualUrl = imageUrl.toString() } } - } } } } } - nick.text = ircFormatDeserializer.formatString(user.nick, messageSettings.colorizeMirc) - val (content, _) = contentFormatter.formatContent( - user.realName ?: "", - networkId = user.networkId - ) - realName.text = content - realName.visibleIf(!user.realName.isNullOrBlank() && user.realName != user.nick) - - awayMessage.text = user.awayMessage.nullIf { it.isNullOrBlank() } ?: SpannableString( - getString( - R.string.label_no_away_message)).apply { - setSpan(IrcItalicSpan(), 0, length, 0) - } - awayContainer.visibleIf(user.isAway == true) - - account.text = user.account - accountContainer.visibleIf(!user.account.isNullOrBlank()) - - val (userIdent, _) = contentFormatter.formatContent( - user.user ?: "", - networkId = user.networkId - ) - ident.text = userIdent - identContainer.visibleIf(userIdent.isNotBlank()) - - val (userHost, _) = contentFormatter.formatContent( - user.host ?: "", - networkId = user.networkId + } + nick.text = ircFormatDeserializer.formatString(user.nick, messageSettings.colorizeMirc) + val (content, _) = contentFormatter.formatContent( + user.realName ?: "", + networkId = user.networkId + ) + realName.text = content + realName.visibleIf(!user.realName.isNullOrBlank() && user.realName != user.nick) + awayMessage.text = user.awayMessage.nullIf<String?> { it.isNullOrBlank() } ?: SpannableString( + getString( + R.string.label_no_away_message ) - host.text = userHost - hostContainer.visibleIf(userHost.isNotBlank()) - - server.text = user.server - serverContainer.visibleIf(!user.server.isNullOrBlank()) - - actionWhois.visibleIf(user.knownToCore) - - actionQuery.setOnClickListener { view -> - modelHelper.connectedSession.value?.orNull()?.let { session -> - val info = session.bufferSyncer.find( - bufferName = user.nick, - networkId = user.networkId, - type = Buffer_Type.of(Buffer_Type.QueryBuffer) - ) - - if (info != null) { - ChatActivity.launch(view.context, bufferId = info.bufferId) - } else { - modelHelper.allBuffers.map { - listOfNotNull(it.find { - it.networkId == user.networkId && it.bufferName == user.nick - }) - }.filter { - it.isNotEmpty() - }.firstElement().toLiveData().observe(viewLifecycleOwner, Observer { - it?.firstOrNull()?.let { info -> - ChatActivity.launch(view.context, bufferId = info.bufferId) - } + ).apply { + setSpan(IrcItalicSpan(), 0, length, 0) + } + awayContainer.visibleIf(user.isAway == true) + account.text = user.account + accountContainer.visibleIf(!user.account.isNullOrBlank()) + val (userIdent, _) = contentFormatter.formatContent( + user.user ?: "", + networkId = user.networkId + ) + ident.text = userIdent + identContainer.visibleIf(userIdent.isNotBlank()) + val (userHost, _) = contentFormatter.formatContent( + user.host ?: "", + networkId = user.networkId + ) + host.text = userHost + hostContainer.visibleIf(userHost.isNotBlank()) + server.text = user.server + serverContainer.visibleIf(!user.server.isNullOrBlank()) + actionWhois.visibleIf(user.knownToCore) + actionQuery.setOnClickListener { view -> + modelHelper.connectedSession.value?.orNull()?.let<ISession, Unit> { session -> + val info = session.bufferSyncer.find( + bufferName = user.nick, + networkId = user.networkId, + type = Buffer_Type.of(Buffer_Type.QueryBuffer) + ) + + if (info != null) { + ChatActivity.launch(view.context, bufferId = info.bufferId) + } else { + modelHelper.allBuffers.map { + listOfNotNull(it.find { + it.networkId == user.networkId && it.bufferName == user.nick }) - - session.bufferSyncer.find( - networkId = user.networkId, - type = Buffer_Type.of(Buffer_Type.StatusBuffer) - )?.let { statusInfo -> - session.rpcHandler.sendInput(statusInfo, "/query ${user.nick}") + }.filter { + it.isNotEmpty() + }.firstElement().toLiveData().observe(viewLifecycleOwner, Observer { + it?.firstOrNull()?.let { info -> + ChatActivity.launch(view.context, bufferId = info.bufferId) } + }) + + session.bufferSyncer.find( + networkId = user.networkId, + type = Buffer_Type.of(Buffer_Type.StatusBuffer) + )?.let { statusInfo -> + session.rpcHandler.sendInput(statusInfo, "/query ${user.nick}") } } } - - var ignoreMenu: PopupMenu? = null - actionIgnore.setOnClickListener { view -> - PopupMenu(actionIgnore.context, actionIgnore).also { menu -> - ignoreMenu?.dismiss() - menu.menuInflater.inflate(R.menu.context_ignore, menu.menu) - for (ignoreItem in user.ignoreListItems) { - menu.menu.add(ignoreItem.ignoreRule).apply { - isCheckable = true - isChecked = ignoreItem.isActive - } + } + var ignoreMenu: PopupMenu? = null + actionIgnore.setOnClickListener { view -> + PopupMenu(actionIgnore.context, actionIgnore).also<PopupMenu> { menu -> + ignoreMenu?.dismiss() + menu.menuInflater.inflate(R.menu.context_ignore, menu.menu) + for (ignoreItem in live.ignoreListItems) { + menu.menu.add(ignoreItem.ignoreRule).apply<MenuItem> { + this.isCheckable = true + this.isChecked = ignoreItem.isActive } - menu.setOnMenuItemClickListener { - when { - it.itemId == R.id.action_create -> { - IgnoreListActivity.launch( - view.context, - addRule = HostmaskHelper.build(user.nick, user.user, user.host) - ) - menu.dismiss() - ignoreMenu = null - true - } - it.itemId == R.id.action_show -> { - IgnoreListActivity.launch( - view.context - ) - menu.dismiss() - ignoreMenu = null - true - } - it.isCheckable -> { - modelHelper.ignoreListManager.value?.orNull()?.requestToggleIgnoreRule(it.title.toString()) - true - } - else -> false + } + menu.setOnMenuItemClickListener { + when { + it.itemId == R.id.action_create -> { + IgnoreListActivity.launch( + view.context, + addRule = HostmaskHelper.build(user.nick, user.user, user.host) + ) + menu.dismiss() + ignoreMenu = null + true } + it.itemId == R.id.action_show -> { + IgnoreListActivity.launch( + view.context + ) + menu.dismiss() + ignoreMenu = null + true + } + it.isCheckable -> { + modelHelper.ignoreListManager.value?.orNull() + ?.requestToggleIgnoreRule(it.title.toString()) + true + } + else -> false } - menu.setOnDismissListener { - ignoreMenu = null - } - menu.show() } + menu.setOnDismissListener { + ignoreMenu = null + } + menu.show() } - - actionMention.setOnClickListener { view -> - ChatActivity.launch(view.context, sharedText = "${user.nick}: ") - } - - actionWhois.setOnClickListener { view -> - modelHelper.connectedSession { - it.orNull()?.let { session -> - session.bufferSyncer.find( - networkId = user.networkId, - type = Buffer_Type.of(Buffer_Type.StatusBuffer) - )?.let { statusInfo -> - session.rpcHandler.sendInput(statusInfo, "/whois ${user.nick} ${user.nick}") - } + } + actionMention.setOnClickListener { view -> + ChatActivity.launch(view.context, sharedText = "${user.nick}: ") + } + actionWhois.setOnClickListener { view -> + modelHelper.connectedSession { + it.orNull()?.let { session -> + session.bufferSyncer.find( + networkId = user.networkId, + type = Buffer_Type.of(Buffer_Type.StatusBuffer) + )?.let { statusInfo -> + session.rpcHandler.sendInput(statusInfo, "/whois ${user.nick} ${user.nick}") } } } - - actionShortcut.setOnClickListener { - this.context?.let { context -> - currentBufferInfo?.let { info -> - ShortcutCreationHelper.create( - context = context, - messageSettings = messageSettings, - accountId = accountId, - info = info, - ircUser = currentIrcUser - ) - } + } + actionShortcut.setOnClickListener { + context?.let<Context, Unit> { context -> + currentBufferInfo?.let { info -> + ShortcutCreationHelper.create( + context = context, + messageSettings = messageSettings, + accountId = accountId, + info = info, + ircUser = currentIrcUser + ) } } - - commonChannelsAdapter.submitList(user.channels) } + commonChannelsAdapter.submitList(live.channels) }) avatar.setOnClickListener { diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt index 12b501f18c82351c950511ced3839f2fa31e0914..058f04ca29bbb19c9a80050c1d46df7c9cf992a8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/avatars/AvatarHelper.kt @@ -25,7 +25,7 @@ import de.kuschku.libquassel.util.irc.IrcCaseMappers import de.kuschku.quasseldroid.persistence.models.MessageData import de.kuschku.quasseldroid.persistence.models.NotificationData import de.kuschku.quasseldroid.settings.MessageSettings -import de.kuschku.quasseldroid.ui.info.user.IrcUserInfo +import de.kuschku.quasseldroid.ui.info.user.IrcUserMeta import de.kuschku.quasseldroid.util.Patterns import de.kuschku.quasseldroid.util.backport.codec.Hex import de.kuschku.quasseldroid.util.helper.letIf @@ -61,7 +61,7 @@ object AvatarHelper { fun avatar(settings: MessageSettings, user: IrcUserItem, size: Int? = null) = avatar(settings, HostmaskHelper.user(user.hostmask), user.realname.toString(), null, size) - fun avatar(settings: MessageSettings, user: IrcUserInfo, size: Int? = null) = + fun avatar(settings: MessageSettings, user: IrcUserMeta, size: Int? = null) = avatar(settings, user.user ?: "", user.realName ?: "", null, size) fun avatar(settings: MessageSettings, user: IrcUser, size: Int? = null) = diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt index cb6c4fa0ae28a6fadbd96ec9e15d823944629ea9..8b55324800efdfce6bfec76f21782c0cc35a1200 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt @@ -73,7 +73,7 @@ class BufferSyncer constructor( fun bufferInfo(bufferId: BufferId) = _bufferInfos[bufferId] fun liveBufferInfo(bufferId: BufferId) = - live_bufferInfos.map { bufferInfo(bufferId) }.distinctUntilChanged() + live_bufferInfos.map { Optional.ofNullable(bufferInfo(bufferId)) }.distinctUntilChanged() fun bufferInfos(): Collection<BufferInfo> = _bufferInfos.values.toList() fun liveBufferInfos(): Observable<Map<BufferId, BufferInfo>> = live_bufferInfos.map { _bufferInfos.toMap() }