From 07747a4096be741a3a3b4eb286a4d1f163aea1ea Mon Sep 17 00:00:00 2001 From: Dmytro Date: Tue, 10 Mar 2026 00:38:58 +0100 Subject: [PATCH 1/3] feat: add grid view to assistant selector --- .../ui/adapter/AssistantSelectorAdapter.kt | 23 ++++-- .../component/AssistantSelectorBottomSheet.kt | 36 ++++++++- .../AssistantSelectorCategoryViewHolder.kt | 7 +- .../AssistantSelectorGridItemViewHolder.kt | 42 ++++++++++ .../com/wstxda/switchai/utils/Constants.kt | 4 + .../layout/list_item_assistant_grid_view.xml | 76 +++++++++++++++++++ app/src/main/res/values-ar/strings.xml | 6 ++ app/src/main/res/values-ko/strings.xml | 6 ++ app/src/main/res/values-pt-rBR/strings.xml | 6 ++ app/src/main/res/values/strings.xml | 6 ++ app/src/main/res/xml/main_preferences.xml | 18 +++++ 11 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorGridItemViewHolder.kt create mode 100644 app/src/main/res/layout/list_item_assistant_grid_view.xml diff --git a/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt b/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt index 7193ef2..e4c8844 100644 --- a/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt +++ b/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt @@ -5,9 +5,11 @@ import android.view.ViewGroup import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.wstxda.switchai.databinding.ListItemAssistantCategoryBinding +import com.wstxda.switchai.databinding.ListItemAssistantGridViewBinding import com.wstxda.switchai.databinding.ListItemAssistantViewBinding import com.wstxda.switchai.databinding.ListItemReorderTipBinding import com.wstxda.switchai.ui.viewholder.AssistantSelectorCategoryViewHolder +import com.wstxda.switchai.ui.viewholder.AssistantSelectorGridItemViewHolder import com.wstxda.switchai.ui.viewholder.AssistantSelectorItemViewHolder import com.wstxda.switchai.ui.viewholder.ReorderTipViewHolder import com.wstxda.switchai.utils.Constants @@ -17,13 +19,15 @@ class AssistantSelectorAdapter( private val onAssistantClicked: (String) -> Unit, private val onPinClicked: (String) -> Unit, private val onDismissTipClicked: () -> Unit, + val isGridMode: Boolean = false, ) : ListAdapter( AssistantSelectorDiffCallback() ) { override fun getItemViewType(position: Int) = when (getItem(position)) { is AssistantSelectorRecyclerView.CategoryHeader -> Constants.VIEW_TYPE_CATEGORY_HEADER - is AssistantSelectorRecyclerView.AssistantSelector -> Constants.VIEW_TYPE_ASSISTANT_ITEM + is AssistantSelectorRecyclerView.AssistantSelector -> + if (isGridMode) Constants.VIEW_TYPE_ASSISTANT_GRID_ITEM else Constants.VIEW_TYPE_ASSISTANT_ITEM is AssistantSelectorRecyclerView.ReorderTip -> Constants.VIEW_TYPE_REORDER_TIP } @@ -42,6 +46,13 @@ class AssistantSelectorAdapter( AssistantSelectorItemViewHolder(binding) } + Constants.VIEW_TYPE_ASSISTANT_GRID_ITEM -> { + val binding = ListItemAssistantGridViewBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + AssistantSelectorGridItemViewHolder(binding) + } + Constants.VIEW_TYPE_REORDER_TIP -> { val binding = ListItemReorderTipBinding.inflate( LayoutInflater.from(parent.context), parent, false @@ -55,12 +66,14 @@ class AssistantSelectorAdapter( override fun onBindViewHolder(holder: RecyclerView.ViewHolder, pos: Int) { when (val item = getItem(pos)) { is AssistantSelectorRecyclerView.CategoryHeader -> (holder as AssistantSelectorCategoryViewHolder).bind( - item + item, isGridMode ) - is AssistantSelectorRecyclerView.AssistantSelector -> (holder as AssistantSelectorItemViewHolder).bind( - item, onAssistantClicked, onPinClicked - ) + is AssistantSelectorRecyclerView.AssistantSelector -> when (holder) { + is AssistantSelectorItemViewHolder -> holder.bind(item, onAssistantClicked, onPinClicked) + is AssistantSelectorGridItemViewHolder -> holder.bind(item, onAssistantClicked, onPinClicked) + else -> Unit + } is AssistantSelectorRecyclerView.ReorderTip -> (holder as ReorderTipViewHolder).bind( onDismissTipClicked diff --git a/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt b/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt index 9defb57..34b780b 100644 --- a/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt +++ b/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt @@ -11,6 +11,7 @@ import androidx.core.view.isInvisible import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.fragment.app.viewModels +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -42,12 +43,19 @@ class AssistantSelectorBottomSheet : BaseBottomSheet openAssistant(assistantKey) viewModel.updateRecentlyUsedAssistants(assistantKey) @@ -70,9 +79,28 @@ class AssistantSelectorBottomSheet : BaseBottomSheet 1 + else -> Constants.GRID_SPAN_COUNT + } + } + } + val tv = android.util.TypedValue() + context.theme.resolveAttribute(android.R.attr.dialogPreferredPadding, tv, true) + val dialogPadding = android.util.TypedValue.complexToDimensionPixelSize(tv.data, resources.displayMetrics) + val itemMargin = (3 * resources.displayMetrics.density).toInt() + val horizontalPadding = dialogPadding - itemMargin + setPadding(horizontalPadding, 0, horizontalPadding, paddingBottom) + layoutManager = gridLayoutManager + } else { + layoutManager = LinearLayoutManager(context) + } adapter = assistantSelectorAdapter } } @@ -120,7 +148,9 @@ class AssistantSelectorBottomSheet : BaseBottomSheet) -> Unit - ) : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) { + ) : ItemTouchHelper.SimpleCallback( + ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT, 0 + ) { override fun getDragDirs( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder diff --git a/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorCategoryViewHolder.kt b/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorCategoryViewHolder.kt index 5d189b4..13f0a26 100644 --- a/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorCategoryViewHolder.kt +++ b/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorCategoryViewHolder.kt @@ -8,8 +8,13 @@ class AssistantSelectorCategoryViewHolder( private val binding: ListItemAssistantCategoryBinding ) : RecyclerView.ViewHolder(binding.root) { - fun bind(categoryHeader: AssistantSelectorRecyclerView.CategoryHeader) { + fun bind(categoryHeader: AssistantSelectorRecyclerView.CategoryHeader, isGridMode: Boolean = false) { binding.categoryTitleTextView.text = categoryHeader.title binding.categoryCountChip.text = categoryHeader.count.toString() + val density = binding.root.resources.displayMetrics.density + val startPadding = ((if (isGridMode) 8 else 40) * density).toInt() + val endPadding = ((if (isGridMode) 8 else 28) * density).toInt() + val topPadding = (12 * density).toInt() + binding.root.setPadding(startPadding, topPadding, endPadding, 0) } } \ No newline at end of file diff --git a/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorGridItemViewHolder.kt b/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorGridItemViewHolder.kt new file mode 100644 index 0000000..e0fbd40 --- /dev/null +++ b/app/src/main/java/com/wstxda/switchai/ui/viewholder/AssistantSelectorGridItemViewHolder.kt @@ -0,0 +1,42 @@ +package com.wstxda.switchai.ui.viewholder + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.wstxda.switchai.R +import com.wstxda.switchai.databinding.ListItemAssistantGridViewBinding +import com.wstxda.switchai.ui.adapter.AssistantSelectorRecyclerView +import com.wstxda.switchai.ui.utils.VibrationService.buttonVibration + +class AssistantSelectorGridItemViewHolder( + private val binding: ListItemAssistantGridViewBinding, +) : RecyclerView.ViewHolder(binding.root) { + + fun bind( + wrapper: AssistantSelectorRecyclerView.AssistantSelector, + onAssistantClicked: (String) -> Unit, + onPinClicked: (String) -> Unit, + ) { + val item = wrapper.assistantItem + binding.assistantCheckedTextView.text = item.name + + val isItemEnabled = item.isInstalled + binding.pinButton.visibility = if (isItemEnabled) View.VISIBLE else View.GONE + + binding.assistantIcon.setImageResource( + if (item.iconRes != 0) item.iconRes else R.drawable.ic_assistant + ) + + binding.pinButton.setIconResource( + if (item.isPinned) R.drawable.ic_pin_filled else R.drawable.ic_pin_outline + ) + + binding.pinButton.setOnClickListener { + onPinClicked(item.key) + it.context.buttonVibration() + } + + itemView.setOnClickListener { + onAssistantClicked(item.key) + } + } +} diff --git a/app/src/main/java/com/wstxda/switchai/utils/Constants.kt b/app/src/main/java/com/wstxda/switchai/utils/Constants.kt index 0ca9326..e7b3fde 100644 --- a/app/src/main/java/com/wstxda/switchai/utils/Constants.kt +++ b/app/src/main/java/com/wstxda/switchai/utils/Constants.kt @@ -8,6 +8,8 @@ object Constants { const val DIGITAL_ASSISTANT_SELECT_PREF_KEY = "digital_assistant_select" const val ASSISTANT_SELECTOR_DIALOG_PREF_KEY = "assistant_selector_dialog" const val ASSISTANT_SEARCH_BAR_PREF_KEY = "assistant_search_bar" + const val ASSISTANT_GRID_VIEW_PREF_KEY = "assistant_grid_view" + const val ASSISTANT_SELECTOR_TITLE_PREF_KEY = "assistant_selector_title" const val ASSISTANT_MANAGER_MANUAL_PREF_KEY = "assistant_manager_manual" const val ASSISTANT_MANAGER_DYNAMIC_PREF_KEY = "assistant_manager_dynamic" const val OPEN_ASSISTANT_TILE_PREF_KEY = "open_assistant_tile" @@ -51,6 +53,8 @@ object Constants { const val VIEW_TYPE_CATEGORY_HEADER = 0 const val VIEW_TYPE_ASSISTANT_ITEM = 1 const val VIEW_TYPE_REORDER_TIP = 2 + const val VIEW_TYPE_ASSISTANT_GRID_ITEM = 3 + const val GRID_SPAN_COUNT = 3 // Maximum number of recently used assistants const val CAT_MAX_RECENTLY_USED = 3 // Category for AssistantSelectorBottomSheet diff --git a/app/src/main/res/layout/list_item_assistant_grid_view.xml b/app/src/main/res/layout/list_item_assistant_grid_view.xml new file mode 100644 index 0000000..bb7cabf --- /dev/null +++ b/app/src/main/res/layout/list_item_assistant_grid_view.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 44c37b2..0acaaaa 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -83,6 +83,12 @@ شريط البحث تمكين شريط البحث للعثور بسرعة على المساعدين في المحدد + عرض الشبكة + عرض المساعدين في تخطيط شبكي مدمج + + إظهار العنوان + إظهار عنوان "اختر المساعد" في المحدد + إدارة المساعدين اختر المساعدين الذين يظهرون في القائمة diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index d351a81..1bef9eb 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -83,6 +83,12 @@ 검색창 선택기에서 어시스턴트를 빠르게 찾을 수 있도록 검색창을 활성화합니다 + 그리드 보기 + 어시스턴트를 콤팩트한 그리드 레이아웃으로 표시합니다 + + 제목 표시 + 선택기에서 "어시스턴트 선택" 제목을 표시합니다 + 어시스턴트 관리 선택기에 표시될 어시스턴트를 선택하세요 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index b4c1031..9ddd61a 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -80,6 +80,12 @@ Barra de pesquisa Habilitar a barra de pesquisa para encontrar assistentes rapidamente no seletor + Visualização em grade + Exibir assistentes em um layout de grade compacto + + Mostrar título + Mostrar o título "Escolher assistente" no seletor + Usar seletor de assistente Se ativado, selecione um assistente toda vez que iniciar. Caso contrário, será usado a opção Assistente digital diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 27475ba..87eddf7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -87,6 +87,12 @@ Search bar Enable the search bar to quickly find assistants in the selector + Grid view + Display assistants in a compact grid layout + + Show title + Show the "Choose assistant" title in the selector + Manage assistants Choose which assistants are displayed in the selector diff --git a/app/src/main/res/xml/main_preferences.xml b/app/src/main/res/xml/main_preferences.xml index 6e957a7..a406f2f 100644 --- a/app/src/main/res/xml/main_preferences.xml +++ b/app/src/main/res/xml/main_preferences.xml @@ -43,6 +43,24 @@ app:iconSpaceReserved="false" app:layout="@layout/preference_material_middle" /> + + + + Date: Tue, 10 Mar 2026 01:08:19 +0100 Subject: [PATCH 2/3] feat: add Russian and Ukrainian translations --- app/src/main/res/values-ru/strings.xml | 204 +++++++++++++++++++++++++ app/src/main/res/values-uk/strings.xml | 204 +++++++++++++++++++++++++ 2 files changed, 408 insertions(+) create mode 100644 app/src/main/res/values-ru/strings.xml create mode 100644 app/src/main/res/values-uk/strings.xml diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000..af7372b --- /dev/null +++ b/app/src/main/res/values-ru/strings.xml @@ -0,0 +1,204 @@ + + + + + Настройки ассистента + + + + Accio + Alexa + Алиса + Bixby + Brenno + ChatGPT + Claude + Conduit + Copilot + DeepSeek + Dicio + Dola + Doubao + Euria + Gemini + Grok + Home Assistant + Home Minimal + ima + Kimi + Kruti + Le Chat + Liner + Lumo + Luzia + Manus + Маруся + Meta AI + MiniMax + Monica + Moto AI + oxproxion + Perplexity + Pi + Poe + Qingyan + Qwen + Spark + StepFun + Ultimate Alexa + Venice AI + Wenxiaoyan + XiaoAI + You + Yuanbao + Zapia + + + + Внешний вид + Выбор ассистента + Ярлыки + О приложении + Поведение + Голосовой ввод + + Разработчик + Репозиторий исходного кода + + Тема + + Библиотеки + Лицензии с открытым исходным кодом + + Версия + + Цифровой ассистент + + Настройка цифрового ассистента + Установите SwitchAI как приложение цифрового ассистента по умолчанию + + Использовать выбор ассистента + Если включено, выбирайте ассистента при каждом запуске. Иначе будет использован параметр Цифровой ассистент + + Строка поиска + Включить строку поиска для быстрого поиска ассистентов в меню выбора + + Вид сеткой + Отображать ассистентов в компактном виде сеткой + + Показывать заголовок + Показывать заголовок «Выбор ассистента» в меню + + Управление ассистентами + Выберите, какие ассистенты отображаются в меню выбора + + Динамическое управление + Динамически управляйте отображаемыми ассистентами в зависимости от установленных приложений + В меню отображаются только установленные ассистенты + + Добавить плитку ассистента + Добавить плитку быстрых настроек для доступа к ассистенту на устройстве + + Добавить виджет ассистента + Добавить виджет для доступа к ассистенту с главного экрана устройства + + Вибрация при открытии + Тактильная обратная связь при открытии ассистента. На неё могут влиять системные настройки + + Звук при открытии + Звуковая обратная связь при открытии ассистента. Может быть отключена режимом звука устройства или активным воспроизведением медиа + + Использовать права root + Использовать права root для включения голосового ввода для отдельных ассистентов и улучшения удобства использования + + Использовать голосовой ввод + Если включено, вместо главного экрана будет использоваться голосовой ввод в поддерживаемых ассистентах + + + + Выбор темы + + Системная + Светлая + Тёмная + + + + Проверить обновления + Скачать + + Обновлений нет + Доступно новое обновление: %s + Нет подключения к интернету + Что-то пошло не так… Попробуйте позже + + + + Выберите ассистента + + Поиск ассистентов + Ассистенты не найдены + + Закреплённые + Недавно использованные + Ассистенты + Не установлены + + Чтобы изменить порядок закреплённых ассистентов, нажмите и удерживайте одного из них, затем перетащите на нужное место + Закрыть подсказку + + Открыть ассистента + Ошибка открытия ассистента + Приложение не найдено. Пожалуйста, сначала установите его + Ассистент пока не реализован… + + Приложение цифрового ассистента по умолчанию + В настройках выберите SwitchAI в качестве приложения цифрового ассистента по умолчанию для быстрого доступа к выбранному ассистенту с помощью жестов, кнопок и многого другого… + Установить по умолчанию + + Как использовать цифрового ассистента + + + + Использование жестов по краям экрана + На устройствах с навигацией жестами (Android 10+) проведите вверх и внутрь из любого нижнего угла экрана. Из угла появится светящаяся дуга, подтверждающая открытие цифрового ассистента. Для этого в настройках системной навигации устройства должна быть выбрана Навигация жестами + Использование кнопки «Домой» + Если на вашем устройстве используется классическая навигация с тремя кнопками, нажмите и удерживайте центральную кнопку «Домой». Обычно это действие предназначено для открытия цифрового ассистента. Если действие выполняет другую функцию, оно может быть настроено производителем устройства + Использование кнопки питания + На многих устройствах можно открыть цифрового ассистента, долго удерживая кнопку питания. Если при этом появляется меню выключения/перезагрузки, функция, вероятно, отключена. Её можно включить в системных настройках, как правило по пути Настройки > Система > Жесты > Нажатие и удержание кнопки питания + Использование проводных и беспроводных гарнитур + Многие проводные и Bluetooth-гарнитуры позволяют открыть цифрового ассистента, долго удерживая многофункциональную кнопку. Обычно она используется для управления воспроизведением или ответа на звонки, но также может открывать ассистента в зависимости от модели гарнитуры. Жесты нажатия на некоторых беспроводных наушниках, например двойное нажатие, также могут открывать цифрового ассистента, если это поддерживается и настроено в приложении + + + + Ассистент + Открыть + Выбрать + Выбор + Открыть выбор + + + + Успешно добавлено в быстрые настройки + Уже добавлено в быстрые настройки + + + + Сначала предоставьте права root + + + + Выберите не менее %1$d вариантов + Выберите не более %1$d вариантов + + + + Material-стиль + Невидимый + + Виджет в стиле Material для доступа к ассистенту + Невидимый виджет для доступа к ассистенту + + Ваш лаунчер не поддерживает закрепление виджетов + + diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000..27486f4 --- /dev/null +++ b/app/src/main/res/values-uk/strings.xml @@ -0,0 +1,204 @@ + + + + + Налаштування асистента + + + + Accio + Alexa + Alice + Bixby + Brenno + ChatGPT + Claude + Conduit + Copilot + DeepSeek + Dicio + Dola + Doubao + Euria + Gemini + Grok + Home Assistant + Home Minimal + ima + Kimi + Kruti + Le Chat + Liner + Lumo + Luzia + Manus + Marusya + Meta AI + MiniMax + Monica + Moto AI + oxproxion + Perplexity + Pi + Poe + Qingyan + Qwen + Spark + StepFun + Ultimate Alexa + Venice AI + Wenxiaoyan + XiaoAI + You + Yuanbao + Zapia + + + + Зовнішній вигляд + Вибір асистента + Ярлики + Про додаток + Поведінка + Голосове введення + + Розробник + Репозиторій вихідного коду + + Тема + + Бібліотеки + Ліцензії з відкритим вихідним кодом + + Версія + + Цифровий асистент + + Налаштування цифрового асистента + Встановіть SwitchAI як стандартний застосунок цифрового асистента + + Використовувати вибір асистента + Якщо увімкнено, обирайте асистента щоразу при запуску. Інакше буде використано параметр Цифровий асистент + + Рядок пошуку + Увімкнути рядок пошуку для швидкого пошуку асистентів у меню вибору + + Вигляд сіткою + Відображати асистентів у компактному вигляді сіткою + + Показувати заголовок + Показувати заголовок «Вибір асистента» у меню + + Керування асистентами + Оберіть, які асистенти відображаються у меню вибору + + Динамічне керування + Динамічно керуйте відображуваними асистентами залежно від встановлених застосунків + У меню відображаються лише встановлені асистенти + + Додати плитку асистента + Додати плитку швидких налаштувань для доступу до асистента на пристрої + + Додати віджет асистента + Додати віджет для доступу до асистента з головного екрана пристрою + + Вібрація при відкритті + Тактильний зворотний зв\'язок при відкритті асистента. На нього можуть впливати системні налаштування + + Звук при відкритті + Звуковий зворотний зв\'язок при відкритті асистента. Може бути вимкнено режимом звуку пристрою або активним відтворенням медіа + + Використовувати права root + Використовувати права root для увімкнення голосового введення для окремих асистентів і покращення зручності використання + + Використовувати голосове введення + Якщо увімкнено, замість головного екрана буде використовуватися голосове введення в підтримуваних асистентах + + + + Вибір теми + + Системна + Світла + Темна + + + + Перевірити оновлення + Завантажити + + Оновлень немає + Доступне нове оновлення: %s + Немає підключення до інтернету + Щось пішло не так… Спробуйте пізніше + + + + Оберіть асистента + + Пошук асистентів + Асистентів не знайдено + + Закріплені + Нещодавно використані + Асистенти + Не встановлені + + Щоб змінити порядок закріплених асистентів, натисніть і утримуйте одного з них, а потім перетягніть на потрібне місце + Закрити підказку + + Відкрити асистента + Помилка відкриття асистента + Застосунок не знайдено. Будь ласка, спочатку встановіть його + Асистент ще не реалізований… + + Стандартний застосунок цифрового асистента + У налаштуваннях оберіть SwitchAI як стандартний застосунок цифрового асистента для швидкого доступу до обраного асистента за допомогою жестів, кнопок тощо… + Встановити за замовчуванням + + Як користуватися цифровим асистентом + + + + Використання жестів по краях екрана + На пристроях із навігацією жестами (Android 10+) проведіть вгору та всередину з будь-якого нижнього кута екрана. З кута з\'явиться світна дуга, що підтверджує відкриття цифрового асистента. Для цього в налаштуваннях системної навігації пристрою має бути обрано Навігація жестами + Використання кнопки «Додому» + Якщо ваш пристрій використовує класичну навігацію з трьома кнопками, натисніть і утримуйте центральну кнопку «Додому» на мить. Зазвичай ця дія призначена для відкриття цифрового асистента. Якщо дія виконує іншу функцію, її міг налаштувати виробник пристрою + Використання кнопки живлення + На багатьох пристроях можна відкрити цифрового асистента, утримуючи кнопку живлення. Якщо при цьому з\'являється меню вимкнення/перезавантаження, функція, ймовірно, вимкнена. Її можна увімкнути в системних налаштуваннях, як правило за шляхом Налаштування > Система > Жести > Натискання і утримання кнопки живлення + Використання дротових і бездротових гарнітур + Багато дротових і Bluetooth-гарнітур дозволяють відкрити цифрового асистента, утримуючи багатофункціональну кнопку. Зазвичай вона використовується для керування відтворенням або відповіді на дзвінки, але також може відкривати асистента залежно від моделі гарнітури. Жести натискання на деяких бездротових навушниках, наприклад подвійне натискання, також можуть відкривати цифрового асистента, якщо це підтримується та налаштовано в застосунку + + + + Асистент + Відкрити + Обрати + Вибір + Відкрити вибір + + + + Успішно додано до швидких налаштувань + Вже додано до швидких налаштувань + + + + Спочатку надайте права root + + + + Оберіть щонайменше %1$d варіанти + Оберіть не більше %1$d варіантів + + + + Material-стиль + Невидимий + + Віджет у стилі Material для доступу до асистента + Невидимий віджет для доступу до асистента + + Ваш лаунчер не підтримує закріплення віджетів + + From f78dc69b34812577fd015482c14254adc1aace48 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Tue, 10 Mar 2026 14:18:11 +0100 Subject: [PATCH 3/3] feat: implement grid view for assistant selector by dpi scaling and overridable column settings --- .../switchai/fragment/SettingsFragment.kt | 4 ++ .../ui/adapter/AssistantSelectorAdapter.kt | 2 +- .../component/AssistantSelectorBottomSheet.kt | 27 ++++++++++++- .../ui/viewholder/ReorderTipViewHolder.kt | 8 +++- .../com/wstxda/switchai/utils/Constants.kt | 2 + .../viewmodel/AssistantSelectorViewModel.kt | 10 +++++ app/src/main/res/drawable/ic_grid.xml | 9 +++++ app/src/main/res/values-ar/strings.xml | 7 +++- app/src/main/res/values-ko/strings.xml | 5 +++ app/src/main/res/values-pt-rBR/strings.xml | 7 +++- app/src/main/res/values-ru/strings.xml | 7 +++- app/src/main/res/values-uk/strings.xml | 7 +++- app/src/main/res/values/arrays.xml | 18 +++++++++ app/src/main/res/values/integers.xml | 4 ++ app/src/main/res/values/strings.xml | 7 +++- app/src/main/res/xml/main_preferences.xml | 40 +++++++++++++++---- 16 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 app/src/main/res/drawable/ic_grid.xml create mode 100644 app/src/main/res/values/integers.xml diff --git a/app/src/main/java/com/wstxda/switchai/fragment/SettingsFragment.kt b/app/src/main/java/com/wstxda/switchai/fragment/SettingsFragment.kt index 6b25bd6..cc2762a 100644 --- a/app/src/main/java/com/wstxda/switchai/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/wstxda/switchai/fragment/SettingsFragment.kt @@ -68,6 +68,10 @@ class SettingsFragment : PreferenceFragmentCompat() { findPreference(Constants.ASSISTANT_MANAGER_MANUAL_PREF_KEY)?.isVisible = !isDynamic } + assistantSelectorViewModel.isGridViewEnabled.observe(this) { isGrid -> + findPreference(Constants.ASSISTANT_GRID_COLUMNS_PREF_KEY)?.isVisible = isGrid + findPreference(Constants.ASSISTANT_GRID_COLUMNS_LAND_PREF_KEY)?.isVisible = isGrid + } } override fun onResume() { diff --git a/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt b/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt index e4c8844..0571a0a 100644 --- a/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt +++ b/app/src/main/java/com/wstxda/switchai/ui/adapter/AssistantSelectorAdapter.kt @@ -76,7 +76,7 @@ class AssistantSelectorAdapter( } is AssistantSelectorRecyclerView.ReorderTip -> (holder as ReorderTipViewHolder).bind( - onDismissTipClicked + onDismissTipClicked, isGridMode ) } } diff --git a/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt b/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt index 34b780b..d6eff9f 100644 --- a/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt +++ b/app/src/main/java/com/wstxda/switchai/ui/component/AssistantSelectorBottomSheet.kt @@ -82,12 +82,34 @@ class AssistantSelectorBottomSheet : BaseBottomSheet 3 + isLandscape -> 4 + isLowDensity -> 2 + else -> 3 + } + } + val spanCount = if (userPref > 0) userPref else autoSpan + val gridLayoutManager = GridLayoutManager(context, spanCount) gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { override fun getSpanSize(position: Int): Int { return when (assistantSelectorAdapter.getItemViewType(position)) { Constants.VIEW_TYPE_ASSISTANT_GRID_ITEM -> 1 - else -> Constants.GRID_SPAN_COUNT + else -> spanCount } } } @@ -97,6 +119,7 @@ class AssistantSelectorBottomSheet : BaseBottomSheet Unit) { + fun bind(onDismissClicked: () -> Unit, isGridMode: Boolean = false) { binding.dismissButton.setOnClickListener { onDismissClicked() } + if (isGridMode) { + val lp = binding.root.layoutParams as? android.view.ViewGroup.MarginLayoutParams + lp?.marginStart = 0 + lp?.marginEnd = 0 + binding.root.layoutParams = lp + } } } \ No newline at end of file diff --git a/app/src/main/java/com/wstxda/switchai/utils/Constants.kt b/app/src/main/java/com/wstxda/switchai/utils/Constants.kt index e7b3fde..a0dc485 100644 --- a/app/src/main/java/com/wstxda/switchai/utils/Constants.kt +++ b/app/src/main/java/com/wstxda/switchai/utils/Constants.kt @@ -9,6 +9,8 @@ object Constants { const val ASSISTANT_SELECTOR_DIALOG_PREF_KEY = "assistant_selector_dialog" const val ASSISTANT_SEARCH_BAR_PREF_KEY = "assistant_search_bar" const val ASSISTANT_GRID_VIEW_PREF_KEY = "assistant_grid_view" + const val ASSISTANT_GRID_COLUMNS_PREF_KEY = "assistant_grid_columns" + const val ASSISTANT_GRID_COLUMNS_LAND_PREF_KEY = "assistant_grid_columns_land" const val ASSISTANT_SELECTOR_TITLE_PREF_KEY = "assistant_selector_title" const val ASSISTANT_MANAGER_MANUAL_PREF_KEY = "assistant_manager_manual" const val ASSISTANT_MANAGER_DYNAMIC_PREF_KEY = "assistant_manager_dynamic" diff --git a/app/src/main/java/com/wstxda/switchai/viewmodel/AssistantSelectorViewModel.kt b/app/src/main/java/com/wstxda/switchai/viewmodel/AssistantSelectorViewModel.kt index c6ed3b0..433cba8 100644 --- a/app/src/main/java/com/wstxda/switchai/viewmodel/AssistantSelectorViewModel.kt +++ b/app/src/main/java/com/wstxda/switchai/viewmodel/AssistantSelectorViewModel.kt @@ -44,6 +44,9 @@ class AssistantSelectorViewModel(application: Application) : AndroidViewModel(ap private val _isDynamicModeEnabled = MutableLiveData() val isDynamicModeEnabled: LiveData = _isDynamicModeEnabled + private val _isGridViewEnabled = MutableLiveData() + val isGridViewEnabled: LiveData = _isGridViewEnabled + private val pinnedAssistantKeys = mutableListOf() private val recentlyUsedAssistants = mutableListOf>() @@ -77,9 +80,15 @@ class AssistantSelectorViewModel(application: Application) : AndroidViewModel(ap Constants.ASSISTANT_MANAGER_DYNAMIC_PREF_KEY, false ) + private val isGridView: Boolean + get() = defaultSharedPreferences.getBoolean( + Constants.ASSISTANT_GRID_VIEW_PREF_KEY, false + ) + init { defaultSharedPreferences.registerOnSharedPreferenceChangeListener(this) _isDynamicModeEnabled.value = isDynamicMode + _isGridViewEnabled.value = isGridView val intentFilter = IntentFilter().apply { addAction(Intent.ACTION_PACKAGE_ADDED) @@ -347,6 +356,7 @@ class AssistantSelectorViewModel(application: Application) : AndroidViewModel(ap _isDynamicModeEnabled.value = isDynamicMode loadAssistants() } + Constants.ASSISTANT_GRID_VIEW_PREF_KEY -> _isGridViewEnabled.value = isGridView } } diff --git a/app/src/main/res/drawable/ic_grid.xml b/app/src/main/res/drawable/ic_grid.xml new file mode 100644 index 0000000..313b976 --- /dev/null +++ b/app/src/main/res/drawable/ic_grid.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 0acaaaa..84663cf 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -86,8 +86,13 @@ عرض الشبكة عرض المساعدين في تخطيط شبكي مدمج + أعمدة الشبكة + عدد الأعمدة في الشبكة + أعمدة الشبكة (أفقي) + تلقائي + إظهار العنوان - إظهار عنوان "اختر المساعد" في المحدد + إظهار عنوان "حدد المساعد" في المحدد إدارة المساعدين اختر المساعدين الذين يظهرون في القائمة diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 1bef9eb..84d70ad 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -86,6 +86,11 @@ 그리드 보기 어시스턴트를 콤팩트한 그리드 레이아웃으로 표시합니다 + 그리드 열 수 + 그리드의 열 수 + 그리드 열 수 (가로) + 자동 + 제목 표시 선택기에서 "어시스턴트 선택" 제목을 표시합니다 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 9ddd61a..fe7cbdc 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -83,8 +83,13 @@ Visualização em grade Exibir assistentes em um layout de grade compacto + Colunas da grade + Número de colunas na grade + Colunas da grade (paisagem) + Automático + Mostrar título - Mostrar o título "Escolher assistente" no seletor + Mostrar o título "Selecionar assistente" no seletor Usar seletor de assistente Se ativado, selecione um assistente toda vez que iniciar. Caso contrário, será usado a opção Assistente digital diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index af7372b..e17179e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -86,8 +86,13 @@ Вид сеткой Отображать ассистентов в компактном виде сеткой + Столбцов в сетке + Количество столбцов в сетке + Столбцов в сетке (альбомная) + Автоматически + Показывать заголовок - Показывать заголовок «Выбор ассистента» в меню + Показывать заголовок «Выберите ассистента» в меню Управление ассистентами Выберите, какие ассистенты отображаются в меню выбора diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 27486f4..4f7b0f1 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -86,8 +86,13 @@ Вигляд сіткою Відображати асистентів у компактному вигляді сіткою + Стовпців у сітці + Кількість стовпців у сітці + Стовпців у сітці (альбомна) + Автоматично + Показувати заголовок - Показувати заголовок «Вибір асистента» у меню + Показувати заголовок «Виберіть асистента» у меню Керування асистентами Оберіть, які асистенти відображаються у меню вибору diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8608e7b..23eb7e0 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -102,6 +102,24 @@ + + @string/grid_columns_auto + 2 + 3 + 4 + 5 + + + + 0 + 2 + 3 + 4 + 5 + + + + @string/theme_system @string/theme_light diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 0000000..60307e5 --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,4 @@ + + + 3 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 87eddf7..a4358cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,8 +90,13 @@ Grid view Display assistants in a compact grid layout + Grid columns + Number of columns in the grid + Grid columns (landscape) + Automatic + Show title - Show the "Choose assistant" title in the selector + Show the "Select assistant" title in the selector Manage assistants Choose which assistants are displayed in the selector diff --git a/app/src/main/res/xml/main_preferences.xml b/app/src/main/res/xml/main_preferences.xml index a406f2f..6352acc 100644 --- a/app/src/main/res/xml/main_preferences.xml +++ b/app/src/main/res/xml/main_preferences.xml @@ -43,6 +43,15 @@ app:iconSpaceReserved="false" app:layout="@layout/preference_material_middle" /> + + - + app:layout="@layout/preference_material_middle" + app:useSimpleSummaryProvider="true" /> + +