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",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"description": "Automated user parsing and invites for Telegram groups",
"main": "src/main/index.js",

View File

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

View File

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

View File

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