From 1c0004a5d5222b4592df6f99b17f970e0e3e71b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Tue, 27 May 2025 17:48:47 +0200 Subject: [PATCH] feat(core): incrementally load items --- src/core/models.zig | 15 +++++----- src/core/provider/local.zig | 9 ++++-- src/core/tab/tab.zig | 55 +++++++++++++++++++++++-------------- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/core/models.zig b/src/core/models.zig index 72221a9..29ea3e8 100644 --- a/src/core/models.zig +++ b/src/core/models.zig @@ -1,7 +1,3 @@ -const std = @import("std"); -const Provider = @import("provider/provider.zig").Provider; -const consts = @import("consts.zig"); - pub const Item = struct { allocator: std.mem.Allocator, provider: Provider, @@ -52,13 +48,13 @@ pub const Element = struct { pub const Container = struct { item: Item, - children: std.ArrayList(FullName), + children: locked(std.ArrayList(FullName)), childrenLoading: bool, fn deinit(self: *Container) void { - for (self.children.items) |itemFullName| { + for (self.children.data.items) |itemFullName| { self.item.allocator.free(itemFullName.path); } - self.children.deinit(); + self.children.data.deinit(); self.item.allocator.destroy(self); } }; @@ -103,3 +99,8 @@ pub const AbsolutePathType = union(enum) { container, item, }; + +const std = @import("std"); +const Provider = @import("provider/provider.zig").Provider; +const consts = @import("consts.zig"); +const locked = @import("./sync.zig").locked; diff --git a/src/core/provider/local.zig b/src/core/provider/local.zig index ea1a4f6..b6a0d3d 100644 --- a/src/core/provider/local.zig +++ b/src/core/provider/local.zig @@ -18,7 +18,9 @@ fn loadChildren(container: *Container) void { while (it.next() catch return) |entry| { const child = container.item.fullName.getChild(entry.name, container.item.allocator) catch return; - container.children.append(child) catch return; + container.children.mutex.lock(); + defer container.children.mutex.unlock(); + container.children.data.append(child) catch return; } } @@ -108,7 +110,9 @@ pub const LocalContentProvider = struct { .directory => blk: { const container = try allocator.create(Container); container.* = Container{ - .children = std.ArrayList(FullName).init(allocator), + .children = locked(std.ArrayList(FullName)){ + .data = std.ArrayList(FullName).init(allocator), + }, .childrenLoading = true, .item = undefined, }; @@ -214,3 +218,4 @@ const ItemEnum = models.ItemEnum; const Element = models.Element; const Container = models.Container; const native_os = @import("builtin").os.tag; +const locked = @import("../sync.zig").locked; diff --git a/src/core/tab/tab.zig b/src/core/tab/tab.zig index 6e6117d..d1244cb 100644 --- a/src/core/tab/tab.zig +++ b/src/core/tab/tab.zig @@ -2,6 +2,7 @@ pub const Tab = struct { allocator: std.mem.Allocator, currentLocation: ?*Container, currentItems: locked(?std.ArrayList(Arc(*Item))), + currentParentItems: locked(?std.ArrayList(Arc(*Item))), currentLocationChanged: Observable(?*Container), currentItemFullName: ?models.FullName, currentItem: ?Arc(*models.Item), @@ -19,6 +20,7 @@ pub const Tab = struct { self.* = Tab{ .allocator = allocator, .currentItems = .{ .data = null }, + .currentParentItems = .{ .data = null }, .currentLocationChanged = Observable(?*Container).init(allocator), .currentLocation = null, .currentRequested = null, @@ -198,32 +200,43 @@ pub const Tab = struct { } //TODO: add async - while (location.childrenLoading) { - std.Thread.sleep(1 * std.time.ns_per_ms); - } + //NOTE: also we should + var processed_number: usize = 0; + while (true) { + std.Thread.sleep(100 * std.time.ns_per_ms); - 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_fullname.path }); - continue; - }; + location.children.mutex.lock(); + defer location.children.mutex.unlock(); - self.currentItems.mutex.lock(); - defer self.currentItems.mutex.unlock(); + std.debug.assert(processed_number <= location.children.data.items.len); - const insertIndex = for (self.currentItems.data.?.items, 0..) |*item, i| { - if (order.orderByDisplayName(resolvedItem, item.value.*) == .lt) break i; - } else null; + if (!location.childrenLoading and processed_number == location.children.data.items.len) break; + if (processed_number == location.children.data.items.len) continue; - 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); + 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 {}; } - - self.updateCurrentItem() catch {}; } }