This commit is contained in:
Ivan Neplokhov 2026-01-21 10:59:51 +04:00
parent 9a82153e9a
commit c1c32c7955
4 changed files with 132 additions and 39 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "telegram-invite-automation", "name": "telegram-invite-automation",
"version": "1.0.0", "version": "1.1.0",
"private": true, "private": true,
"description": "Automated user parsing and invites for Telegram groups", "description": "Automated user parsing and invites for Telegram groups",
"main": "src/main/index.js", "main": "src/main/index.js",

View File

@ -2454,8 +2454,15 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.dailyLimit} value={taskForm.dailyLimit === "" ? "" : taskForm.dailyLimit}
onChange={(event) => setTaskForm({ ...taskForm, dailyLimit: Number(event.target.value) })} onChange={(event) => {
const value = event.target.value;
setTaskForm({ ...taskForm, dailyLimit: value === "" ? "" : Number(value) });
}}
onBlur={() => {
const value = Number(taskForm.dailyLimit);
setTaskForm({ ...taskForm, dailyLimit: Number.isFinite(value) && value > 0 ? value : 1 });
}}
/> />
</label> </label>
<label> <label>
@ -2463,8 +2470,15 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.historyLimit} value={taskForm.historyLimit === 0 ? "" : taskForm.historyLimit}
onChange={(event) => setTaskForm({ ...taskForm, historyLimit: Number(event.target.value) })} onChange={(event) => {
const value = event.target.value;
setTaskForm({ ...taskForm, historyLimit: value === "" ? "" : Number(value) });
}}
onBlur={() => {
const value = Number(taskForm.historyLimit);
setTaskForm({ ...taskForm, historyLimit: Number.isFinite(value) && value > 0 ? value : 1 });
}}
/> />
</label> </label>
<label className="checkbox"> <label className="checkbox">
@ -2481,8 +2495,15 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.warmupStartLimit} value={taskForm.warmupStartLimit === "" ? "" : taskForm.warmupStartLimit}
onChange={(event) => setTaskForm({ ...taskForm, warmupStartLimit: Number(event.target.value) })} onChange={(event) => {
const value = event.target.value;
setTaskForm({ ...taskForm, warmupStartLimit: value === "" ? "" : Number(value) });
}}
onBlur={() => {
const value = Number(taskForm.warmupStartLimit);
setTaskForm({ ...taskForm, warmupStartLimit: Number.isFinite(value) && value > 0 ? value : 1 });
}}
disabled={!taskForm.warmupEnabled} disabled={!taskForm.warmupEnabled}
/> />
</label> </label>
@ -2491,8 +2512,15 @@ export default function App() {
<input <input
type="number" type="number"
min="0" min="0"
value={taskForm.warmupDailyIncrease} value={taskForm.warmupDailyIncrease === "" ? "" : taskForm.warmupDailyIncrease}
onChange={(event) => setTaskForm({ ...taskForm, warmupDailyIncrease: Number(event.target.value) })} onChange={(event) => {
const value = event.target.value;
setTaskForm({ ...taskForm, warmupDailyIncrease: value === "" ? "" : Number(value) });
}}
onBlur={() => {
const value = Number(taskForm.warmupDailyIncrease);
setTaskForm({ ...taskForm, warmupDailyIncrease: Number.isFinite(value) && value >= 0 ? value : 0 });
}}
disabled={!taskForm.warmupEnabled} disabled={!taskForm.warmupEnabled}
/> />
</label> </label>
@ -2574,12 +2602,22 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.maxCompetitorBots} value={taskForm.maxCompetitorBots === "" ? "" : taskForm.maxCompetitorBots}
onChange={(event) => { onChange={(event) => {
const nextValue = Number(event.target.value); const value = event.target.value;
if (value === "") {
setTaskForm({ ...taskForm, maxCompetitorBots: "", maxOurBots: "" });
return;
}
const nextValue = Number(value);
const nextForm = { ...taskForm, maxCompetitorBots: nextValue, maxOurBots: nextValue }; const nextForm = { ...taskForm, maxCompetitorBots: nextValue, maxOurBots: nextValue };
setTaskForm(sanitizeTaskForm(nextForm)); setTaskForm(sanitizeTaskForm(nextForm));
}} }}
onBlur={() => {
const value = Number(taskForm.maxCompetitorBots);
const normalized = Number.isFinite(value) && value > 0 ? value : 1;
setTaskForm(sanitizeTaskForm({ ...taskForm, maxCompetitorBots: normalized, maxOurBots: normalized }));
}}
/> />
<span className="hint">Одинаковое количество для конкурентов и нашей группы.</span> <span className="hint">Одинаковое количество для конкурентов и нашей группы.</span>
</label> </label>
@ -2590,11 +2628,17 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.maxCompetitorBots} value={taskForm.maxCompetitorBots === "" ? "" : taskForm.maxCompetitorBots}
onChange={(event) => { onChange={(event) => {
const nextValue = Number(event.target.value); const value = event.target.value;
const nextForm = { ...taskForm, maxCompetitorBots: nextValue }; setTaskForm({
setTaskForm(nextForm); ...taskForm,
maxCompetitorBots: value === "" ? "" : Number(value)
});
}}
onBlur={() => {
const value = Number(taskForm.maxCompetitorBots);
setTaskForm({ ...taskForm, maxCompetitorBots: Number.isFinite(value) && value > 0 ? value : 1 });
}} }}
/> />
<span className="hint">Используется для авто-вступления в группы конкурентов.</span> <span className="hint">Используется для авто-вступления в группы конкурентов.</span>
@ -2604,8 +2648,15 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.maxOurBots} value={taskForm.maxOurBots === "" ? "" : taskForm.maxOurBots}
onChange={(event) => setTaskForm({ ...taskForm, maxOurBots: Number(event.target.value) })} onChange={(event) => {
const value = event.target.value;
setTaskForm({ ...taskForm, maxOurBots: value === "" ? "" : Number(value) });
}}
onBlur={() => {
const value = Number(taskForm.maxOurBots);
setTaskForm({ ...taskForm, maxOurBots: Number.isFinite(value) && value > 0 ? value : 1 });
}}
/> />
<span className="hint"> <span className="hint">
{roleMode === "split" ? "Ограничивает аккаунты, которые будут приглашать." : "Ограничивает количество инвайтящих аккаунтов."} {roleMode === "split" ? "Ограничивает аккаунты, которые будут приглашать." : "Ограничивает количество инвайтящих аккаунтов."}
@ -2686,8 +2737,15 @@ export default function App() {
<input <input
type="number" type="number"
min="1" min="1"
value={taskForm.stopBlockedPercent} value={taskForm.stopBlockedPercent === "" ? "" : taskForm.stopBlockedPercent}
onChange={(event) => setTaskForm({ ...taskForm, stopBlockedPercent: Number(event.target.value) })} onChange={(event) => {
const value = event.target.value;
setTaskForm({ ...taskForm, stopBlockedPercent: value === "" ? "" : Number(value) });
}}
onBlur={() => {
const value = Number(taskForm.stopBlockedPercent);
setTaskForm({ ...taskForm, stopBlockedPercent: Number.isFinite(value) && value > 0 ? value : 1 });
}}
disabled={!taskForm.stopOnBlocked} disabled={!taskForm.stopOnBlocked}
/> />
</label> </label>

View File

@ -480,37 +480,37 @@ body {
} }
.action-bar { .action-bar {
padding: 14px; padding: 8px 10px;
gap: 10px; gap: 6px;
} }
.action-bar h2 { .action-bar h2 {
font-size: 16px; font-size: 14px;
} }
.action-bar .status-caption { .action-bar .status-caption {
font-size: 11px; font-size: 10px;
} }
.action-bar .status-pill { .action-bar .status-pill {
font-size: 11px; font-size: 10px;
padding: 4px 10px; padding: 3px 8px;
} }
.action-buttons .cta { .action-buttons .cta {
margin-left: auto; margin-left: auto;
padding: 6px 12px; padding: 4px 8px;
border-radius: 999px; border-radius: 999px;
font-weight: 600; font-weight: 600;
} }
.action-buttons .cta + .cta { .action-buttons .cta + .cta {
margin-left: 10px; margin-left: 8px;
} }
.action-buttons button { .action-buttons button {
padding: 6px 10px; padding: 4px 8px;
font-size: 12px; font-size: 11px;
} }
.status-pill { .status-pill {

View File

@ -10,8 +10,15 @@ function SettingsTab({ settings, onSettingsChange, saveSettings }) {
<input <input
type="number" type="number"
min="1" min="1"
value={settings.accountMaxGroups} value={settings.accountMaxGroups === "" ? "" : settings.accountMaxGroups}
onChange={(event) => onSettingsChange("accountMaxGroups", Number(event.target.value))} onChange={(event) => {
const value = event.target.value;
onSettingsChange("accountMaxGroups", value === "" ? "" : Number(value));
}}
onBlur={() => {
const value = Number(settings.accountMaxGroups);
onSettingsChange("accountMaxGroups", Number.isFinite(value) && value > 0 ? value : 1);
}}
/> />
</label> </label>
<label> <label>
@ -19,8 +26,15 @@ function SettingsTab({ settings, onSettingsChange, saveSettings }) {
<input <input
type="number" type="number"
min="1" min="1"
value={settings.accountDailyLimit} value={settings.accountDailyLimit === "" ? "" : settings.accountDailyLimit}
onChange={(event) => onSettingsChange("accountDailyLimit", Number(event.target.value))} onChange={(event) => {
const value = event.target.value;
onSettingsChange("accountDailyLimit", value === "" ? "" : Number(value));
}}
onBlur={() => {
const value = Number(settings.accountDailyLimit);
onSettingsChange("accountDailyLimit", Number.isFinite(value) && value > 0 ? value : 1);
}}
/> />
</label> </label>
<label> <label>
@ -28,8 +42,15 @@ function SettingsTab({ settings, onSettingsChange, saveSettings }) {
<input <input
type="number" type="number"
min="1" min="1"
value={settings.floodCooldownMinutes} value={settings.floodCooldownMinutes === "" ? "" : settings.floodCooldownMinutes}
onChange={(event) => onSettingsChange("floodCooldownMinutes", Number(event.target.value))} onChange={(event) => {
const value = event.target.value;
onSettingsChange("floodCooldownMinutes", value === "" ? "" : Number(value));
}}
onBlur={() => {
const value = Number(settings.floodCooldownMinutes);
onSettingsChange("floodCooldownMinutes", Number.isFinite(value) && value > 0 ? value : 1);
}}
/> />
</label> </label>
<label> <label>
@ -37,8 +58,15 @@ function SettingsTab({ settings, onSettingsChange, saveSettings }) {
<input <input
type="number" type="number"
min="1" min="1"
value={settings.quietModeMinutes} value={settings.quietModeMinutes === "" ? "" : settings.quietModeMinutes}
onChange={(event) => onSettingsChange("quietModeMinutes", Number(event.target.value))} onChange={(event) => {
const value = event.target.value;
onSettingsChange("quietModeMinutes", value === "" ? "" : Number(value));
}}
onBlur={() => {
const value = Number(settings.quietModeMinutes);
onSettingsChange("quietModeMinutes", Number.isFinite(value) && value > 0 ? value : 1);
}}
/> />
</label> </label>
<label> <label>
@ -46,8 +74,15 @@ function SettingsTab({ settings, onSettingsChange, saveSettings }) {
<input <input
type="number" type="number"
min="1" min="1"
value={settings.queueTtlHours} value={settings.queueTtlHours === "" ? "" : settings.queueTtlHours}
onChange={(event) => onSettingsChange("queueTtlHours", Number(event.target.value))} onChange={(event) => {
const value = event.target.value;
onSettingsChange("queueTtlHours", value === "" ? "" : Number(value));
}}
onBlur={() => {
const value = Number(settings.queueTtlHours);
onSettingsChange("queueTtlHours", Number.isFinite(value) && value > 0 ? value : 1);
}}
/> />
</label> </label>
</div> </div>