feat: 同时启动多个模拟器时使用自动检测连接时提供弹窗选择
https://github.com/user-attachments/assets/0b424e4d-6704-4d63-84dc-64916df6220b
## Summary by Sourcery
添加通用的项目选择对话框,并使用它在自动检测期间处理多个已检测到的模拟器和连接地址。
New Features:
- 引入可复用的项目选择对话框和视图模型,可以显示带有可自定义标题和提示语的项目列表,并返回所选项目。
- 当检测到多个模拟器或多个 ADB 路径时,允许用户选择要连接的模拟器实例。
- 当检测到多个非默认的 ADB 连接地址时,允许用户选择要使用的连接地址。
Bug Fixes:
- 当发现多个候选项时,通过明确要求用户进行选择,防止产生含糊不清或错误的模拟器/ADB 选择。
- 当不存在有效目录时,将已配置路径初始化为空,避免强制使用硬编码的默认模拟器安装路径。
- 确保选择对话框始终在 UI 线程调度器上创建和显示,以避免潜在的线程问题。
Enhancements:
- 优化模拟器检测逻辑,以同时跟踪模拟器名称和解析后的 ADB 路径,对结果去重,并在选择界面中展示这些信息。
- 使用通用项目选择对话框替换特定于模拟器路径的对话框,并简化相关视图模型的职责。
- 通过可在不同选择场景中复用的通用选择与提示字符串,改进本地化支持。
<details>
<summary>Original summary in English</summary>
## Summary by Sourcery
Add generic item selection dialog and use it to handle multiple detected
emulators and connection addresses during auto-detection.
New Features:
- Introduce a reusable item selection dialog and view model that can
display a list of items with customizable title and prompt and return
the selected item.
- Allow users to choose which emulator instance to connect to when
multiple emulators or ADB paths are detected.
- Allow users to choose which connection address to use when multiple
non-default ADB addresses are detected.
Bug Fixes:
- Prevent ambiguous or incorrect emulator/ADB selection by explicitly
requiring a user choice when multiple candidates are found.
- Avoid forcing hard-coded default emulator installation paths by
initializing configured paths as empty when no valid directory exists.
- Ensure selection dialogs are always created and shown on the UI thread
dispatcher to avoid potential threading issues.
Enhancements:
- Refine emulator detection to track both emulator name and resolved ADB
path, deduplicate results, and surface this information in the selection
UI.
- Replace the emulator-path-specific dialog with a generic item
selection dialog and simplify related view model responsibilities.
- Improve localization support with generic selection and prompt strings
that can be reused across different selection scenarios.
</details>
## Summary by Sourcery
将任务序列化逻辑从任务设置视图模型中抽取出来,放入一个专门的序列化接口中,并在每个任务特定的视图模型中通过内部接口实现。
Enhancements:
- 引入 `ITaskQueueModelSerialize` 接口,将任务序列化相关的逻辑与 `TaskSettingsViewModel`
解耦。
- 重构多个任务特定的设置视图模型,通过私有的嵌套 `ISerialize` 接口来实现新的序列化接口。
- 简化或移除未使用的 `using` 指令,并在相关视图模型中进行一些次要的属性格式整理。
<details>
<summary>Original summary in English</summary>
## Summary by Sourcery
Extract task serialization logic from task settings view models into a
dedicated serialization interface implemented via inner interfaces on
each task-specific view model.
Enhancements:
- Introduce the ITaskQueueModelSerialize interface to decouple task
serialization concerns from TaskSettingsViewModel.
- Refactor multiple task-specific settings view models to implement the
new serialization interface via private nested ISerialize interfaces.
- Simplify or remove unused using directives and minor property
formatting cleanups across affected view models.
</details>
增强内容:
- 让 TaskSettingsViewModel 实现新的 ITaskQueueModelSerialize
接口,以将任务序列化相关的关注点从视图模型中分离出来。
- 清理 TaskSettingsViewModel 中未使用的 using 指令,以减少依赖。
<details>
<summary>Original summary in English</summary>
## Summary by Sourcery
将任务序列化逻辑从任务设置视图模型中抽取出来,放入一个专门的序列化接口中,并在每个任务特定的视图模型中通过内部接口实现。
Enhancements:
- 引入 `ITaskQueueModelSerialize` 接口,将任务序列化相关的逻辑与 `TaskSettingsViewModel`
解耦。
- 重构多个任务特定的设置视图模型,通过私有的嵌套 `ISerialize` 接口来实现新的序列化接口。
- 简化或移除未使用的 `using` 指令,并在相关视图模型中进行一些次要的属性格式整理。
<details>
<summary>Original summary in English</summary>
## Summary by Sourcery
Extract task serialization logic from task settings view models into a
dedicated serialization interface implemented via inner interfaces on
each task-specific view model.
Enhancements:
- Introduce the ITaskQueueModelSerialize interface to decouple task
serialization concerns from TaskSettingsViewModel.
- Refactor multiple task-specific settings view models to implement the
new serialization interface via private nested ISerialize interfaces.
- Simplify or remove unused using directives and minor property
formatting cleanups across affected view models.
</details>
</details>