feat: selected's children

This commit is contained in:
2025-05-28 18:07:25 +02:00
parent a884c2066f
commit 53b93bad64
4 changed files with 229 additions and 52 deletions

View File

@@ -1,25 +1,30 @@
pub const UnknownTabError = error.UnknownTab;
pub const AppState = struct {
allocator: std.mem.Allocator,
currentTab: *Tab = undefined,
tabs: std.ArrayList(*Tab),
currentTabChanged: Observable(*Tab),
tabPreCurrentItemsUnload: Observable(*Tab),
tabChildrenLoaded: Observable(*Tab),
pub fn init(allocator: std.mem.Allocator) AppState {
return .{
.allocator = allocator,
.tabs = std.ArrayList(*Tab).init(allocator),
.currentTabChanged = Observable(*Tab).init(allocator),
.tabPreCurrentItemsUnload = Observable(*Tab).init(allocator),
.tabChildrenLoaded = Observable(*Tab).init(allocator),
};
}
pub fn addTab(self: *AppState, tab: *Tab) !void {
try self.tabs.append(tab);
// tab.preCurrentItemsUnload.attach(.{
// .ctx = @ptrCast(@alignCast(self)),
// .update = preCurrentItemsUnload,
// });
const tabChildrenLoadedHandlerObserver = try tab.childrenLoaded.allocator.create(Observer(*Tab));
tabChildrenLoadedHandlerObserver.* = Observer(*Tab){
.ctx = @ptrCast(@alignCast(self)),
.update = tabChildrenLoadedHandler,
};
try tab.childrenLoaded.attach(tabChildrenLoadedHandlerObserver);
}
pub fn setCurrentTab(self: *AppState, newTab: *Tab) !void {
@@ -34,8 +39,20 @@ pub const AppState = struct {
self.currentTabChanged.notify(newTab);
}
pub fn removeTab(self: *AppState, tab: *Tab) void {
const index = for (tab.childrenLoaded.observers, 0..) |observer, i| {
if (observer.ctx == self) break i;
} else null;
if (index) |i| {
tab.childrenLoaded.observers.swapRemove(i);
}
//TODO: remove from tabs
}
pub fn deinit(self: *AppState) void {
self.tabPreCurrentItemsUnload.deinit();
self.tabChildrenLoaded.deinit();
self.currentTabChanged.deinit();
for (self.tabs.items) |tab| {
tab.deinit();
@@ -43,12 +60,13 @@ pub const AppState = struct {
self.tabs.deinit();
}
fn preCurrentItemsUnload(ctx: *anyopaque, tab: *Tab) void {
const self: AppState = @ptrCast(@alignCast(ctx));
self.tabPreCurrentItemsUnload.notify(tab);
fn tabChildrenLoadedHandler(ctx: *anyopaque, tab: *Tab) void {
const self: *AppState = @ptrCast(@alignCast(ctx));
self.tabChildrenLoaded.notify(tab);
}
};
const std = @import("std");
const Tab = @import("tab/tab.zig").Tab;
const Observable = @import("observable.zig").Observable;
const Observer = @import("observable.zig").Observer;

View File

@@ -1,15 +1,20 @@
pub fn Observable(T: type) type {
return struct {
allocator: std.mem.Allocator,
observers: std.ArrayList(*const Observer(T)),
const Self = @This();
pub fn init(allocator: std.mem.Allocator) Self {
return .{
.allocator = allocator,
.observers = std.ArrayList(*const Observer(T)).init(allocator),
};
}
pub fn deinit(self: *Self) void {
for(self.observers)|o| {
self.allocator.destroy(o);
}
self.observers.deinit();
}

View File

@@ -3,6 +3,8 @@ pub const Tab = struct {
currentLocation: ?*Container,
currentItems: locked(?std.ArrayList(Arc(*Item))),
currentParentItems: locked(?std.ArrayList(Arc(*Item))),
currentChildren: locked(?std.ArrayList(Arc(*Item))),
childrenLoaded: Observable(*Tab),
currentLocationChanged: Observable(?*Container),
currentItemFullName: ?models.FullName,
currentItem: ?Arc(*models.Item),
@@ -21,7 +23,9 @@ pub const Tab = struct {
.allocator = allocator,
.currentItems = .{ .data = null },
.currentParentItems = .{ .data = null },
.currentChildren = .{ .data = null },
.currentLocationChanged = Observable(?*Container).init(allocator),
.childrenLoaded = Observable(*Tab).init(allocator),
.currentLocation = null,
.currentRequested = null,
.currentItem = null,
@@ -169,6 +173,13 @@ pub const Tab = struct {
self.currentItemFullName = models.FullName{
.path = try self.allocator.dupe(u8, arc.value.*.fullName.path),
};
switch (arc.value.*.item) {
.container => {
std.Thread.Pool.spawn(self.threadPool, loadChildrenWrapper, .{ self, arc.retain() }) catch unreachable;
},
else => {},
}
}
fn loadItemsWrapper(self: *Tab, location: *Container) void {
@@ -180,6 +191,7 @@ pub const Tab = struct {
fn loadParentItemsWrapper(self: *Tab, location: *Container) void {
const parentAbsolutePath = location.item.parent orelse return;
var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit();
const allocator = arena.allocator();
@@ -188,7 +200,7 @@ pub const Tab = struct {
.path = allocator.dupe(u8, parentAbsolutePath.path.path) catch return,
};
const resolvedParent = location.item.provider.getItemByFullName(parentFullName, &.{ .skipChildInit = true }, allocator) catch |e| {
const resolvedParent = location.item.provider.getItemByFullName(parentFullName, &.{}, allocator) catch |e| {
std.debug.print("error {} {s}\r\n", .{ e, parentFullName.path });
return;
};
@@ -196,9 +208,47 @@ pub const Tab = struct {
.container => |c| c,
else => return,
};
loadItems(*Tab, self, parentContainer, &self.currentParentItems, (struct {
fn a(_: *Tab) void {}
}).a, self.allocator) catch {};
loadItems(
void,
{},
parentContainer,
&self.currentParentItems,
(struct {
fn a(_: void) void {}
}).a,
self.allocator,
) catch {};
}
fn loadChildrenWrapper(self: *Tab, newSelectedItemArc: Arc(*models.Item)) void {
defer if (newSelectedItemArc.releaseUnwrap()) |item| item.deinit();
var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit();
const allocator = arena.allocator();
const resolvedChild = newSelectedItemArc.value.*.provider.getItemByFullName(newSelectedItemArc.value.*.fullName, &.{}, allocator) catch |e| {
std.debug.print("error {} {s}\r\n", .{ e, newSelectedItemArc.value.*.fullName.path });
return;
};
const childContainer = switch (resolvedChild.item) {
.container => |c| c,
else => return,
};
loadItems(
void,
{},
childContainer,
&self.currentChildren,
(struct {
fn a(_: void) void {}
}).a,
self.allocator,
) catch {};
self.childrenLoaded.notify(self);
}
pub fn deinit(self: *Tab) void {
@@ -217,10 +267,35 @@ pub const Tab = struct {
currentItems.deinit();
}
const data2 = self.currentParentItems.data;
self.currentParentItems.data = null;
if (data2) |currentItems| {
for (currentItems.items) |arc_item| {
if (arc_item.releaseUnwrap()) |item| {
item.deinit();
}
}
currentItems.deinit();
}
const data3 = self.currentChildren.data;
self.currentChildren.data = null;
if (data3) |currentItems| {
for (currentItems.items) |arc_item| {
if (arc_item.releaseUnwrap()) |item| {
item.deinit();
}
}
currentItems.deinit();
}
self.cleanCurrentItem();
self.cleanCurrentRequested();
self.currentLocationChanged.deinit();
self.childrenLoaded.deinit();
self.allocator.destroy(self);
}