地圖 (Jido) is a lightweight Unix TUI file explorer designed for speed and simplicity.
1const std = @import("std");
2
3const vaxis = @import("vaxis");
4
5const App = @import("app.zig");
6
7pub const Cache = struct {
8 mutex: std.Thread.Mutex = .{},
9 cache: std.StringHashMap(Image),
10};
11
12const Status = enum {
13 ready,
14 processing,
15 failed,
16};
17
18const Image = @This();
19
20///Only use on first transmission. Subsequent draws should use
21///`Image.image`.
22data: ?vaxis.zigimg.Image = null,
23image: ?vaxis.Image = null,
24path: ?[]const u8 = null,
25status: Status = .processing,
26
27pub fn deinit(self: Image, alloc: std.mem.Allocator, vx: vaxis.Vaxis, tty: *vaxis.Tty) void {
28 if (self.image) |image| {
29 vx.freeImage(tty.writer(), image.id);
30 }
31 if (self.data) |data| {
32 var d = data;
33 d.deinit(alloc);
34 }
35 if (self.path) |path| alloc.free(path);
36}
37
38pub fn processImage(alloc: std.mem.Allocator, app: *App, path: []const u8) error{ Unsupported, OutOfMemory }!void {
39 app.images.cache.put(path, .{ .path = path, .status = .processing }) catch {
40 const message = try std.fmt.allocPrint(alloc, "Failed to load image '{s}' - error occurred while attempting to add image to cache.", .{path});
41 defer alloc.free(message);
42 app.notification.write(message, .err) catch {};
43 if (app.file_logger) |file_logger| file_logger.write(message, .err) catch {};
44 return error.Unsupported;
45 };
46
47 const load_img_thread = std.Thread.spawn(.{}, loadImage, .{
48 alloc,
49 app,
50 path,
51 }) catch {
52 app.images.mutex.lock();
53 if (app.images.cache.getPtr(path)) |entry| {
54 entry.status = .failed;
55 }
56 app.images.mutex.unlock();
57
58 const message = try std.fmt.allocPrint(alloc, "Failed to load image '{s}' - error occurred while attempting to spawn processing thread.", .{path});
59 defer alloc.free(message);
60 app.notification.write(message, .err) catch {};
61 if (app.file_logger) |file_logger| file_logger.write(message, .err) catch {};
62
63 return error.Unsupported;
64 };
65 load_img_thread.detach();
66}
67
68fn loadImage(alloc: std.mem.Allocator, app: *App, path: []const u8) error{OutOfMemory}!void {
69 var buf: [(1024 * 1024) * 5]u8 = undefined; // 5mb
70 const data = vaxis.zigimg.Image.fromFilePath(alloc, path, &buf) catch {
71 app.images.mutex.lock();
72 if (app.images.cache.getPtr(path)) |entry| {
73 entry.status = .failed;
74 }
75 app.images.mutex.unlock();
76
77 const message = try std.fmt.allocPrint(alloc, "Failed to load image '{s}' - error occurred while attempting to read image from path.", .{path});
78 defer alloc.free(message);
79 app.notification.write(message, .err) catch {};
80 if (app.file_logger) |file_logger| file_logger.write(message, .err) catch {};
81
82 return;
83 };
84
85 app.images.mutex.lock();
86 if (app.images.cache.getPtr(path)) |entry| {
87 entry.status = .ready;
88 entry.data = data;
89 entry.path = path;
90 } else {
91 const message = try std.fmt.allocPrint(alloc, "Failed to load image '{s}' - error occurred while attempting to add image to cache.", .{path});
92 defer alloc.free(message);
93 app.notification.write(message, .err) catch {};
94 if (app.file_logger) |file_logger| file_logger.write(message, .err) catch {};
95 return;
96 }
97 app.images.mutex.unlock();
98
99 app.loop.postEvent(.image_ready);
100}