feat: cleanup appstate, move sort to tab
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
pub const ActionResult = union(enum) {
|
||||
None,
|
||||
Handled,
|
||||
};
|
||||
|
||||
pub const Action = union(enum) {
|
||||
GoUp,
|
||||
Enter,
|
||||
SelectNext,
|
||||
SelectPrevious,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !void {
|
||||
pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !ActionResult {
|
||||
switch (action) {
|
||||
.GoUp => {
|
||||
if (appState.currentTab.currentLocation) |currentLocation| {
|
||||
@@ -6,14 +6,76 @@ pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !vo
|
||||
if (parent) |p| {
|
||||
const path = try arena.dupe(u8, p.path.path);
|
||||
try appState.currentTab.setCurrentLocation(.{ .path = path });
|
||||
return ActionResult.Handled;
|
||||
} else return error.NoParent;
|
||||
} else return error.NoCurrentLocation;
|
||||
},
|
||||
.Enter => unreachable,
|
||||
.Enter => {},
|
||||
.SelectNext => {
|
||||
return selectNextIndex(appState.currentTab, .Next);
|
||||
},
|
||||
.SelectPrevious => {
|
||||
return selectNextIndex(appState.currentTab, .Previous);
|
||||
},
|
||||
}
|
||||
|
||||
return ActionResult.None;
|
||||
}
|
||||
|
||||
const SelectStep = enum {
|
||||
Next,
|
||||
Previous,
|
||||
NextPage,
|
||||
PreviousPage,
|
||||
};
|
||||
|
||||
fn selectNextIndex(currentTab: *Tab, step: SelectStep) ActionResult {
|
||||
const index = blk: {
|
||||
currentTab.currentItems.mutex.lock();
|
||||
defer currentTab.currentItems.mutex.unlock();
|
||||
|
||||
const currentItems = currentTab.currentItems.data orelse return ActionResult.None;
|
||||
|
||||
if (currentTab.currentItem) |*currentItem| {
|
||||
const index = indexOf(Arc(*models.Item), models.FullName, currentItems.items, currentItem, arcFullNameEql);
|
||||
if (index) |i| {
|
||||
break :blk switch (step) {
|
||||
.Next => i +| 1,
|
||||
.Previous => i -| 1,
|
||||
.NextPage => i +| 8,
|
||||
.PreviousPage => i +| 8,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
break :blk 0;
|
||||
};
|
||||
|
||||
currentTab.selectItem(index) catch {
|
||||
//TODO
|
||||
};
|
||||
return ActionResult.Handled;
|
||||
}
|
||||
|
||||
fn arcFullNameEql(arcLhs: *const Arc(*models.Item), rhs: *const models.FullName) bool {
|
||||
const arcLhs2 = arcLhs.retain();
|
||||
defer if (arcLhs2.releaseUnwrap()) |i| i.deinit();
|
||||
|
||||
return models.FullName.eql(&arcLhs2.value.*.fullName, rhs);
|
||||
}
|
||||
|
||||
fn indexOf(comptime TSlice: type, comptime TItem: type, slice: []const TSlice, value: *const TItem, compare: *const fn (a: *const TSlice, b: *const TItem) bool) ?usize {
|
||||
for (0.., slice) |i, *item| {
|
||||
if (compare(item, value)) return i;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const Action = @import("action.zig").Action;
|
||||
const ActionResult = @import("action.zig").ActionResult;
|
||||
const AppState = @import("../app_state.zig").AppState;
|
||||
const RootProvider = @import("../provider/root.zig").RootProvider;
|
||||
const models = @import("../models.zig");
|
||||
const Arc = @import("zigrc").Arc;
|
||||
const Tab = @import("../tab/tab.zig").Tab;
|
||||
|
||||
@@ -80,6 +80,10 @@ pub const FullName = struct {
|
||||
|
||||
return FullName{ .path = path };
|
||||
}
|
||||
|
||||
pub fn eql(self: *const FullName, value: *const FullName) bool {
|
||||
return std.mem.eql(u8, self.path, value.path);
|
||||
}
|
||||
};
|
||||
|
||||
pub const NativePath = struct {
|
||||
|
||||
@@ -3,7 +3,7 @@ pub const Tab = struct {
|
||||
currentLocation: ?*Container,
|
||||
currentItems: locked(?std.ArrayList(Arc(*Item))),
|
||||
currentLocationChanged: Observable(?*Container),
|
||||
currentItemsChanged: bool = false,
|
||||
currentItem: ?models.FullName,
|
||||
threadPool: *std.Thread.Pool,
|
||||
rootProvider: *RootProvider,
|
||||
|
||||
@@ -18,6 +18,7 @@ pub const Tab = struct {
|
||||
.currentItems = .{ .data = null },
|
||||
.currentLocationChanged = Observable(?*Container).init(allocator),
|
||||
.currentLocation = null,
|
||||
.currentItem = null,
|
||||
.threadPool = threadPool,
|
||||
.rootProvider = rootProvider,
|
||||
};
|
||||
@@ -28,26 +29,54 @@ pub const Tab = struct {
|
||||
c.item.deinit();
|
||||
}
|
||||
|
||||
errdefer {
|
||||
self.currentLocation = null;
|
||||
self.currentLocationChanged.notify(null);
|
||||
if (self.currentItem) |i| {
|
||||
self.allocator.free(i.path);
|
||||
self.currentItem = null;
|
||||
}
|
||||
|
||||
const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator);
|
||||
errdefer {
|
||||
newLocation.deinit();
|
||||
}
|
||||
const newLocationContainer = blk: {
|
||||
const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator);
|
||||
errdefer {
|
||||
newLocation.deinit();
|
||||
self.currentLocation = null;
|
||||
self.currentLocationChanged.notify(null);
|
||||
}
|
||||
|
||||
const newLocationContainer = switch (newLocation.item) {
|
||||
.container => |c| c,
|
||||
.element => return error.NotContainer,
|
||||
const newLocationContainer = switch (newLocation.item) {
|
||||
.container => |c| c,
|
||||
.element => return error.NotContainer,
|
||||
};
|
||||
|
||||
self.currentLocation = newLocationContainer;
|
||||
break :blk newLocationContainer;
|
||||
};
|
||||
|
||||
self.currentLocation = newLocationContainer;
|
||||
self.currentLocationChanged.notify(newLocationContainer);
|
||||
|
||||
//TODO: Proper error handling
|
||||
std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable;
|
||||
|
||||
self.selectItem(0) catch {
|
||||
self.currentItem = null;
|
||||
};
|
||||
}
|
||||
|
||||
pub fn selectItem(self: *Tab, index: usize) !void {
|
||||
self.currentItems.mutex.lock();
|
||||
defer self.currentItems.mutex.unlock();
|
||||
|
||||
const currentItems = self.currentItems.data orelse return error.Error;
|
||||
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
||||
@@ -84,25 +113,25 @@ pub const Tab = struct {
|
||||
std.Thread.sleep(1 * std.time.ns_per_ms);
|
||||
}
|
||||
|
||||
for (location.children.items) |item| {
|
||||
const resolvedItem = location.item.provider.getItemByFullName(item, &.{ .skipChildInit = true }, self.allocator) catch |e| {
|
||||
for (location.children.items) |item_fullname| {
|
||||
const resolvedItem = location.item.provider.getItemByFullName(item_fullname, &.{ .skipChildInit = true }, self.allocator) catch |e| {
|
||||
//TODO: save error to container errors
|
||||
std.debug.print("error {} {s}\r\n", .{ e, item.path });
|
||||
std.debug.print("error {} {s}\r\n", .{ e, item_fullname.path });
|
||||
continue;
|
||||
};
|
||||
|
||||
self.currentItems.mutex.lock();
|
||||
defer self.currentItems.mutex.unlock();
|
||||
|
||||
// const arc = try Arc(*Item).init(self.allocator, resolvedItem);
|
||||
// try self.currentItems.data.?.append(arc);
|
||||
try self.currentItems.data.?.append(try Arc(*Item).init(self.allocator, resolvedItem));
|
||||
}
|
||||
|
||||
{
|
||||
self.currentItems.mutex.lock();
|
||||
defer self.currentItems.mutex.unlock();
|
||||
self.currentItemsChanged = true;
|
||||
const index = for (self.currentItems.data.?.items, 0..) |item, i| {
|
||||
if (compareByDisplayName(resolvedItem, item.value.*)) break i;
|
||||
} else null;
|
||||
const arc = try Arc(*Item).init(self.allocator, resolvedItem);
|
||||
if (index) |i| {
|
||||
try self.currentItems.data.?.insert(i, arc);
|
||||
} else {
|
||||
try self.currentItems.data.?.append(arc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +151,18 @@ pub const Tab = struct {
|
||||
currentItems.deinit();
|
||||
}
|
||||
|
||||
if (self.currentItem) |currentItem| {
|
||||
self.allocator.free(currentItem.path);
|
||||
}
|
||||
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
fn compareByDisplayName(lhs: *models.Item, rhs: *models.Item) bool {
|
||||
if (lhs.item == .container and rhs.item == .element) return true;
|
||||
if (lhs.item == .element and rhs.item == .container) return false;
|
||||
return std.mem.order(u8, lhs.displayName, rhs.displayName) == .lt;
|
||||
}
|
||||
};
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
Reference in New Issue
Block a user