refactor: remove effect badges and clear active effects on player reset
This commit is contained in:
14 files changed
+31
-42
No files matched your search
@@ -361,13 +361,8 @@ async function cycleLoop() {
|
|||||||
:title="`${fx.name} – ${fx.description}`"
|
:title="`${fx.name} – ${fx.description}`"
|
||||||
@click="onToggleEffect(fx)"
|
@click="onToggleEffect(fx)"
|
||||||
>
|
>
|
||||||
<div class="effect-info">
|
<component :is="effectIcon(fx.icon)" :size="15" class="effect-icon" />
|
||||||
<component :is="effectIcon(fx.icon)" :size="14" class="effect-icon" />
|
<span class="effect-name">{{ fx.name }}</span>
|
||||||
<span class="effect-name">{{ fx.name }}</span>
|
|
||||||
</div>
|
|
||||||
<span class="effect-badge" :class="{ active: fx.active }">
|
|
||||||
{{ fx.active ? 'WŁ' : fx.badge }}
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -419,8 +414,8 @@ async function cycleLoop() {
|
|||||||
.btn-effect {
|
.btn-effect {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: center;
|
||||||
gap: 6px;
|
gap: 7px;
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
background: rgba(255, 255, 255, 0.03);
|
background: rgba(255, 255, 255, 0.03);
|
||||||
border: 1px solid var(--border-glass, rgba(255, 255, 255, 0.08));
|
border: 1px solid var(--border-glass, rgba(255, 255, 255, 0.08));
|
||||||
@@ -451,13 +446,6 @@ async function cycleLoop() {
|
|||||||
border-color: rgba(245, 158, 11, 0.7);
|
border-color: rgba(245, 158, 11, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.effect-info {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.effect-icon {
|
.effect-icon {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease;
|
||||||
@@ -473,21 +461,4 @@ async function cycleLoop() {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.effect-badge {
|
|
||||||
font-size: 0.62rem;
|
|
||||||
font-weight: 700;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
color: var(--text-muted);
|
|
||||||
letter-spacing: 0.4px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.effect-badge.active {
|
|
||||||
background: #f59e0b;
|
|
||||||
color: #0f172a;
|
|
||||||
box-shadow: 0 0 8px rgba(245, 158, 11, 0.4);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -54,7 +54,6 @@ export interface PlayerEffect {
|
|||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
badge: string
|
|
||||||
icon: string
|
icon: string
|
||||||
active: boolean
|
active: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,22 @@ class TestAudioEffects(unittest.TestCase):
|
|||||||
self.assertFalse(toggled)
|
self.assertFalse(toggled)
|
||||||
self.assertFalse(pipeline.is_active("distortion"))
|
self.assertFalse(pipeline.is_active("distortion"))
|
||||||
|
|
||||||
|
def test_effects_metadata_does_not_contain_badge(self):
|
||||||
|
from zyrarbot.audio.effects.registry import get_available_effects_metadata
|
||||||
|
|
||||||
|
metadata = get_available_effects_metadata()
|
||||||
|
self.assertGreater(len(metadata), 0)
|
||||||
|
for entry in metadata:
|
||||||
|
self.assertIn("id", entry)
|
||||||
|
self.assertIn("name", entry)
|
||||||
|
self.assertIn("description", entry)
|
||||||
|
self.assertIn("icon", entry)
|
||||||
|
self.assertNotIn("badge", entry)
|
||||||
|
|
||||||
|
def test_effect_instances_have_no_badge_attribute(self):
|
||||||
|
for effect in create_default_effects():
|
||||||
|
self.assertFalse(hasattr(effect, "badge"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
@@ -256,6 +256,11 @@ class MusicPlayerQueueTest(unittest.IsolatedAsyncioTestCase):
|
|||||||
player.set_effect(GUILD, "fourth_density", True)
|
player.set_effect(GUILD, "fourth_density", True)
|
||||||
self.assertEqual(player.state(GUILD).active_effects, {"distortion", "fourth_density"})
|
self.assertEqual(player.state(GUILD).active_effects, {"distortion", "fourth_density"})
|
||||||
|
|
||||||
|
# Stopping/clearing the player disables all active effects
|
||||||
|
player.clear(GUILD)
|
||||||
|
self.assertEqual(player.state(GUILD).active_effects, set())
|
||||||
|
self.assertFalse(player.is_effect_active(GUILD, "distortion"))
|
||||||
|
self.assertFalse(player.is_effect_active(GUILD, "fourth_density"))
|
||||||
|
|
||||||
async def test_default_plays_are_applied_per_guild(self):
|
async def test_default_plays_are_applied_per_guild(self):
|
||||||
player, _ = build_player()
|
player, _ = build_player()
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ class AudioEffect(ABC):
|
|||||||
id: str
|
id: str
|
||||||
name: str
|
name: str
|
||||||
description: str
|
description: str
|
||||||
badge: str
|
|
||||||
icon: str
|
icon: str
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class DistortionEffect(AudioEffect):
|
|||||||
id = "distortion"
|
id = "distortion"
|
||||||
name = "Przester"
|
name = "Przester"
|
||||||
description = "Ekstremalne podbicie głośności (1000%) z przesterem"
|
description = "Ekstremalne podbicie głośności (1000%) z przesterem"
|
||||||
badge = "1000%"
|
|
||||||
icon = "zap"
|
icon = "zap"
|
||||||
|
|
||||||
def __init__(self, multiplier: float = 10.0) -> None:
|
def __init__(self, multiplier: float = 10.0) -> None:
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ class FourthDensityEffect(AudioEffect):
|
|||||||
id = "fourth_density"
|
id = "fourth_density"
|
||||||
name = "Czwarta gęstość"
|
name = "Czwarta gęstość"
|
||||||
description = "Pływający ton (sinusoidalna zmiana pitch z okresem ~1 sekundy)"
|
description = "Pływający ton (sinusoidalna zmiana pitch z okresem ~1 sekundy)"
|
||||||
badge = "~1s PITCH"
|
|
||||||
icon = "sparkles"
|
icon = "sparkles"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ class MuffledEffect(AudioEffect):
|
|||||||
id = "muffled"
|
id = "muffled"
|
||||||
name = "Pod wodą"
|
name = "Pod wodą"
|
||||||
description = "Filtr dolnoprzepustowy (dźwięk przytłumiony / zza ściany)"
|
description = "Filtr dolnoprzepustowy (dźwięk przytłumiony / zza ściany)"
|
||||||
badge = "LOWPASS"
|
|
||||||
icon = "waves"
|
icon = "waves"
|
||||||
|
|
||||||
def __init__(self, alpha: float = 0.085) -> None:
|
def __init__(self, alpha: float = 0.085) -> None:
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ def get_available_effects_metadata() -> list[dict[str, Any]]:
|
|||||||
"id": effect.id,
|
"id": effect.id,
|
||||||
"name": effect.name,
|
"name": effect.name,
|
||||||
"description": effect.description,
|
"description": effect.description,
|
||||||
"badge": effect.badge,
|
|
||||||
"icon": effect.icon,
|
"icon": effect.icon,
|
||||||
}
|
}
|
||||||
for effect in create_default_effects()
|
for effect in create_default_effects()
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ class RobotEffect(AudioEffect):
|
|||||||
id = "robot"
|
id = "robot"
|
||||||
name = "Robot"
|
name = "Robot"
|
||||||
description = "Metaliczny, robotyczny głos cyborga (ring modulation ~65Hz)"
|
description = "Metaliczny, robotyczny głos cyborga (ring modulation ~65Hz)"
|
||||||
badge = "CYBORG"
|
|
||||||
icon = "bot"
|
icon = "bot"
|
||||||
|
|
||||||
def __init__(self, freq_hz: float = 65.0, mix: float = 0.85) -> None:
|
def __init__(self, freq_hz: float = 65.0, mix: float = 0.85) -> None:
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ class ToasterEffect(AudioEffect):
|
|||||||
id = "toaster"
|
id = "toaster"
|
||||||
name = "Dźwięk z tostera"
|
name = "Dźwięk z tostera"
|
||||||
description = "Memiczny dźwięk z mikrofalówki / kalkulatora (bitcrusher 5-bit, aliasing)"
|
description = "Memiczny dźwięk z mikrofalówki / kalkulatora (bitcrusher 5-bit, aliasing)"
|
||||||
badge = "8-BIT"
|
|
||||||
icon = "radio"
|
icon = "radio"
|
||||||
|
|
||||||
def __init__(self, bit_depth: int = 5, downsample: int = 6) -> None:
|
def __init__(self, bit_depth: int = 5, downsample: int = 6) -> None:
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class TremoloEffect(AudioEffect):
|
|||||||
id = "tremolo"
|
id = "tremolo"
|
||||||
name = "Tremolo"
|
name = "Tremolo"
|
||||||
description = "Pulsowanie amplitudy (efekt wibracji głośności)"
|
description = "Pulsowanie amplitudy (efekt wibracji głośności)"
|
||||||
badge = "LFO"
|
|
||||||
icon = "activity"
|
icon = "activity"
|
||||||
|
|
||||||
def __init__(self, freq_hz: float = 4.0, depth: float = 0.6) -> None:
|
def __init__(self, freq_hz: float = 4.0, depth: float = 0.6) -> None:
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class GuildMusicState:
|
|||||||
self.queue.clear()
|
self.queue.clear()
|
||||||
self.current = None
|
self.current = None
|
||||||
self.index = -1
|
self.index = -1
|
||||||
|
self.active_effects.clear()
|
||||||
|
|
||||||
|
|
||||||
def find(self, track_id: str) -> YTDLSource | None:
|
def find(self, track_id: str) -> YTDLSource | None:
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ class MusicPlayer:
|
|||||||
self._playback_tokens[guild_id] = self._playback_tokens.get(guild_id, 0) + 1
|
self._playback_tokens[guild_id] = self._playback_tokens.get(guild_id, 0) + 1
|
||||||
self._interrupted_playbacks.discard(guild_id)
|
self._interrupted_playbacks.discard(guild_id)
|
||||||
self.state(guild_id).reset()
|
self.state(guild_id).reset()
|
||||||
|
self._apply_volume(guild_id)
|
||||||
|
|
||||||
def has_saved_queue(self, guild_id: int) -> bool:
|
def has_saved_queue(self, guild_id: int) -> bool:
|
||||||
return bool(self._queues and self._queues.exists(guild_id))
|
return bool(self._queues and self._queues.exists(guild_id))
|
||||||
@@ -236,6 +237,10 @@ class MusicPlayer:
|
|||||||
def is_effect_active(self, guild_id: int, effect_id: str) -> bool:
|
def is_effect_active(self, guild_id: int, effect_id: str) -> bool:
|
||||||
return effect_id in self.state(guild_id).active_effects
|
return effect_id in self.state(guild_id).active_effects
|
||||||
|
|
||||||
|
def clear_effects(self, guild_id: int) -> None:
|
||||||
|
self.state(guild_id).active_effects.clear()
|
||||||
|
self._apply_volume(guild_id)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def set_loop_mode(self, guild_id: int, mode: LoopMode) -> None:
|
def set_loop_mode(self, guild_id: int, mode: LoopMode) -> None:
|
||||||
|
|||||||
Reference in new issue
Block a user