feat: requested selected item
This commit is contained in:
@@ -227,7 +227,7 @@ const Model = struct {
|
|||||||
break :colors .{ fg, bg };
|
break :colors .{ fg, bg };
|
||||||
};
|
};
|
||||||
|
|
||||||
const text = try ctx.arena.dupe(u8, child.fullName.path);
|
const text = try ctx.arena.dupe(u8, child.displayName);
|
||||||
const text_element = try ctx.arena.create(vxfw.Text);
|
const text_element = try ctx.arena.create(vxfw.Text);
|
||||||
text_element.* = vxfw.Text{
|
text_element.* = vxfw.Text{
|
||||||
.text = text,
|
.text = text,
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !Ac
|
|||||||
} else return error.NoCurrentLocation;
|
} else return error.NoCurrentLocation;
|
||||||
},
|
},
|
||||||
.SelectNext => {
|
.SelectNext => {
|
||||||
return selectNextIndex(appState.currentTab, .Next);
|
return selectNextIndex(appState.currentTab, .Next, arena);
|
||||||
},
|
},
|
||||||
.SelectPrevious => {
|
.SelectPrevious => {
|
||||||
return selectNextIndex(appState.currentTab, .Previous);
|
return selectNextIndex(appState.currentTab, .Previous, arena);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,29 +35,38 @@ const SelectStep = enum {
|
|||||||
PreviousPage,
|
PreviousPage,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn selectNextIndex(currentTab: *Tab, step: SelectStep) ActionResult {
|
fn selectNextIndex(currentTab: *Tab, step: SelectStep, arena: std.mem.Allocator) !ActionResult {
|
||||||
const index = blk: {
|
const item = item: {
|
||||||
currentTab.currentItems.mutex.lock();
|
currentTab.currentItems.mutex.lock();
|
||||||
defer currentTab.currentItems.mutex.unlock();
|
defer currentTab.currentItems.mutex.unlock();
|
||||||
|
|
||||||
const currentItems = currentTab.currentItems.data orelse return ActionResult.None;
|
const currentItems = currentTab.currentItems.data orelse return ActionResult.None;
|
||||||
|
|
||||||
if (currentTab.currentItem) |*currentItem| {
|
const index = blk: {
|
||||||
const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, currentItem, arcFullNameEql);
|
if (currentTab.currentItem) |*currentItem| {
|
||||||
if (index) |i| {
|
const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, currentItem, arcFullNameEql);
|
||||||
break :blk switch (step) {
|
if (index) |i| {
|
||||||
.Next => i +| 1,
|
break :blk switch (step) {
|
||||||
.Previous => i -| 1,
|
.Next => i +| 1,
|
||||||
.NextPage => i +| 8,
|
.Previous => i -| 1,
|
||||||
.PreviousPage => i +| 8,
|
.NextPage => i +| 8,
|
||||||
};
|
.PreviousPage => i +| 8,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break :blk 0;
|
break :blk 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const arc = currentItems.items[index];
|
||||||
|
const arc_copy = arc.retain();
|
||||||
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
|
break :item models.FullName{
|
||||||
|
.path = try arena.dupe(u8, arc_copy.value.*.fullName.path),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
currentTab.selectItem(index) catch {
|
currentTab.selectItem(item) catch {
|
||||||
//TODO
|
//TODO
|
||||||
};
|
};
|
||||||
return ActionResult.Handled;
|
return ActionResult.Handled;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ pub const Tab = struct {
|
|||||||
currentItems: locked(?std.ArrayList(Arc(*Item))),
|
currentItems: locked(?std.ArrayList(Arc(*Item))),
|
||||||
currentLocationChanged: Observable(?*Container),
|
currentLocationChanged: Observable(?*Container),
|
||||||
currentItem: ?models.FullName,
|
currentItem: ?models.FullName,
|
||||||
|
currentRequestedItem: ?models.FullName,
|
||||||
threadPool: *std.Thread.Pool,
|
threadPool: *std.Thread.Pool,
|
||||||
rootProvider: *RootProvider,
|
rootProvider: *RootProvider,
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ pub const Tab = struct {
|
|||||||
.currentItems = .{ .data = null },
|
.currentItems = .{ .data = null },
|
||||||
.currentLocationChanged = Observable(?*Container).init(allocator),
|
.currentLocationChanged = Observable(?*Container).init(allocator),
|
||||||
.currentLocation = null,
|
.currentLocation = null,
|
||||||
|
.currentRequestedItem = null,
|
||||||
.currentItem = null,
|
.currentItem = null,
|
||||||
.threadPool = threadPool,
|
.threadPool = threadPool,
|
||||||
.rootProvider = rootProvider,
|
.rootProvider = rootProvider,
|
||||||
@@ -52,31 +54,83 @@ pub const Tab = struct {
|
|||||||
};
|
};
|
||||||
self.currentLocationChanged.notify(newLocationContainer);
|
self.currentLocationChanged.notify(newLocationContainer);
|
||||||
|
|
||||||
//TODO: Proper error handling
|
self.updateCurrentItem() catch {
|
||||||
std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable;
|
|
||||||
|
|
||||||
self.selectItem(0) catch {
|
|
||||||
self.currentItem = null;
|
self.currentItem = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: Proper error handling
|
||||||
|
std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selectItem(self: *Tab, index: usize) !void {
|
pub fn selectItem(self: *Tab, requested_selected: models.FullName) !void {
|
||||||
self.currentItems.mutex.lock();
|
self.currentItems.mutex.lock();
|
||||||
defer self.currentItems.mutex.unlock();
|
defer self.currentItems.mutex.unlock();
|
||||||
|
|
||||||
const currentItems = self.currentItems.data orelse return error.Error;
|
self.currentRequestedItem = models.FullName{
|
||||||
|
.path = try self.allocator.dupe(u8, requested_selected.path),
|
||||||
if (index >= currentItems.items.len) {
|
|
||||||
return error.OutOfRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.currentItem) |currentItem| {
|
|
||||||
self.allocator.free(currentItem.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.currentItem = models.FullName{
|
|
||||||
.path = try self.allocator.dupe(u8, currentItems.items[index].value.*.fullName.path),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return self.updateCurrentItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn updateCurrentItem(self: *Tab) !void {
|
||||||
|
const currentRequestedItem = self.currentRequestedItem orelse return;
|
||||||
|
|
||||||
|
// The requested is already selected
|
||||||
|
if (self.currentItem) |currentItem| {
|
||||||
|
if (std.mem.order(u8, currentRequestedItem.path, currentItem.path) == .eq) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentItems = self.currentItems.data orelse return error.Error;
|
||||||
|
if (currentItems.items.len == 0) return error.Error;
|
||||||
|
|
||||||
|
// Looking for the requested
|
||||||
|
const foundIndex = for (0..currentItems.items.len) |i| {
|
||||||
|
const arc_item = currentItems.items[i];
|
||||||
|
const arc_copy = arc_item.retain();
|
||||||
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
|
const comp = std.mem.order(u8, arc_copy.value.*.fullName.path, currentRequestedItem.path);
|
||||||
|
if (comp == .eq) {
|
||||||
|
break i;
|
||||||
|
}
|
||||||
|
if (comp == .lt) {
|
||||||
|
break i -| 1;
|
||||||
|
}
|
||||||
|
} else null;
|
||||||
|
|
||||||
|
if (foundIndex) |i| {
|
||||||
|
const arc_item = currentItems.items[i];
|
||||||
|
const arc_copy = arc_item.retain();
|
||||||
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
|
self.setSelectedItemInner(models.FullName{
|
||||||
|
.path = try self.allocator.dupe(u8, arc_copy.value.*.fullName.path),
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: use lastdeepestselectedpath
|
||||||
|
|
||||||
|
// Fallback to first item
|
||||||
|
{
|
||||||
|
const arc_item = currentItems.items[0];
|
||||||
|
const arc_copy = arc_item.retain();
|
||||||
|
defer if (arc_copy.releaseUnwrap()) |item| item.deinit();
|
||||||
|
|
||||||
|
self.setSelectedItemInner(models.FullName{
|
||||||
|
.path = try self.allocator.dupe(u8, arc_copy.value.*.fullName.path),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setSelectedItemInner(self: *Tab, newSelectedItem: models.FullName) void {
|
||||||
|
if (self.currentItem) |current| {
|
||||||
|
self.allocator.free(current.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.currentItem = newSelectedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
||||||
@@ -123,15 +177,18 @@ pub const Tab = struct {
|
|||||||
self.currentItems.mutex.lock();
|
self.currentItems.mutex.lock();
|
||||||
defer self.currentItems.mutex.unlock();
|
defer self.currentItems.mutex.unlock();
|
||||||
|
|
||||||
const index = for (self.currentItems.data.?.items, 0..) |item, i| {
|
const insertIndex = for (self.currentItems.data.?.items, 0..) |item, i| {
|
||||||
if (compareByDisplayName(resolvedItem, item.value.*)) break i;
|
if (compareByDisplayName(resolvedItem, item.value.*)) break i;
|
||||||
} else null;
|
} else null;
|
||||||
|
|
||||||
const arc = try Arc(*Item).init(self.allocator, resolvedItem);
|
const arc = try Arc(*Item).init(self.allocator, resolvedItem);
|
||||||
if (index) |i| {
|
if (insertIndex) |i| {
|
||||||
try self.currentItems.data.?.insert(i, arc);
|
try self.currentItems.data.?.insert(i, arc);
|
||||||
} else {
|
} else {
|
||||||
try self.currentItems.data.?.append(arc);
|
try self.currentItems.data.?.append(arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.updateCurrentItem() catch {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user