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 068628cf563eefa088d8628cdf75741068140ad1..1eea6bbde98ba228e07a74152a2b693218920f94 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 @@ -21,8 +21,12 @@ package de.kuschku.quasseldroid.ui.chat.buffers import android.os.Bundle import android.os.Parcelable +import android.text.Editable +import android.text.TextWatcher import android.view.* import android.widget.AdapterView +import android.widget.EditText +import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatSpinner import androidx.appcompat.widget.Toolbar import androidx.lifecycle.Observer @@ -76,6 +80,15 @@ class BufferViewConfigFragment : ServiceBoundFragment() { @BindView(R.id.feature_context_bufferactivitysync) lateinit var featureContextBufferActivitySync: WarningBarView + @BindView(R.id.buffer_search) + lateinit var bufferSearch: EditText + + @BindView(R.id.buffer_search_clear) + lateinit var bufferSearchClear: AppCompatImageButton + + @BindView(R.id.buffer_search_container) + lateinit var bufferSearchContainer: ViewGroup + @Inject lateinit var appearanceSettings: AppearanceSettings @@ -469,6 +482,26 @@ class BufferViewConfigFragment : ServiceBoundFragment() { hasSetBufferViewConfigId = false }) + viewModel.bufferViewConfig.toLiveData().observe(this, Observer { + val visible = it.orNull()?.showSearch() ?: false + bufferSearchContainer.visibleIf(visible) + if (!visible) bufferSearch.setText("") + }) + + bufferSearch.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable) { + viewModel.bufferSearch.onNext(s.toString()) + } + + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) = Unit + }) + + bufferSearchClear.setOnClickListener { + bufferSearch.setText("") + } + return view } diff --git a/app/src/main/res/layout/fragment_chat_list.xml b/app/src/main/res/layout/fragment_chat_list.xml index cb69b2eb1aa9d281ecb83ae8db0c22f85f6c710c..647c026ba93c27c7ee031b5caf97ac3f15585297 100644 --- a/app/src/main/res/layout/fragment_chat_list.xml +++ b/app/src/main/res/layout/fragment_chat_list.xml @@ -32,20 +32,71 @@ <androidx.appcompat.widget.Toolbar android:id="@+id/chatListToolbar" android:layout_width="match_parent" - android:layout_height="?attr/actionBarSize" - app:contentInsetStartWithNavigation="0dp" + android:layout_height="wrap_content" + android:minHeight="?attr/actionBarSize" + app:contentInsetLeft="0dip" + app:contentInsetStart="0dip" + app:contentInsetStartWithNavigation="0dip" app:popupTheme="?attr/actionBarPopupTheme"> - <androidx.appcompat.widget.AppCompatSpinner - android:id="@+id/chatListSpinner" - style="@style/Widget.FullWidthSpinner" - android:layout_width="fill_parent" - android:layout_height="match_parent" - app:popupTheme="?attr/actionBarPopupTheme" - tools:listitem="@layout/widget_spinner_item_toolbar" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <androidx.appcompat.widget.AppCompatSpinner + android:id="@+id/chatListSpinner" + style="@style/Widget.FullWidthSpinner" + android:layout_width="fill_parent" + android:layout_height="match_parent" + app:popupTheme="?attr/actionBarPopupTheme" + tools:listitem="@layout/widget_spinner_item_toolbar" /> + </LinearLayout> </androidx.appcompat.widget.Toolbar> + <androidx.cardview.widget.CardView + android:id="@+id/buffer_search_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="6dp" + android:layout_marginRight="6dp" + android:layout_marginBottom="6dp"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <EditText + android:id="@+id/buffer_search" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:background="@android:color/transparent" + android:hint="@string/label_search_buffer" + android:imeOptions="actionSearch" + android:inputType="textNoSuggestions" + android:lines="1" + android:minHeight="40dp" + android:paddingLeft="8dp" + android:paddingRight="8dp" + android:textColor="?colorTextPrimary" + android:textColorHint="?colorTextSecondary" + android:textSize="16sp" /> + + <androidx.appcompat.widget.AppCompatImageButton + android:id="@+id/buffer_search_clear" + android:layout_width="40dp" + android:layout_height="match_parent" + android:background="?selectableItemBackgroundBorderless" + app:srcCompat="@drawable/ic_close" + app:tint="?colorTextSecondary" /> + + </LinearLayout> + + </androidx.cardview.widget.CardView> + </com.google.android.material.appbar.AppBarLayout> <de.kuschku.quasseldroid.util.ui.WarningBarView diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c89d1515a8fdbf61a62d9e202dfa9d4d8a2f09b2..ca13816f425b7573904968c0407a1ecceec55ccf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -93,6 +93,7 @@ <string name="label_query_long">Open private chat with user</string> <string name="label_rename">Rename</string> <string name="label_save">Save</string> + <string name="label_search_buffer">Search…</string> <string name="label_select">Select</string> <string name="label_send">Send</string> <string name="label_set_default">Set Default</string> 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 bfa9a51718e929d48f3f203d9921791fff7ec306..85492ab33392fdce2585991c64afbcf294948317 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt @@ -62,6 +62,8 @@ class QuasselViewModel : ViewModel() { return result.size } + val bufferSearch = BehaviorSubject.createDefault("") + val expandedMessages = BehaviorSubject.createDefault(emptySet<MsgId>()) val buffer = BehaviorSubject.createDefault(Int.MAX_VALUE) @@ -111,7 +113,7 @@ class QuasselViewModel : ViewModel() { val bufferViewConfig = bufferViewManager.flatMapSwitchMap { manager -> bufferViewConfigId.map { id -> Optional.ofNullable(manager.bufferViewConfig(id)) - } + }.mapSwitchMap(BufferViewConfig::liveUpdates) } val errors = sessionManager.switchMap { @@ -350,8 +352,8 @@ class QuasselViewModel : ViewModel() { } val bufferList: Observable<Pair<BufferViewConfig?, List<BufferProps>>> = - combineLatest(session, bufferViewConfig, showHidden) - .switchMap { (sessionOptional, configOptional, showHiddenRaw) -> + combineLatest(session, bufferViewConfig, showHidden, bufferSearch) + .switchMap { (sessionOptional, configOptional, showHiddenRaw, bufferSearch) -> val session = sessionOptional.orNull() val bufferSyncer = session?.bufferSyncer val showHidden = showHiddenRaw ?: false @@ -370,6 +372,10 @@ class QuasselViewModel : ViewModel() { fun transformIds(ids: Collection<BufferId>, state: BufferHiddenState) = ids.asSequence().mapNotNull { id -> bufferSyncer.bufferInfo(id) + }.filter { + bufferSearch.isBlank() || + it.type.hasFlag(Buffer_Type.StatusBuffer) || + it.bufferName?.contains(bufferSearch, ignoreCase = true) == true }.filter { currentConfig.networkId() <= 0 || currentConfig.networkId() == it.networkId }.filter { @@ -507,7 +513,7 @@ class QuasselViewModel : ViewModel() { } bufferSyncer.liveBufferInfos().switchMap { - val buffers = if (showHidden) { + val buffers = if (showHidden || bufferSearch.isNotBlank()) { transformIds(ids, BufferHiddenState.VISIBLE) + transformIds(temp - ids, BufferHiddenState.HIDDEN_TEMPORARY) + transformIds(perm - temp - ids, BufferHiddenState.HIDDEN_PERMANENT) +