Spaces:
Sleeping
Sleeping
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 |
+
}
|