feat: cleanup appstate, move sort to tab

This commit is contained in:
2025-05-26 17:22:23 +02:00
parent c4c901f1d4
commit 095b8659d6
9 changed files with 270 additions and 159 deletions

View File

@@ -1,8 +1,8 @@
/// Our main application state
const Model = struct {
crash: bool = false,
allocator: std.mem.Allocator,
current_items_view: *vxfw.ListView,
current_items_view_widget: vxfw.Widget,
app_common_model: *AppCommonModel,
root_provider: *RootProvider,
@@ -11,15 +11,15 @@ const Model = struct {
return .{
.userdata = self,
.eventHandler = Model.typeErasedEventHandler,
.captureHandler = Model.typeErasedCaptureHandler,
.drawFn = Model.typeErasedDrawFn,
};
}
/// This function will be called from the vxfw runtime.
fn typeErasedEventHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void {
const vm: *Model = @ptrCast(@alignCast(ptr));
switch (event) {
.init => return ctx.requestFocus(vm.current_items_view.widget()),
.init => return ctx.requestFocus(vm.current_items_view_widget),
.key_press => |key| {
if (key.matches('c', .{ .ctrl = true })) {
ctx.quit = true;
@@ -28,18 +28,27 @@ const Model = struct {
if (key.matches('r', .{})) {
// vm.crash = true;
ctx.redraw = true;
return ctx.requestFocus(vm.current_items_view.widget());
return ctx.requestFocus(vm.current_items_view_widget);
}
// if (key.matches(vaxis.Key.left, .{})) {
// ctx.redraw = true;
// return ctx.requestFocus(vm.current_items_view.widget());
// }
},
.focus_in => return ctx.requestFocus(vm.current_items_view_widget),
else => {},
}
}
fn typeErasedCaptureHandler(ptr: *anyopaque, ctx: *vxfw.EventContext, event: vxfw.Event) anyerror!void {
const vm: *Model = @ptrCast(@alignCast(ptr));
switch (event) {
.key_press => |key| {
var arena = std.heap.ArenaAllocator.init(vm.allocator);
defer arena.deinit();
handle_key(key, &vm.app_common_model.appState, arena.allocator()) catch {};
const result = handle_key(key, &vm.app_common_model.appState, arena.allocator()) catch null;
if (result) |r| {
if (r == ActionResult.Handled) {
ctx.consumeAndRedraw();
}
}
},
.focus_in => return ctx.requestFocus(vm.current_items_view.widget()),
else => {},
}
}
@@ -80,8 +89,7 @@ const Model = struct {
const currentItemsTop = 1;
const list_surface: vxfw.SubSurface = .{
.origin = .{ .row = currentItemsTop, .col = parentItemsWidth },
.surface = try vm.current_items_view
.widget()
.surface = try vm.current_items_view_widget
.draw(ctx.withConstraints(ctx.min, .{
.width = currentItemsWidth,
.height = ctx.max.height.? - currentItemsTop,
@@ -90,23 +98,77 @@ const Model = struct {
};
try rootWidgets.append(list_surface);
const current_location_text = if (vm.app_common_model.appState.currentTab.currentLocation) |loc| loc.item.fullName.path else "";
const current_location_text_element = try ctx.arena.create(vxfw.Text);
current_location_text_element.* = vxfw.Text{
.text = current_location_text,
.overflow = .clip,
.softwrap = false,
.style = .{
.fg = .{ .index = 4 },
},
};
const current_location_text_surface: vxfw.SubSurface = .{
.origin = .{ .row = 0, .col = 0 },
.surface = try current_location_text_element.widget().draw(ctx),
// .surface = try vm.current_items.widget().draw(ctx),
};
const header = try ctx.arena.create(std.ArrayList(vxfw.Widget));
header.* = std.ArrayList(vxfw.Widget).init(ctx.arena);
try rootWidgets.append(current_location_text_surface);
{
const current_location_text = if (vm.app_common_model.appState.currentTab.currentLocation) |loc|
try std.fmt.allocPrint(ctx.arena, "{s} ", .{loc.item.fullName.path})
else
"";
const current_location_text_element = try ctx.arena.create(vxfw.Text);
current_location_text_element.* = vxfw.Text{
.text = current_location_text,
.overflow = .clip,
.softwrap = false,
.style = .{
.fg = .{ .index = 4 },
},
};
try header.append(current_location_text_element.widget());
}
{
const currentTab = vm.app_common_model.appState.currentTab;
if (currentTab.currentItem) |currentItem| {
currentTab.currentItems.mutex.lock();
defer currentTab.currentItems.mutex.unlock();
if (currentTab.currentItems.data) |currentItems| {
const current_item_text =
for (currentItems.items) |item| {
const arc_item = item.retain();
defer if (arc_item.releaseUnwrap()) |i| i.deinit();
if (models.FullName.eql(&arc_item.value.*.fullName, &currentItem)) {
break try std.fmt.allocPrint(ctx.arena, "{s} ", .{arc_item.value.*.displayName});
}
} else "";
const current_item_text_element = try ctx.arena.create(vxfw.Text);
current_item_text_element.* = vxfw.Text{
.text = current_item_text,
.overflow = .clip,
.softwrap = false,
.style = .{
.fg = .{ .index = 4 },
},
};
try header.append(current_item_text_element.widget());
}
}
}
{
const head_items = try ctx.arena.alloc(vxfw.FlexItem, header.items.len);
for (0.., header.items) |i, item| {
head_items[i] = vxfw.FlexItem{
.widget = item,
.flex = 0,
};
}
const header_element = try ctx.arena.create(vxfw.FlexRow);
header_element.* = .{ .children = head_items };
const flex_column_surface: vxfw.SubSurface = .{
.origin = .{ .row = 0, .col = 0 },
.surface = try header_element.widget().draw(ctx),
};
try rootWidgets.append(flex_column_surface);
}
return .{
.size = max_size,
@@ -120,20 +182,32 @@ const Model = struct {
if (vm.crash) @panic("asd123");
const text_items = blk2: {
vm.app_common_model.current_items.mutex.lock();
defer vm.app_common_model.current_items.mutex.unlock();
const currentTab = vm.app_common_model.appState.currentTab;
const current_full_name = if (currentTab.currentItem) |currentItem|
models.FullName{ .path = try ctx.arena.dupe(u8, currentItem.path) }
else
null;
break :blk2 if (vm.app_common_model.current_items.data) |items| blk: {
currentTab.currentItems.mutex.lock();
defer currentTab.currentItems.mutex.unlock();
break :blk2 if (currentTab.currentItems.data) |items| blk: {
const children = try ctx.arena.create(std.ArrayList(*vxfw.Text));
children.* = std.ArrayList(*vxfw.Text).init(ctx.arena);
// const current_index = vm.current_items_view.cursor;
// const children = try ctx.arena.alloc(*vxfw.Text, items.len);
for (0.., items) |i, *weak_child| {
const arc_child = weak_child.upgrade() orelse continue;
for (items.items) |*original_arc_child| {
const arc_child = original_arc_child.retain();
defer if (arc_child.releaseUnwrap()) |item| item.deinit();
const child = arc_child.value.*;
const is_active = i == vm.current_items_view.cursor;
// const is_active = i == current_index;
const is_active = if (current_full_name) |c_full_name|
models.FullName.eql(&c_full_name, &child.fullName)
else
false;
const fg, const bg = colors: {
var fg: vaxis.Color = .default;
@@ -271,6 +345,10 @@ pub fn main() !void {
.draw_cursor = false,
.children = .{ .slice = items },
};
var list_widget = list.widget();
list_widget.eventHandler = struct {
fn a(_: *anyopaque, _: *vxfw.EventContext, _: vxfw.Event) anyerror!void {}
}.a;
var appState: AppState = AppState.init(allocator);
try appState.addTab(tab1);
@@ -287,13 +365,12 @@ pub fn main() !void {
.allocator = allocator,
.app_common_model = &app_common_model,
.current_items_view = &list,
.current_items_view_widget = list_widget,
.root_provider = &rootProvider,
};
model.app_common_model.usage_number.data += 1;
try pool.spawn(core.data_loop, .{model.app_common_model});
var app = try vxfw.App.init(allocator);
defer app.deinit();
@@ -313,12 +390,12 @@ const vaxis = @import("vaxis");
const vxfw = vaxis.vxfw;
const models = @import("../core/models.zig");
const ActionResult = @import("../core/action/action.zig").ActionResult;
const provider = @import("../core/provider/provider.zig");
const RootProvider = @import("../core/provider/root.zig").RootProvider;
const local_provider = @import("../core/provider/local.zig");
const Tab = @import("../core/tab/tab.zig").Tab;
const locked = @import("../core/sync.zig").locked;
const AppCommonModel = @import("../app_common/Model.zig");
const core = @import("../app_common/root.zig");
const AppState = @import("../core/app_state.zig").AppState;
const handle_key = @import("./action_map.zig").handle_key;