Skip to content

Commit 10b95e3

Browse files
feat: Combo Bind (frontend) (#6407)
Co-authored-by: sqlerrorthing <[email protected]>
1 parent c2eac04 commit 10b95e3

File tree

10 files changed

+522
-220
lines changed

10 files changed

+522
-220
lines changed

src-theme/src/integration/ws.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,52 @@ export function listenAlways<NAME extends keyof EventMap>(eventName: NAME, callb
4949
/**
5050
* Registers a event listener that will be called on every event of the given name.
5151
*
52-
* The listener will be automatically removed when the component is destroyed.
53-
*
54-
* Should only be used inside a Svelte component.
55-
*
5652
* @param eventName
5753
* @param callback
54+
* @return A function that can be called to remove the listener.
5855
*/
59-
export function listen<NAME extends keyof EventMap>(eventName: NAME, callback: (event: EventMap[NAME]) => void) {
56+
function listenNonComponent<NAME extends keyof EventMap>(eventName: NAME, callback: (event: EventMap[NAME]) => void) {
6057
if (!listeners.has(eventName)) {
6158
listeners.set(eventName, []);
6259
}
6360

6461
listeners.get(eventName)!!.push(callback);
6562

66-
onDestroy(() => deleteListener(eventName, callback));
63+
return () => deleteListener(eventName, callback);
64+
}
65+
66+
/**
67+
* Registers a event listener that will be called on every event of the given name.
68+
*
69+
* The listener will be automatically removed when the component is destroyed.
70+
*
71+
* Should only be used inside a Svelte component.
72+
*
73+
* @param eventName
74+
* @param callback
75+
*/
76+
export function listen<NAME extends keyof EventMap>(eventName: NAME, callback: (event: EventMap[NAME]) => void) {
77+
const onDestroyHook = listenNonComponent(eventName, callback);
78+
onDestroy(onDestroyHook);
79+
}
80+
81+
/**
82+
* Wait next event which matches given {@link predicate}.
83+
*/
84+
export async function waitMatches<NAME extends keyof EventMap>(eventName: NAME, predicate: (event: EventMap[NAME]) => boolean): Promise<EventMap[NAME]> {
85+
return new Promise((resolve, reject) => {
86+
const deleteHandler = listenNonComponent(eventName, (e) => {
87+
try {
88+
if (predicate(e)) {
89+
resolve(e);
90+
deleteHandler();
91+
}
92+
} catch (e) {
93+
reject(e);
94+
deleteHandler();
95+
}
96+
})
97+
});
6798
}
6899

69100
export function cleanupListeners() {

src-theme/src/routes/clickgui/Module.svelte

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@
133133
</div>
134134

135135
<style lang="scss">
136-
@use "../../colors.scss" as *;
136+
@use "../../colors" as *;
137+
@use "./icon-settings-expand" as *;
137138
138139
.module {
139140
position: relative;
@@ -178,21 +179,8 @@
178179
179180
&.has-settings {
180181
.name::after {
181-
content: "";
182-
display: block;
183-
position: absolute;
184-
height: 10px;
185-
width: 10px;
186-
right: 15px;
187-
top: 50%;
188-
background-image: url("/img/clickgui/icon-settings-expand.svg");
189-
background-position: center;
190-
background-repeat: no-repeat;
182+
@include icon-settings-expand($right: 15px);
191183
opacity: 0.5;
192-
transform-origin: 50% 50%;
193-
transform: translateY(-50%) rotate(-90deg);
194-
transition: ease opacity 0.2s,
195-
ease transform 0.4s;
196184
}
197185
198186
&.expanded .name::after {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*!
2+
* This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce)
3+
*
4+
* Copyright (c) 2015 - 2025 CCBlueX
5+
*
6+
* LiquidBounce is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* LiquidBounce is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with LiquidBounce. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
@mixin icon-settings-expand(
21+
$size: 10px,
22+
$right: 10px,
23+
$rotate: -90deg,
24+
) {
25+
content: "";
26+
display: block;
27+
position: absolute;
28+
height: $size;
29+
width: $size;
30+
right: $right;
31+
top: 50%;
32+
background-image: url("/img/clickgui/icon-settings-expand.svg");
33+
background-position: center;
34+
background-repeat: no-repeat;
35+
transform-origin: 50% 50%;
36+
transform: translateY(-50%) rotate($rotate);
37+
transition: ease opacity 0.2s, ease transform 0.4s;
38+
}

src-theme/src/routes/clickgui/setting/BindSetting.svelte

Lines changed: 0 additions & 154 deletions
This file was deleted.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<script lang="ts">
2+
import type {BindModifier} from "../../../../integration/types";
3+
import {os} from "../../clickgui_store";
4+
5+
export let modifiers: Iterable<BindModifier>;
6+
export let boundKey: string | undefined;
7+
8+
const getRenderString = (modifier: BindModifier) => {
9+
switch ($os) {
10+
case "windows":
11+
switch (modifier) {
12+
case "Control":
13+
return "Ctrl";
14+
case "Super":
15+
return "\u229e";
16+
default:
17+
return modifier;
18+
}
19+
case "mac":
20+
switch (modifier) {
21+
case "Shift":
22+
return "\u21e7";
23+
case "Control":
24+
return "^";
25+
case "Alt":
26+
return "\u2325";
27+
case "Super":
28+
return "\u2318";
29+
default:
30+
return modifier;
31+
}
32+
default:
33+
return modifier;
34+
}
35+
};
36+
</script>
37+
38+
<span class="wrapper">
39+
{#if boundKey}
40+
{#each modifiers as modifier (modifier)}
41+
<span>{getRenderString(modifier)}</span>
42+
<span class="divider">+</span>
43+
{/each}
44+
<span class="boundKey">{boundKey}</span>
45+
{:else}
46+
<span class="dimmed">None</span>
47+
{/if}
48+
</span>
49+
50+
<style lang="scss">
51+
@use "../../../../colors" as *;
52+
53+
.wrapper {
54+
column-gap: 2px;
55+
display: flex;
56+
align-items: center;
57+
}
58+
59+
.dimmed {
60+
color: $clickgui-text-dimmed-color;
61+
}
62+
63+
.divider {
64+
color: $clickgui-text-dimmed-color;
65+
opacity: 0.8;
66+
font-size: 10px;
67+
line-height: 1;
68+
font-family: monospace;
69+
}
70+
71+
.boundKey {
72+
font-weight: bold;
73+
}
74+
</style>

0 commit comments

Comments
 (0)