From a884c2066f5748f579e734dbdfeafe19717c5943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Wed, 28 May 2025 11:55:03 +0200 Subject: [PATCH] feat(core): load parent's children --- src/core/tab/tab.zig | 160 ++++++++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 63 deletions(-) diff --git a/src/core/tab/tab.zig b/src/core/tab/tab.zig index d1244cb..0821ef7 100644 --- a/src/core/tab/tab.zig +++ b/src/core/tab/tab.zig @@ -64,6 +64,7 @@ pub const Tab = struct { //TODO: Proper error handling std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable; + std.Thread.Pool.spawn(self.threadPool, loadParentItemsWrapper, .{ self, newLocationContainer }) catch unreachable; } pub fn selectItem(self: *Tab, requested_selected: models.FullName) !void { @@ -171,73 +172,33 @@ pub const Tab = struct { } fn loadItemsWrapper(self: *Tab, location: *Container) void { - loadItems(self, location) catch return; + loadItems(*Tab, self, location, &self.currentItems, updateCurrentItemCallback, self.allocator) catch {}; + } + fn updateCurrentItemCallback(self: *Tab) void { + self.updateCurrentItem() catch {}; } - fn loadItems(self: *Tab, location: *Container) !void { - { - self.currentItems.mutex.lock(); - defer self.currentItems.mutex.unlock(); - const data = self.currentItems.data; - self.currentItems.data = null; - if (data) |currentItems| { - for (currentItems.items) |*item| { - if (item.releaseUnwrap()) |i| i.deinit(); - } - currentItems.deinit(); - } - } + 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(); - { - self.currentItems.mutex.lock(); - defer self.currentItems.mutex.unlock(); + const parentFullName = models.FullName{ + .path = allocator.dupe(u8, parentAbsolutePath.path.path) catch return, + }; - self.currentItems.data = std.ArrayList(Arc(*Item)).init(self.allocator); - } - errdefer { - self.currentItems.data.?.deinit(); - self.currentItems.data = null; - } - - //TODO: add async - //NOTE: also we should - var processed_number: usize = 0; - while (true) { - std.Thread.sleep(100 * std.time.ns_per_ms); - - location.children.mutex.lock(); - defer location.children.mutex.unlock(); - - std.debug.assert(processed_number <= location.children.data.items.len); - - if (!location.childrenLoading and processed_number == location.children.data.items.len) break; - if (processed_number == location.children.data.items.len) continue; - - defer processed_number = location.children.data.items.len; - for (location.children.data.items[processed_number..]) |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_fullname.path }); - continue; - }; - - self.currentItems.mutex.lock(); - defer self.currentItems.mutex.unlock(); - - const insertIndex = for (self.currentItems.data.?.items, 0..) |*item, i| { - if (order.orderByDisplayName(resolvedItem, item.value.*) == .lt) break i; - } else null; - - const arc = try Arc(*Item).init(self.allocator, resolvedItem); - if (insertIndex) |i| { - try self.currentItems.data.?.insert(i, arc); - } else { - try self.currentItems.data.?.append(arc); - } - - self.updateCurrentItem() catch {}; - } - } + const resolvedParent = location.item.provider.getItemByFullName(parentFullName, &.{ .skipChildInit = true }, allocator) catch |e| { + std.debug.print("error {} {s}\r\n", .{ e, parentFullName.path }); + return; + }; + const parentContainer = switch (resolvedParent.item) { + .container => |c| c, + else => return, + }; + loadItems(*Tab, self, parentContainer, &self.currentParentItems, (struct { + fn a(_: *Tab) void {} + }).a, self.allocator) catch {}; } pub fn deinit(self: *Tab) void { @@ -276,6 +237,79 @@ pub const Tab = struct { } }; +fn loadItems( + comptime T: type, + ctx: T, + location: *Container, + sourceItems: *locked(?std.ArrayList(Arc(*Item))), + itemLoadedCallback: *const fn (T) void, + allocator: std.mem.Allocator, +) !void { + { + sourceItems.mutex.lock(); + defer sourceItems.mutex.unlock(); + + const data = sourceItems.data; + sourceItems.data = null; + if (data) |currentItems| { + for (currentItems.items) |*item| { + if (item.releaseUnwrap()) |i| i.deinit(); + } + currentItems.deinit(); + } + } + + { + sourceItems.mutex.lock(); + defer sourceItems.mutex.unlock(); + + sourceItems.data = std.ArrayList(Arc(*Item)).init(allocator); + } + errdefer { + sourceItems.data.?.deinit(); + sourceItems.data = null; + } + + //TODO: add async + var processed_number: usize = 0; + while (true) { + std.Thread.sleep(100 * std.time.ns_per_ms); + + location.children.mutex.lock(); + defer location.children.mutex.unlock(); + + std.debug.assert(processed_number <= location.children.data.items.len); + + if (!location.childrenLoading and processed_number == location.children.data.items.len) break; + if (processed_number == location.children.data.items.len) continue; + + defer processed_number = location.children.data.items.len; + for (location.children.data.items[processed_number..]) |item_fullname| { + const resolvedItem = location.item.provider.getItemByFullName(item_fullname, &.{ .skipChildInit = true }, allocator) catch |e| { + //TODO: save error to container errors + std.debug.print("error {} {s}\r\n", .{ e, item_fullname.path }); + continue; + }; + + sourceItems.mutex.lock(); + defer sourceItems.mutex.unlock(); + + const insertIndex = for (sourceItems.data.?.items, 0..) |*item, i| { + if (order.orderByDisplayName(resolvedItem, item.value.*) == .lt) break i; + } else null; + + const arc = try Arc(*Item).init(allocator, resolvedItem); + if (insertIndex) |i| { + try sourceItems.data.?.insert(i, arc); + } else { + try sourceItems.data.?.append(arc); + } + + itemLoadedCallback(ctx); + } + } +} + const std = @import("std"); const assert = std.debug.assert; const Mutex = std.Thread.Mutex;