Skip to content

Commit 32f70d3

Browse files
committed
🛠️ • v.0.1.0-beta.1 + patch 1
1 parent cfabed5 commit 32f70d3

5 files changed

Lines changed: 161 additions & 66 deletions

File tree

docs/release-notes/v.0.1.0-beta.1.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@ This is the first FluAutoClicker beta release candidate for Windows testing.
1818
- Update checker with manual checks, automatic checks, release status, and GitHub release opening.
1919
- And other....
2020

21-
21+
### + hotfix #1
22+
- fixed keyboard
23+
- fixed mode select

src/scripts/app/start-stop.ts

Lines changed: 62 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { listen } from "@tauri-apps/api/event";
33
import { syncAllKeyboardSettings } from "../keyboard";
44
import { syncAllMouseSettings } from "../mouse";
55
import { notify } from "../notifications";
6-
import { updateTabStates } from "../ui";
6+
import { getSelectedMode, updateTabStates } from "../ui";
7+
import type { AppMode } from "../ui";
78

89
type RunningPayload = {
910
running?: boolean;
@@ -16,6 +17,9 @@ type MacroStatusPayload = {
1617

1718
type SupportedTab = "mouse" | "keyboard" | "macro";
1819

20+
let runningMode: SupportedTab | null = null;
21+
let isToggling = false;
22+
1923
function getStartButton() {
2024
return document.getElementById("start-btn");
2125
}
@@ -42,14 +46,7 @@ function setStartButtonState(isRunning: boolean) {
4246
}
4347

4448
function getActiveTab(): SupportedTab {
45-
const activeTab = document.querySelector<HTMLElement>(".mode-tabs .tab.active");
46-
const tab = activeTab?.dataset.tab;
47-
48-
if (tab === "keyboard" || tab === "macro") {
49-
return tab;
50-
}
51-
52-
return "mouse";
49+
return getSelectedMode();
5350
}
5451

5552
function getMouseIntervalMs(): number {
@@ -77,50 +74,69 @@ function showTimingWarningModal() {
7774
}
7875

7976
async function toggleMouseClicker() {
80-
await invoke("toggle_clicker");
77+
return invoke<boolean>("toggle_clicker");
78+
}
79+
80+
function rememberRunningMode(mode: AppMode, isRunning: boolean) {
81+
if (isRunning) {
82+
runningMode = mode;
83+
return;
84+
}
85+
86+
if (runningMode === mode) {
87+
runningMode = null;
88+
}
8189
}
8290

8391
async function handleStartButtonClick() {
8492
const startButton = getStartButton();
85-
if (!startButton) {
93+
if (!startButton || isToggling) {
8694
return;
8795
}
8896

89-
const activeTab = getActiveTab();
90-
const isAlreadyRunning = startButton.classList.contains("running");
97+
isToggling = true;
98+
try {
99+
const isAlreadyRunning = startButton.classList.contains("running");
100+
const activeTab = isAlreadyRunning && runningMode ? runningMode : getActiveTab();
91101

92-
if (activeTab === "keyboard") {
93-
if (!isAlreadyRunning) {
94-
await syncAllKeyboardSettings();
95-
}
102+
if (activeTab === "keyboard") {
103+
if (!isAlreadyRunning) {
104+
await syncAllKeyboardSettings();
105+
}
96106

97-
const isRunning = await invoke<boolean>("toggle_keyboard_clicker");
98-
setStartButtonState(Boolean(isRunning));
99-
updateTabStates();
100-
return;
101-
}
107+
const isRunning = await invoke<boolean>("toggle_keyboard_clicker");
108+
rememberRunningMode("keyboard", Boolean(isRunning));
109+
setStartButtonState(Boolean(isRunning));
110+
updateTabStates();
111+
return;
112+
}
102113

103-
if (activeTab === "macro") {
104-
try {
114+
if (activeTab === "macro") {
105115
const isRunning = await invoke<boolean>("toggle_macro_player");
116+
rememberRunningMode("macro", Boolean(isRunning));
106117
setStartButtonState(Boolean(isRunning));
107-
} catch (error) {
108-
console.error("Failed to toggle macro player", error);
109-
notify(error instanceof Error ? error.message : String(error), "error", 3200);
118+
updateTabStates();
119+
return;
110120
}
111121

112-
updateTabStates();
113-
return;
114-
}
122+
if (!isAlreadyRunning && getMouseIntervalMs() <= 3) {
123+
showTimingWarningModal();
124+
return;
125+
}
115126

116-
if (!isAlreadyRunning && getMouseIntervalMs() <= 3) {
117-
showTimingWarningModal();
118-
return;
127+
if (!isAlreadyRunning) {
128+
await syncAllMouseSettings();
129+
}
130+
const isRunning = await toggleMouseClicker();
131+
rememberRunningMode("mouse", Boolean(isRunning));
132+
setStartButtonState(Boolean(isRunning));
133+
updateTabStates();
134+
} catch (error) {
135+
console.error("Failed to toggle selected mode", error);
136+
notify(error instanceof Error ? error.message : String(error), "error", 3200);
137+
} finally {
138+
isToggling = false;
119139
}
120-
121-
await syncAllMouseSettings();
122-
await toggleMouseClicker();
123-
updateTabStates();
124140
}
125141

126142
export function initStartStopControls() {
@@ -132,18 +148,24 @@ export function initStartStopControls() {
132148
}
133149

134150
void listen<RunningPayload>("status-changed", (event) => {
135-
setStartButtonState(Boolean(event.payload.running));
151+
const isRunning = Boolean(event.payload.running);
152+
rememberRunningMode("mouse", isRunning);
153+
setStartButtonState(isRunning);
136154
updateTabStates();
137155
});
138156

139157
void listen<RunningPayload>("keyboard-status-changed", (event) => {
140-
setStartButtonState(Boolean(event.payload.running));
158+
const isRunning = Boolean(event.payload.running);
159+
rememberRunningMode("keyboard", isRunning);
160+
setStartButtonState(isRunning);
141161
updateTabStates();
142162
});
143163

144164
void listen<MacroStatusPayload>("macro-status-changed", (event) => {
145165
const state = String(event.payload?.state || "stopped");
146-
setStartButtonState(state === "playing");
166+
const isRunning = state === "playing";
167+
rememberRunningMode("macro", isRunning);
168+
setStartButtonState(isRunning);
147169
updateTabStates();
148170

149171
if (state === "error" && event.payload?.error) {

src/scripts/keyboard.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ let recordingModifiers: Set<string> = new Set();
1414
let recordingCallback: ((mainKey: string, modifiers: string[]) => void) | null = null;
1515

1616
export function initKeyboard() {
17-
const keys = document.querySelectorAll('.kb-key');
18-
const tsuKeys = document.querySelectorAll<HTMLElement>('.kb-tsu');
17+
const keyboardSection = document.getElementById('keyboard-section') || document;
18+
const keys = keyboardSection.querySelectorAll('.kb-key');
19+
const tsuKeys = keyboardSection.querySelectorAll<HTMLElement>('.kb-tsu');
1920
const kbMainKeyDisplay = document.getElementById('kb-main-key-display');
2021
const kbModifiersDisplay = document.getElementById('kb-modifiers-display');
2122
const kbContainer = document.getElementById('kb-sliding-container');
@@ -27,6 +28,31 @@ export function initKeyboard() {
2728
let selectedMainElement: HTMLElement | null = null;
2829
let selectedModifiers: Set<string> = new Set();
2930

31+
function readSelectionFromActiveKeys() {
32+
selectedMainKey = null;
33+
selectedMainElement = null;
34+
selectedModifiers.clear();
35+
36+
keys.forEach(k => {
37+
if (!k.classList.contains('active')) {
38+
return;
39+
}
40+
41+
const label = k.textContent?.trim().toLowerCase() || '';
42+
if (isModifierLabel(label)) {
43+
selectedModifiers.add(label);
44+
return;
45+
}
46+
47+
if (!selectedMainElement) {
48+
selectedMainElement = k as HTMLElement;
49+
selectedMainKey = label;
50+
} else {
51+
k.classList.remove('active');
52+
}
53+
});
54+
}
55+
3056
function updateDisplays() {
3157
const modParts = Array.from(selectedModifiers);
3258
const modString = modParts.length > 0
@@ -54,6 +80,7 @@ export function initKeyboard() {
5480
}
5581

5682

83+
readSelectionFromActiveKeys();
5784
updateDisplays();
5885
tsuKeys.forEach((key) => {
5986
key.textContent = ":)";
@@ -81,14 +108,14 @@ export function initKeyboard() {
81108

82109
if (isActive) {
83110
selectedModifiers.delete(label);
84-
document.querySelectorAll('.kb-key').forEach(k => {
111+
keys.forEach(k => {
85112
if (k.textContent?.trim().toLowerCase() === label) {
86113
k.classList.remove('active');
87114
}
88115
});
89116
} else {
90117
selectedModifiers.add(label);
91-
document.querySelectorAll('.kb-key').forEach(k => {
118+
keys.forEach(k => {
92119
if (k.textContent?.trim().toLowerCase() === label) {
93120
k.classList.add('active');
94121
}
@@ -217,7 +244,7 @@ export function initKeyboard() {
217244

218245
recordingCallback = (mainKey: string, modifiers: string[]) => {
219246

220-
document.querySelectorAll('.kb-key').forEach(k => {
247+
keys.forEach(k => {
221248
const kLabel = k.textContent?.trim().toLowerCase() || '';
222249
if (isModifierLabel(kLabel)) {
223250
k.classList.remove('active');
@@ -231,7 +258,7 @@ export function initKeyboard() {
231258
selectedModifiers.clear();
232259

233260

234-
const allKbKeys = document.querySelectorAll('.kb-key');
261+
const allKbKeys = keys;
235262
for (const k of allKbKeys) {
236263
const kLabel = k.textContent?.trim().toLowerCase() || '';
237264
if (kLabel === mainKey) {
@@ -244,7 +271,7 @@ export function initKeyboard() {
244271

245272
modifiers.forEach(mod => {
246273
selectedModifiers.add(mod);
247-
document.querySelectorAll('.kb-key').forEach(k => {
274+
keys.forEach(k => {
248275
const kLabel = k.textContent?.trim().toLowerCase() || '';
249276
if (kLabel === mod) {
250277
k.classList.add('active');
@@ -352,7 +379,8 @@ function handleRecordKeydown(e: KeyboardEvent) {
352379

353380
export async function syncAllKeyboardSettings() {
354381

355-
const activeKeys = document.querySelectorAll('.kb-key.active');
382+
const keyboardSection = document.getElementById('keyboard-section') || document;
383+
const activeKeys = keyboardSection.querySelectorAll('.kb-key.active');
356384
let mainKey = "a";
357385
const modLabels: string[] = [];
358386

src/scripts/settings-persistence.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ type AppConfigFile = {
7373
const SETTINGS_CHANGED_EVENT = "flu:settings-changed";
7474
const SETTINGS_APPLIED_EVENT = "flu:settings-applied";
7575
const UPDATE_LAST_CHECK_STORAGE_KEY = "flu-update-last-checked-at";
76+
const APP_MODES = new Set(["mouse", "keyboard", "macro"]);
7677

7778
let currentConfig: AppConfigFile | null = null;
7879
let saveTimeoutId: number | null = null;
@@ -188,8 +189,10 @@ function setKeyboardSelection(key: string, modifiers: string) {
188189
.map((part) => part.trim().toLowerCase())
189190
.filter((part) => part && part !== "none")
190191
);
192+
const keyboardSection = document.getElementById("keyboard-section") || document;
193+
let hasActiveMainKey = false;
191194

192-
document.querySelectorAll(".kb-key").forEach((button) => {
195+
keyboardSection.querySelectorAll(".kb-key").forEach((button) => {
193196
const element = button as HTMLElement;
194197
const label = element.textContent?.trim().toLowerCase() || "";
195198
if (!label || element.classList.contains("kb-tsu") || element.classList.contains("kb-menu")) {
@@ -198,7 +201,12 @@ function setKeyboardSelection(key: string, modifiers: string) {
198201
}
199202

200203
const isModifier = ["ctrl", "shift", "alt", "win"].includes(label);
201-
const isActive = isModifier ? modifierSet.has(label) : label === normalizedKey;
204+
const isActive = isModifier
205+
? modifierSet.has(label)
206+
: label === normalizedKey && !hasActiveMainKey;
207+
if (!isModifier && isActive) {
208+
hasActiveMainKey = true;
209+
}
202210
element.classList.toggle("active", isActive);
203211
});
204212

@@ -315,7 +323,8 @@ function applyConfigToUi(config: AppConfigFile) {
315323
setToggleState("remove-italic-toggle", config.general.remove_italic);
316324
setToggleState("acrylic-toggle", frontendState.acrylic_enabled === true);
317325

318-
const activeTab = String(frontendState.active_tab || "mouse");
326+
const activeTabCandidate = String(frontendState.active_tab || "mouse");
327+
const activeTab = APP_MODES.has(activeTabCandidate) ? activeTabCandidate : "mouse";
319328
document.querySelectorAll(".mode-tabs .tab").forEach((tab) => {
320329
tab.classList.toggle("active", (tab as HTMLElement).dataset.tab === activeTab);
321330
});
@@ -362,17 +371,22 @@ function getNumericValue(id: string, fallback: number): number {
362371
}
363372

364373
function getKeyboardSnapshot() {
365-
const activeKeys = document.querySelectorAll(".kb-key.active");
374+
const keyboardSection = document.getElementById("keyboard-section") || document;
375+
const activeKeys = keyboardSection.querySelectorAll(".kb-key.active");
366376
let key = "a";
367377
const modifiers: string[] = [];
378+
let foundMainKey = false;
368379

369380
activeKeys.forEach((entry) => {
370381
const label = (entry.textContent || "").trim().toLowerCase();
371382
if (["ctrl", "shift", "alt", "win"].includes(label)) {
372383
modifiers.push(label);
373384
return;
374385
}
375-
key = label || key;
386+
if (!foundMainKey && label) {
387+
key = label;
388+
foundMainKey = true;
389+
}
376390
});
377391

378392
return {
@@ -385,8 +399,9 @@ async function captureConfigSnapshot(): Promise<AppConfigFile> {
385399
const base = currentConfig || defaultConfig();
386400
const hotkeys = await fetchHotkeys();
387401
const keyboard = getKeyboardSnapshot();
388-
const activeTab =
402+
const activeTabCandidate =
389403
document.querySelector<HTMLElement>(".mode-tabs .tab.active")?.dataset.tab || "mouse";
404+
const activeTab = APP_MODES.has(activeTabCandidate) ? activeTabCandidate : "mouse";
390405
const multithreadMode = getActiveValue("#multithread-mode-row .multi-btn.active", "normal");
391406
return {
392407
...base,

0 commit comments

Comments
 (0)