mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-01 03:18:16 +03:00
fix: preserve TUN switch animations
Keep user-initiated switch animation running when the shared settings controller echoes the committed TUN state, and animate the peer surface without emitting a recursive request. Preserve snap synchronization for initialization and rollback, with real Qt coverage for both directions and rapid toggles. Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
@@ -148,6 +148,23 @@ class AppQSwitch(Mixins.ThemeAware, QCheckBox):
|
||||
|
||||
del blocker
|
||||
|
||||
def syncCheckedAnimated(self, checked: bool):
|
||||
"""Animate changed external state without emitting another request."""
|
||||
checked = bool(checked)
|
||||
|
||||
if self.isChecked() == checked:
|
||||
# A user toggle already started the canonical animation before its
|
||||
# committed state was broadcast back through the shared authority.
|
||||
return
|
||||
|
||||
blocker = QtCore.QSignalBlocker(self)
|
||||
|
||||
self.setChecked(checked)
|
||||
|
||||
del blocker
|
||||
|
||||
self._animateToggle(checked)
|
||||
|
||||
def hitButton(self, position: QtCore.QPoint) -> bool:
|
||||
"""Make the complete custom-painted switch track interactive."""
|
||||
return self.rect().contains(position)
|
||||
|
||||
@@ -825,7 +825,9 @@ class HomePage(Mixins.QTranslatable, QMainWindow):
|
||||
AppSettingsController().systemProxyModeChanged.connect(
|
||||
self._syncSystemProxyMode
|
||||
)
|
||||
AppSettingsController().tunModeChanged.connect(self.tunModeSwitch.syncChecked)
|
||||
AppSettingsController().tunModeChanged.connect(
|
||||
self.tunModeSwitch.syncCheckedAnimated
|
||||
)
|
||||
|
||||
AppConnectionController().interactionEnabledChanged.connect(
|
||||
self.setConnectionControlsEnabled
|
||||
|
||||
@@ -661,7 +661,7 @@ class SettingsPage(Mixins.QTranslatable, QMainWindow):
|
||||
self.tunModeCard.checkBox.setEnabled(self._tunModeAvailable)
|
||||
|
||||
AppSettingsController().tunModeChanged.connect(
|
||||
self.tunModeCard.checkBox.syncChecked
|
||||
self.tunModeCard.checkBox.syncCheckedAnimated
|
||||
)
|
||||
|
||||
(
|
||||
|
||||
@@ -25,7 +25,7 @@ from Furious.Frozenlib import AppBuiltinProxyMode, AppSettings
|
||||
from Furious.Models import CoreConfiguration, ServerProfile
|
||||
from Furious.Plugins.API import RoutingOption
|
||||
from Furious.Repository import Storage, SubscriptionGroup
|
||||
from Furious.Qt import AppQDialog
|
||||
from Furious.Qt import AppQDialog, AppQSwitch
|
||||
from Furious.Widget.RoutingSelector import RoutingSelector
|
||||
from Furious.Widget.ServerTableView import ServerTableView
|
||||
from Furious.Window.HomePage import HomePage
|
||||
@@ -690,7 +690,9 @@ class SharedSettingsQtWorkflowTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
settingsController.systemProxyModeChanged.connect(proxyCard.sync)
|
||||
settingsController.tunModeChanged.connect(tunCard.checkBox.syncChecked)
|
||||
settingsController.tunModeChanged.connect(
|
||||
tunCard.checkBox.syncCheckedAnimated
|
||||
)
|
||||
settingsLayout.addWidget(proxyCard)
|
||||
settingsLayout.addWidget(tunCard)
|
||||
|
||||
@@ -740,10 +742,20 @@ class SharedSettingsQtWorkflowTest(unittest.TestCase):
|
||||
QtCore.Qt.MouseButton.LeftButton,
|
||||
pos=home.tunModeSwitch.rect().center(),
|
||||
)
|
||||
|
||||
QTest.qWait(40)
|
||||
|
||||
for switch in (home.tunModeSwitch, tunCard.checkBox):
|
||||
self.assertGreater(switch.thumbPosition, 0.0)
|
||||
self.assertLess(switch.thumbPosition, 1.0)
|
||||
|
||||
QTest.qWait(AppQSwitch.AnimationDuration)
|
||||
processQtEvents()
|
||||
|
||||
self.assertTrue(home.tunModeSwitch.isChecked())
|
||||
self.assertTrue(tunCard.checkBox.isChecked())
|
||||
self.assertEqual(home.tunModeSwitch.thumbPosition, 1.0)
|
||||
self.assertEqual(tunCard.checkBox.thumbPosition, 1.0)
|
||||
self.assertEqual(tunStates, [True])
|
||||
|
||||
QTest.mouseClick(
|
||||
@@ -751,12 +763,42 @@ class SharedSettingsQtWorkflowTest(unittest.TestCase):
|
||||
QtCore.Qt.MouseButton.LeftButton,
|
||||
pos=tunCard.checkBox.rect().center(),
|
||||
)
|
||||
|
||||
QTest.qWait(40)
|
||||
|
||||
for switch in (home.tunModeSwitch, tunCard.checkBox):
|
||||
self.assertGreater(switch.thumbPosition, 0.0)
|
||||
self.assertLess(switch.thumbPosition, 1.0)
|
||||
|
||||
QTest.qWait(AppQSwitch.AnimationDuration)
|
||||
processQtEvents()
|
||||
|
||||
self.assertFalse(home.tunModeSwitch.isChecked())
|
||||
self.assertFalse(tunCard.checkBox.isChecked())
|
||||
self.assertEqual(home.tunModeSwitch.thumbPosition, 0.0)
|
||||
self.assertEqual(tunCard.checkBox.thumbPosition, 0.0)
|
||||
self.assertEqual(tunStates, [True, False])
|
||||
|
||||
QTest.mouseClick(
|
||||
home.tunModeSwitch,
|
||||
QtCore.Qt.MouseButton.LeftButton,
|
||||
pos=home.tunModeSwitch.rect().center(),
|
||||
)
|
||||
QTest.qWait(20)
|
||||
QTest.mouseClick(
|
||||
home.tunModeSwitch,
|
||||
QtCore.Qt.MouseButton.LeftButton,
|
||||
pos=home.tunModeSwitch.rect().center(),
|
||||
)
|
||||
QTest.qWait(AppQSwitch.AnimationDuration + 40)
|
||||
processQtEvents()
|
||||
|
||||
self.assertFalse(home.tunModeSwitch.isChecked())
|
||||
self.assertFalse(tunCard.checkBox.isChecked())
|
||||
self.assertEqual(home.tunModeSwitch.thumbPosition, 0.0)
|
||||
self.assertEqual(tunCard.checkBox.thumbPosition, 0.0)
|
||||
self.assertEqual(tunStates, [True, False, True, False])
|
||||
|
||||
connectionController.setInteractionEnabled(False)
|
||||
processQtEvents()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user