feat(ui): add drag-and-drop sorting for provider list (#126)
* feat(ui): add drag-and-drop sorting for provider list Implement drag-and-drop functionality to allow users to reorder providers with custom sort indices. Features: - Install @dnd-kit libraries for drag-and-drop support - Add sortIndex field to Provider type (frontend & backend) - Implement SortableProviderItem component with drag handle - Add update_providers_sort_order Tauri command - Sync tray menu order with provider list sorting - Add i18n support for drag-related UI text Technical details: - Use @dnd-kit/core and @dnd-kit/sortable for smooth drag interactions - Disable animations for immediate response after drop - Update tray menu immediately after reordering - Sort priority: sortIndex → createdAt → name 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix(ui): remove unused transition variable in ProviderList Remove unused 'transition' destructured variable from useSortable hook to fix TypeScript error TS6133. The transition property is hardcoded as 'none' in the style object to prevent conflicts with drag operations. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -49,7 +49,28 @@ fn create_tray_menu(
|
||||
menu_builder = menu_builder.item(&claude_header);
|
||||
|
||||
if !claude_manager.providers.is_empty() {
|
||||
for (id, provider) in &claude_manager.providers {
|
||||
// Sort providers by sortIndex, then by createdAt, then by name
|
||||
let mut sorted_providers: Vec<_> = claude_manager.providers.iter().collect();
|
||||
sorted_providers.sort_by(|(_, a), (_, b)| {
|
||||
// Priority 1: sortIndex
|
||||
match (a.sort_index, b.sort_index) {
|
||||
(Some(idx_a), Some(idx_b)) => return idx_a.cmp(&idx_b),
|
||||
(Some(_), None) => return std::cmp::Ordering::Less,
|
||||
(None, Some(_)) => return std::cmp::Ordering::Greater,
|
||||
_ => {}
|
||||
}
|
||||
// Priority 2: createdAt
|
||||
match (a.created_at, b.created_at) {
|
||||
(Some(time_a), Some(time_b)) => return time_a.cmp(&time_b),
|
||||
(Some(_), None) => return std::cmp::Ordering::Greater,
|
||||
(None, Some(_)) => return std::cmp::Ordering::Less,
|
||||
_ => {}
|
||||
}
|
||||
// Priority 3: name
|
||||
a.name.cmp(&b.name)
|
||||
});
|
||||
|
||||
for (id, provider) in sorted_providers {
|
||||
let is_current = claude_manager.current == *id;
|
||||
let item = CheckMenuItem::with_id(
|
||||
app,
|
||||
@@ -84,7 +105,28 @@ fn create_tray_menu(
|
||||
menu_builder = menu_builder.item(&codex_header);
|
||||
|
||||
if !codex_manager.providers.is_empty() {
|
||||
for (id, provider) in &codex_manager.providers {
|
||||
// Sort providers by sortIndex, then by createdAt, then by name
|
||||
let mut sorted_providers: Vec<_> = codex_manager.providers.iter().collect();
|
||||
sorted_providers.sort_by(|(_, a), (_, b)| {
|
||||
// Priority 1: sortIndex
|
||||
match (a.sort_index, b.sort_index) {
|
||||
(Some(idx_a), Some(idx_b)) => return idx_a.cmp(&idx_b),
|
||||
(Some(_), None) => return std::cmp::Ordering::Less,
|
||||
(None, Some(_)) => return std::cmp::Ordering::Greater,
|
||||
_ => {}
|
||||
}
|
||||
// Priority 2: createdAt
|
||||
match (a.created_at, b.created_at) {
|
||||
(Some(time_a), Some(time_b)) => return time_a.cmp(&time_b),
|
||||
(Some(_), None) => return std::cmp::Ordering::Greater,
|
||||
(None, Some(_)) => return std::cmp::Ordering::Less,
|
||||
_ => {}
|
||||
}
|
||||
// Priority 3: name
|
||||
a.name.cmp(&b.name)
|
||||
});
|
||||
|
||||
for (id, provider) in sorted_providers {
|
||||
let is_current = codex_manager.current == *id;
|
||||
let item = CheckMenuItem::with_id(
|
||||
app,
|
||||
@@ -460,6 +502,8 @@ pub fn run() {
|
||||
// app_config_dir override via Store
|
||||
commands::get_app_config_dir_override,
|
||||
commands::set_app_config_dir_override,
|
||||
// provider sort order management
|
||||
commands::update_providers_sort_order,
|
||||
// theirs: config import/export and dialogs
|
||||
import_export::export_config_to_file,
|
||||
import_export::import_config_from_file,
|
||||
|
||||
Reference in New Issue
Block a user