Bot commited on
Commit
e2ef031
·
1 Parent(s): a375c71

feat: implement inline Eternity Mode status toggle and Priority settings control inside Tools dropdown menu

Browse files
src/components/tool-select-dropdown.tsx CHANGED
@@ -261,6 +261,10 @@ export function ToolSelectDropdown({
261
  <div className="py-1">
262
  <DropdownMenuSeparator />
263
  </div>
 
 
 
 
264
  <div className="py-2">
265
  <ToolPresets />
266
  <div className="py-1">
@@ -1087,3 +1091,142 @@ function ImageGeneratorSelector({
1087
  </DropdownMenuGroup>
1088
  );
1089
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  <div className="py-1">
262
  <DropdownMenuSeparator />
263
  </div>
264
+ <EternitySelector />
265
+ <div className="py-1">
266
+ <DropdownMenuSeparator />
267
+ </div>
268
  <div className="py-2">
269
  <ToolPresets />
270
  <div className="py-1">
 
1091
  </DropdownMenuGroup>
1092
  );
1093
  }
1094
+
1095
+ function EternitySelector() {
1096
+ const [activeProject, setActiveProject] = useState<{ project_name: string; is_active: boolean; priority: string } | null>(null);
1097
+ const [loading, setLoading] = useState(false);
1098
+
1099
+ const fetchStatus = async () => {
1100
+ try {
1101
+ const res = await fetch("/api/eternity");
1102
+ if (res.ok) {
1103
+ const data = await res.json();
1104
+ const projects = data.projects || [];
1105
+ // Find the active project, or default to the most recent project
1106
+ const active = projects.find((p: any) => p.is_active) || projects[0];
1107
+ if (active) {
1108
+ setActiveProject({
1109
+ project_name: active.project_name,
1110
+ is_active: active.is_active,
1111
+ priority: active.priority,
1112
+ });
1113
+ } else {
1114
+ setActiveProject(null);
1115
+ }
1116
+ }
1117
+ } catch (err) {
1118
+ console.error(err);
1119
+ }
1120
+ };
1121
+
1122
+ useEffect(() => {
1123
+ fetchStatus();
1124
+ }, []);
1125
+
1126
+ const handleToggle = async (checked: boolean) => {
1127
+ if (!activeProject) return;
1128
+ setLoading(true);
1129
+ try {
1130
+ const res = await fetch("/api/eternity", {
1131
+ method: "POST",
1132
+ headers: { "Content-Type": "application/json" },
1133
+ body: JSON.stringify({
1134
+ action: "toggle",
1135
+ project_name: activeProject.project_name,
1136
+ is_active: checked,
1137
+ }),
1138
+ });
1139
+ if (res.ok) {
1140
+ setActiveProject(prev => prev ? { ...prev, is_active: checked } : null);
1141
+ toast.success(`Eternity Mode ${checked ? "enabled" : "paused"}`);
1142
+ } else {
1143
+ throw new Error("Failed to update");
1144
+ }
1145
+ } catch (err: any) {
1146
+ toast.error(err.message);
1147
+ } finally {
1148
+ setLoading(false);
1149
+ }
1150
+ };
1151
+
1152
+ const handlePriorityChange = async (priority: string) => {
1153
+ if (!activeProject) return;
1154
+ setLoading(true);
1155
+ try {
1156
+ const res = await fetch("/api/eternity", {
1157
+ method: "POST",
1158
+ headers: { "Content-Type": "application/json" },
1159
+ body: JSON.stringify({
1160
+ action: "set-priority",
1161
+ project_name: activeProject.project_name,
1162
+ priority: priority,
1163
+ }),
1164
+ });
1165
+ if (res.ok) {
1166
+ setActiveProject(prev => prev ? { ...prev, priority: priority } : null);
1167
+ toast.success(`Priority updated to ${priority}`);
1168
+ } else {
1169
+ throw new Error("Failed to update");
1170
+ }
1171
+ } catch (err: any) {
1172
+ toast.error(err.message);
1173
+ } finally {
1174
+ setLoading(false);
1175
+ }
1176
+ };
1177
+
1178
+ if (!activeProject) {
1179
+ return (
1180
+ <DropdownMenuGroup>
1181
+ <DropdownMenuItem disabled className="text-xs font-semibold flex items-center gap-2 opacity-50">
1182
+ <Waypoints className="size-3.5" />
1183
+ Eternity Mode (No project)
1184
+ </DropdownMenuItem>
1185
+ </DropdownMenuGroup>
1186
+ );
1187
+ }
1188
+
1189
+ return (
1190
+ <DropdownMenuGroup>
1191
+ <DropdownMenuItem
1192
+ className="cursor-pointer font-semibold text-xs text-foreground flex items-center gap-2"
1193
+ onClick={(e) => {
1194
+ e.preventDefault();
1195
+ if (!loading) handleToggle(!activeProject.is_active);
1196
+ }}
1197
+ >
1198
+ <Waypoints className={cn("size-3.5", activeProject.is_active ? "text-primary animate-pulse" : "text-muted-foreground")} />
1199
+ <span className="truncate">Eternity Loop: {activeProject.project_name}</span>
1200
+ <Switch
1201
+ className="ml-auto"
1202
+ checked={activeProject.is_active}
1203
+ disabled={loading}
1204
+ />
1205
+ </DropdownMenuItem>
1206
+
1207
+ <DropdownMenuSub>
1208
+ <DropdownMenuSubTrigger className="text-xs flex items-center gap-2 font-semibold cursor-pointer pl-8">
1209
+ <span>Priority: {activeProject.priority.toUpperCase()}</span>
1210
+ </DropdownMenuSubTrigger>
1211
+ <DropdownMenuPortal>
1212
+ <DropdownMenuSubContent>
1213
+ <DropdownMenuItem
1214
+ className="cursor-pointer text-xs"
1215
+ onClick={() => handlePriorityChange("supreme")}
1216
+ disabled={loading}
1217
+ >
1218
+ 🚀 SUPREME
1219
+ </DropdownMenuItem>
1220
+ <DropdownMenuItem
1221
+ className="cursor-pointer text-xs"
1222
+ onClick={() => handlePriorityChange("low")}
1223
+ disabled={loading}
1224
+ >
1225
+ 💤 LOW
1226
+ </DropdownMenuItem>
1227
+ </DropdownMenuSubContent>
1228
+ </DropdownMenuPortal>
1229
+ </DropdownMenuSub>
1230
+ </DropdownMenuGroup>
1231
+ );
1232
+ }