From e135871100583371242ae97f85e8ceb2f5e310b4 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Tue, 1 Jan 2019 22:53:07 +0100 Subject: [PATCH] Implement context-sensitive warnings for outdated cores --- .../quasseldroid/ui/chat/ChatActivity.kt | 42 +++------ .../chat/buffers/BufferViewConfigFragment.kt | 13 +++ .../quasseldroid/util/helper/ThemeHelper.kt | 8 +- .../quasseldroid/util/ui/WarningBarView.kt | 91 +++++++++++++++++++ app/src/main/res/drawable/ic_alert.xml | 9 ++ app/src/main/res/layout-land/layout_main.xml | 7 +- .../res/layout-sw600dp-land/layout_main.xml | 7 +- .../main/res/layout/fragment_chat_list.xml | 6 ++ app/src/main/res/layout/layout_main.xml | 7 +- ...tion_status.xml => widget_warning_bar.xml} | 16 ++-- app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/styles_widgets.xml | 12 +++ .../viewmodel/QuasselViewModel.kt | 5 + 13 files changed, 179 insertions(+), 46 deletions(-) create mode 100644 app/src/main/java/de/kuschku/quasseldroid/util/ui/WarningBarView.kt create mode 100644 app/src/main/res/drawable/ic_alert.xml rename app/src/main/res/layout/{widget_connection_status.xml => widget_warning_bar.xml} (77%) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt index 41fa189d7..e9229a9d9 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt @@ -35,11 +35,8 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.EditText -import android.widget.LinearLayout -import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.ActionBarDrawerToggle -import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.Toolbar import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat @@ -97,9 +94,9 @@ import de.kuschku.quasseldroid.util.service.ServiceBoundActivity import de.kuschku.quasseldroid.util.ui.DragInterceptBottomSheetBehavior import de.kuschku.quasseldroid.util.ui.MaterialContentLoadingProgressBar import de.kuschku.quasseldroid.util.ui.NickCountDrawable +import de.kuschku.quasseldroid.util.ui.WarningBarView import de.kuschku.quasseldroid.viewmodel.EditorViewModel import de.kuschku.quasseldroid.viewmodel.data.BufferData -import me.zhanghai.android.materialprogressbar.MaterialProgressBar import org.threeten.bp.Instant import org.threeten.bp.ZoneId import org.threeten.bp.format.DateTimeFormatter @@ -121,16 +118,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc lateinit var progressBar: MaterialContentLoadingProgressBar @BindView(R.id.connection_status) - lateinit var connectionStatusDisplay: LinearLayout - - @BindView(R.id.connection_status_icon) - lateinit var connectionStatusDisplayIcon: AppCompatImageView - - @BindView(R.id.connection_status_progress) - lateinit var connectionStatusDisplayProgress: MaterialProgressBar - - @BindView(R.id.connection_status_text) - lateinit var connectionStatusDisplayText: TextView + lateinit var connectionStatusDisplay: WarningBarView @BindView(R.id.autocomplete_list) lateinit var autoCompleteList: RecyclerView @@ -643,28 +631,22 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc ConnectionState.CLOSED -> { progressBar.visibility = View.INVISIBLE - connectionStatusDisplay.visibility = View.VISIBLE - connectionStatusDisplayText.text = getString(R.string.label_status_disconnected) - connectionStatusDisplayIcon.visibility = View.VISIBLE - connectionStatusDisplayProgress.visibility = View.GONE + connectionStatusDisplay.setMode(WarningBarView.MODE_ICON) + connectionStatusDisplay.setText(getString(R.string.label_status_disconnected)) } ConnectionState.CONNECTING -> { progressBar.visibility = View.VISIBLE progressBar.isIndeterminate = true - connectionStatusDisplay.visibility = View.VISIBLE - connectionStatusDisplayText.text = getString(R.string.label_status_connecting) - connectionStatusDisplayIcon.visibility = View.GONE - connectionStatusDisplayProgress.visibility = View.VISIBLE + connectionStatusDisplay.setMode(WarningBarView.MODE_PROGRESS) + connectionStatusDisplay.setText(getString(R.string.label_status_connecting)) } ConnectionState.HANDSHAKE -> { progressBar.visibility = View.VISIBLE progressBar.isIndeterminate = true - connectionStatusDisplay.visibility = View.VISIBLE - connectionStatusDisplayText.text = getString(R.string.label_status_handshake) - connectionStatusDisplayIcon.visibility = View.GONE - connectionStatusDisplayProgress.visibility = View.VISIBLE + connectionStatusDisplay.setMode(WarningBarView.MODE_PROGRESS) + connectionStatusDisplay.setText(getString(R.string.label_status_handshake)) } ConnectionState.INIT -> { progressBar.visibility = View.VISIBLE @@ -673,14 +655,12 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc progressBar.progress = progress progressBar.max = max - connectionStatusDisplay.visibility = View.VISIBLE - connectionStatusDisplayText.text = getString(R.string.label_status_init) - connectionStatusDisplayIcon.visibility = View.GONE - connectionStatusDisplayProgress.visibility = View.VISIBLE + connectionStatusDisplay.setMode(WarningBarView.MODE_PROGRESS) + connectionStatusDisplay.setText(getString(R.string.label_status_init)) } ConnectionState.CONNECTED -> { progressBar.visibility = View.INVISIBLE - connectionStatusDisplay.visibility = View.GONE + connectionStatusDisplay.setMode(WarningBarView.MODE_NONE) } } }) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt index 8bfeb1dac..f9a396634 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt @@ -37,6 +37,7 @@ import de.kuschku.libquassel.protocol.Buffer_Activity import de.kuschku.libquassel.protocol.Buffer_Type import de.kuschku.libquassel.protocol.Message_Type import de.kuschku.libquassel.quassel.BufferInfo +import de.kuschku.libquassel.quassel.ExtendedFeature import de.kuschku.libquassel.quassel.syncables.BufferViewConfig import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork import de.kuschku.libquassel.util.flag.hasFlag @@ -55,6 +56,7 @@ import de.kuschku.quasseldroid.util.avatars.AvatarHelper import de.kuschku.quasseldroid.util.helper.* import de.kuschku.quasseldroid.util.irc.format.IrcFormatDeserializer import de.kuschku.quasseldroid.util.service.ServiceBoundFragment +import de.kuschku.quasseldroid.util.ui.WarningBarView import de.kuschku.quasseldroid.viewmodel.data.BufferHiddenState import de.kuschku.quasseldroid.viewmodel.data.BufferListItem import de.kuschku.quasseldroid.viewmodel.data.BufferState @@ -71,6 +73,9 @@ class BufferViewConfigFragment : ServiceBoundFragment() { @BindView(R.id.chatList) lateinit var chatList: RecyclerView + @BindView(R.id.feature_context_bufferactivitysync) + lateinit var featureContextBufferactivitysync: WarningBarView + @Inject lateinit var appearanceSettings: AppearanceSettings @@ -279,6 +284,14 @@ class BufferViewConfigFragment : ServiceBoundFragment() { hasRestoredChatListState = true } } + + viewModel.features.toLiveData().observe(this, Observer { + featureContextBufferactivitysync.setMode( + if (it.hasFeature(ExtendedFeature.BufferActivitySync)) WarningBarView.MODE_NONE + else WarningBarView.MODE_ICON + ) + }) + combineLatest(viewModel.bufferList, viewModel.expandedNetworks, viewModel.selectedBuffer).toLiveData().switchMapNotNull { a -> diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/helper/ThemeHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/helper/ThemeHelper.kt index bf4d6ff1a..f5ff79eb8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/helper/ThemeHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/helper/ThemeHelper.kt @@ -28,7 +28,9 @@ inline fun <R> Resources.Theme.styledAttributes(vararg attributes: Int, f: Typed } inline fun <R> TypedArray.use(block: (TypedArray) -> R): R { - val result = block(this) - recycle() - return result + try { + return block(this) + } finally { + recycle() + } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/WarningBarView.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/WarningBarView.kt new file mode 100644 index 000000000..e94d65615 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/WarningBarView.kt @@ -0,0 +1,91 @@ +package de.kuschku.quasseldroid.util.ui + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.LinearLayout +import android.widget.TextView +import androidx.annotation.IntDef +import androidx.annotation.StringRes +import androidx.appcompat.widget.AppCompatImageView +import butterknife.BindView +import butterknife.ButterKnife +import de.kuschku.quasseldroid.R +import de.kuschku.quasseldroid.util.helper.use + +class WarningBarView : LinearLayout { + @BindView(R.id.icon) + lateinit var icon: AppCompatImageView + + @BindView(R.id.progress) + lateinit var progress: View + + @BindView(R.id.text) + lateinit var text: TextView + + constructor(context: Context) : + this(context, null) + + constructor(context: Context, attrs: AttributeSet?) : + this(context, attrs, 0) + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : + super(context, attrs, defStyleAttr) { + + LayoutInflater.from(context).inflate(R.layout.widget_warning_bar, this, true) + ButterKnife.bind(this) + + context.theme.obtainStyledAttributes(attrs, R.styleable.WarningBarView, 0, 0).use { + if (it.hasValue(R.styleable.WarningBarView_icon)) + icon.setImageDrawable(it.getDrawable(R.styleable.WarningBarView_icon)) + + if (it.hasValue(R.styleable.WarningBarView_text)) + text.text = it.getString(R.styleable.WarningBarView_text) + + if (it.hasValue(R.styleable.WarningBarView_mode)) + setMode(it.getInt(R.styleable.WarningBarView_mode, MODE_NONE)) + } + } + + fun setText(content: String) { + text.text = content + } + + fun setText(@StringRes content: Int) { + text.setText(content) + } + + fun setMode(@WarningMode mode: Int) { + when (mode) { + MODE_NONE -> { + visibility = View.GONE + } + MODE_TEXT -> { + visibility = View.VISIBLE + icon.visibility = View.GONE + progress.visibility = View.GONE + } + MODE_ICON -> { + visibility = View.VISIBLE + icon.visibility = View.VISIBLE + progress.visibility = View.GONE + } + MODE_PROGRESS -> { + visibility = View.VISIBLE + icon.visibility = View.GONE + progress.visibility = View.VISIBLE + } + } + } + + @IntDef(value = [MODE_NONE, MODE_TEXT, MODE_ICON, MODE_PROGRESS]) + annotation class WarningMode + + companion object { + const val MODE_NONE = 0 + const val MODE_TEXT = 1 + const val MODE_ICON = 2 + const val MODE_PROGRESS = 3 + } +} diff --git a/app/src/main/res/drawable/ic_alert.xml b/app/src/main/res/drawable/ic_alert.xml new file mode 100644 index 000000000..1a1c6a166 --- /dev/null +++ b/app/src/main/res/drawable/ic_alert.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#000" + android:pathData="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" /> +</vector> diff --git a/app/src/main/res/layout-land/layout_main.xml b/app/src/main/res/layout-land/layout_main.xml index a25bb7be2..cac102c65 100644 --- a/app/src/main/res/layout-land/layout_main.xml +++ b/app/src/main/res/layout-land/layout_main.xml @@ -44,7 +44,12 @@ android:layout_height="match_parent" tools:layout="@layout/fragment_messages" /> - <include layout="@layout/widget_connection_status" /> + <de.kuschku.quasseldroid.util.ui.WarningBarView + android:id="@+id/connection_status" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:icon="@drawable/ic_disconnected" + app:mode="none" /> </FrameLayout> <androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/res/layout-sw600dp-land/layout_main.xml b/app/src/main/res/layout-sw600dp-land/layout_main.xml index cf5d0c86b..475bb3877 100644 --- a/app/src/main/res/layout-sw600dp-land/layout_main.xml +++ b/app/src/main/res/layout-sw600dp-land/layout_main.xml @@ -50,7 +50,12 @@ android:layout_height="match_parent" tools:layout="@layout/fragment_messages" /> - <include layout="@layout/widget_connection_status" /> + <de.kuschku.quasseldroid.util.ui.WarningBarView + android:id="@+id/connection_status" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:icon="@drawable/ic_disconnected" + app:mode="none" /> </FrameLayout> <androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/res/layout/fragment_chat_list.xml b/app/src/main/res/layout/fragment_chat_list.xml index 6706a0b83..4de32ee07 100644 --- a/app/src/main/res/layout/fragment_chat_list.xml +++ b/app/src/main/res/layout/fragment_chat_list.xml @@ -48,6 +48,12 @@ </com.google.android.material.appbar.AppBarLayout> + <de.kuschku.quasseldroid.util.ui.WarningBarView + android:id="@+id/feature_context_bufferactivitysync" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:icon="@drawable/ic_alert" + app:text="@string/label_feature_context_bufferactivitysync" /> <de.kuschku.quasseldroid.util.ui.fastscroll.views.FastScrollRecyclerView android:id="@+id/chatList" diff --git a/app/src/main/res/layout/layout_main.xml b/app/src/main/res/layout/layout_main.xml index 9f37466ae..9bcdc4822 100644 --- a/app/src/main/res/layout/layout_main.xml +++ b/app/src/main/res/layout/layout_main.xml @@ -50,7 +50,12 @@ android:layout_height="match_parent" tools:layout="@layout/fragment_messages" /> - <include layout="@layout/widget_connection_status" /> + <de.kuschku.quasseldroid.util.ui.WarningBarView + android:id="@+id/connection_status" + android:layout_width="match_parent" + android:layout_height="wrap_content" + app:icon="@drawable/ic_disconnected" + app:mode="none" /> </FrameLayout> diff --git a/app/src/main/res/layout/widget_connection_status.xml b/app/src/main/res/layout/widget_warning_bar.xml similarity index 77% rename from app/src/main/res/layout/widget_connection_status.xml rename to app/src/main/res/layout/widget_warning_bar.xml index 1414ff1e9..29a35c059 100644 --- a/app/src/main/res/layout/widget_connection_status.xml +++ b/app/src/main/res/layout/widget_warning_bar.xml @@ -2,7 +2,6 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/connection_status" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?colorBackgroundSnackbar" @@ -11,21 +10,20 @@ android:paddingTop="6dp" android:paddingRight="16dp" android:paddingBottom="6dp" - android:visibility="gone" - android:theme="?attr/actionBarTheme" - tools:visibility="visible"> + android:theme="?attr/actionBarTheme"> <androidx.appcompat.widget.AppCompatImageView - android:id="@+id/connection_status_icon" + android:id="@+id/icon" android:layout_width="20dp" android:layout_height="20dp" - app:srcCompat="@drawable/ic_disconnected" + android:layout_gravity="center_vertical" android:visibility="gone" app:tint="?android:textColorPrimary" + tools:srcCompat="@drawable/ic_alert" tools:visibility="visible" /> <me.zhanghai.android.materialprogressbar.MaterialProgressBar - android:id="@+id/connection_status_progress" + android:id="@+id/progress" style="@style/Widget.MaterialProgressBar.ProgressBar" android:layout_width="20dp" android:layout_height="20dp" @@ -34,12 +32,12 @@ app:mpb_indeterminateTint="?android:textColorPrimary" /> <TextView - android:id="@+id/connection_status_text" + android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:textColor="?android:textColorPrimary" - tools:text="@string/label_status_connecting" /> + tools:text="@string/label_feature_context_bufferactivitysync" /> </LinearLayout> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c49f211a..cd7b72e6a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -137,6 +137,8 @@ <string name="label_feature_richmessages">Required for seeing real names or IRCv3 or Gravatar avatars in messages</string> <string name="label_feature_backlogfiltertype">Required for receiving past notifications after connecting</string> + <string name="label_feature_context_bufferactivitysync">Quasseldroid cannot highlight unread chats. Upgrade your core to Quassel v0.13 to resolve this.</string> + <string name="notification_channel_background" translatable="false">background</string> <string name="notification_channel_connection_title">Connection</string> <string name="notification_channel_highlight" translatable="false">highlight</string> diff --git a/app/src/main/res/values/styles_widgets.xml b/app/src/main/res/values/styles_widgets.xml index 4e88a61ea..feef8d4c3 100644 --- a/app/src/main/res/values/styles_widgets.xml +++ b/app/src/main/res/values/styles_widgets.xml @@ -335,4 +335,16 @@ <style name="Widget.NavigationDrawerLayout" parent=""> <item name="insetBackground">#4000</item> </style> + + <!-- NavigationDrawerLayout --> + <declare-styleable name="WarningBarView"> + <attr name="icon" format="reference" /> + <attr name="text" format="string" /> + <attr name="mode"> + <enum name="none" value="0" /> + <enum name="text" value="1" /> + <enum name="icon" value="2" /> + <enum name="progress" value="3" /> + </attr> + </declare-styleable> </resources> diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt index 3b728f75a..843b2b583 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt @@ -21,8 +21,10 @@ package de.kuschku.quasseldroid.viewmodel import androidx.lifecycle.ViewModel import de.kuschku.libquassel.connection.ConnectionState +import de.kuschku.libquassel.connection.Features import de.kuschku.libquassel.protocol.* import de.kuschku.libquassel.quassel.BufferInfo +import de.kuschku.libquassel.quassel.QuasselFeatures import de.kuschku.libquassel.quassel.syncables.* import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork import de.kuschku.libquassel.session.Backend @@ -83,6 +85,9 @@ class QuasselViewModel : ViewModel() { val sessionManager = backend.mapMap(Backend::sessionManager) val session = sessionManager.mapSwitchMap(SessionManager::session) val rpcHandler = session.mapMapNullable(ISession::rpcHandler) + val features = session.mapMap(ISession::features) + .mapMap(Features::negotiated) + .mapOrElse(QuasselFeatures.empty()) val connectionProgress = sessionManager.mapSwitchMap(SessionManager::connectionProgress) .mapOrElse(Triple(ConnectionState.DISCONNECTED, 0, 0)) -- GitLab