-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprofile_ui_input.zig
More file actions
209 lines (179 loc) · 6.21 KB
/
profile_ui_input.zig
File metadata and controls
209 lines (179 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Profile UI Input Handler - Handles keyboard input for profile manager
const std = @import("std");
const profile_ui_state = @import("profile_ui_state");
const profile_manager = @import("profile_manager");
const ProfileUIState = profile_ui_state.ProfileUIState;
const ProfileUIMode = profile_ui_state.ProfileUIMode;
/// Result of input handling
pub const InputResult = enum {
@"continue", // Continue showing UI
close, // Close the UI
redraw, // Redraw the UI
profile_switched, // Profile was switched, close UI
};
/// Handle input for the profile UI
pub fn handleInput(
state: *ProfileUIState,
app: anytype,
input: []const u8,
) !InputResult {
switch (state.mode) {
.list => return try handleListInput(state, app, input),
.create => return try handleCreateInput(state, app, input),
.delete_confirm => return try handleDeleteConfirmInput(state, app, input),
}
}
/// Handle input in list mode
fn handleListInput(
state: *ProfileUIState,
app: anytype,
input: []const u8,
) !InputResult {
// Escape - close UI
if (std.mem.eql(u8, input, "\x1b")) {
return .close;
}
// Up arrow
if (std.mem.eql(u8, input, "\x1b[A")) {
state.selectPrevious();
return .redraw;
}
// Down arrow or Tab - move down
if (std.mem.eql(u8, input, "\x1b[B") or std.mem.eql(u8, input, "\t")) {
state.selectNext();
return .redraw;
}
// Shift+Tab - move up
if (std.mem.eql(u8, input, "\x1b[Z")) {
state.selectPrevious();
return .redraw;
}
// Enter - switch to selected profile
if (std.mem.eql(u8, input, "\r") or std.mem.eql(u8, input, "\n")) {
if (state.getSelectedProfile()) |profile_name| {
// Check if already active
if (std.mem.eql(u8, profile_name, state.active_profile_name)) {
std.debug.print("Already using profile: {s}\n", .{profile_name});
return .redraw;
}
// Check if streaming
if (app.streaming_active) {
std.debug.print("Cannot switch profiles while streaming.\n", .{});
return .redraw;
}
// Switch profile
try profile_manager.switchActiveProfile(app, profile_name);
std.debug.print("✓ Switched to profile: {s}\n", .{profile_name});
return .profile_switched;
}
return .redraw;
}
// C/c - create new profile
if (std.mem.eql(u8, input, "c") or std.mem.eql(u8, input, "C")) {
state.enterCreateMode();
return .redraw;
}
// D/d - delete profile
if (std.mem.eql(u8, input, "d") or std.mem.eql(u8, input, "D")) {
if (state.getSelectedProfile()) |profile_name| {
// Check if it's the active profile
if (std.mem.eql(u8, profile_name, state.active_profile_name)) {
std.debug.print("Cannot delete active profile. Switch to another profile first.\n", .{});
return .redraw;
}
// Check if it's the last profile
if (state.profiles.len <= 1) {
std.debug.print("Cannot delete the last remaining profile.\n", .{});
return .redraw;
}
try state.enterDeleteMode();
return .redraw;
}
return .redraw;
}
return .@"continue";
}
/// Handle input in create mode
fn handleCreateInput(
state: *ProfileUIState,
app: anytype,
input: []const u8,
) !InputResult {
// Escape - cancel
if (std.mem.eql(u8, input, "\x1b")) {
state.cancelCreate();
return .redraw;
}
// Enter - create profile
if (std.mem.eql(u8, input, "\r") or std.mem.eql(u8, input, "\n")) {
const profile_name = state.create_buffer.items;
if (profile_name.len == 0) {
std.debug.print("Profile name cannot be empty.\n", .{});
return .redraw;
}
// Validate name
if (!profile_manager.validateProfileName(profile_name)) {
std.debug.print("Invalid profile name. Use only alphanumeric characters, dashes, and underscores.\n", .{});
return .redraw;
}
// Check if already exists
for (state.profiles) |existing| {
if (std.mem.eql(u8, existing, profile_name)) {
std.debug.print("Profile '{s}' already exists.\n", .{profile_name});
return .redraw;
}
}
// Create profile (save current config)
try profile_manager.saveProfile(state.allocator, profile_name, app.config);
std.debug.print("✓ Created profile: {s}\n", .{profile_name});
// Refresh profile list
try state.refreshProfiles();
// Return to list mode
state.cancelCreate();
return .redraw;
}
// Backspace
if (std.mem.eql(u8, input, "\x7f") or std.mem.eql(u8, input, "\x08")) {
if (state.create_buffer.items.len > 0) {
_ = state.create_buffer.pop();
return .redraw;
}
return .@"continue";
}
// Regular character input
if (input.len == 1) {
const c = input[0];
// Only allow printable ASCII characters
if (c >= 32 and c <= 126) {
try state.create_buffer.append(state.allocator, c);
return .redraw;
}
}
return .@"continue";
}
/// Handle input in delete confirmation mode
fn handleDeleteConfirmInput(
state: *ProfileUIState,
_: anytype,
input: []const u8,
) !InputResult {
// Escape or N/n - cancel
if (std.mem.eql(u8, input, "\x1b") or std.mem.eql(u8, input, "n") or std.mem.eql(u8, input, "N")) {
state.cancelDelete();
return .redraw;
}
// Y/y - confirm deletion
if (std.mem.eql(u8, input, "y") or std.mem.eql(u8, input, "Y")) {
if (state.profile_to_delete) |profile_name| {
try profile_manager.deleteProfile(state.allocator, profile_name);
std.debug.print("✓ Deleted profile: {s}\n", .{profile_name});
// Refresh profile list
try state.refreshProfiles();
// Return to list mode
state.cancelDelete();
return .redraw;
}
return .redraw;
}
return .@"continue";
}