Bump version to 1.0.2+4, implement native state restoration, and clean up UI
This commit is contained in:
1 parent
61be397058
commit
208da38586
4 files changed
+34
-69
No files matched your search
@@ -22,31 +22,6 @@ class ClockDisplay extends StatelessWidget {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
// Background quota track ring
|
|
||||||
const CustomPaint(
|
|
||||||
size: Size(200, 200),
|
|
||||||
painter: _ArcPainter(
|
|
||||||
progress: 1.0,
|
|
||||||
color: Color.fromRGBO(74, 85, 104, 0.2),
|
|
||||||
strokeWidth: 4,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Live quota progress ring
|
|
||||||
TweenAnimationBuilder<double>(
|
|
||||||
tween: Tween(begin: 0, end: timer.progress),
|
|
||||||
duration: const Duration(milliseconds: 400),
|
|
||||||
builder: (context, value, _) => CustomPaint(
|
|
||||||
size: const Size(200, 200),
|
|
||||||
painter: _ArcPainter(
|
|
||||||
progress: value,
|
|
||||||
color: _cyanGlow,
|
|
||||||
strokeWidth: 4,
|
|
||||||
glow: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Center content: countdown + speed
|
// Center content: countdown + speed
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -94,45 +69,3 @@ class ClockDisplay extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ArcPainter extends CustomPainter {
|
|
||||||
final double progress;
|
|
||||||
final Color color;
|
|
||||||
final double strokeWidth;
|
|
||||||
final bool glow;
|
|
||||||
|
|
||||||
const _ArcPainter({
|
|
||||||
required this.progress,
|
|
||||||
required this.color,
|
|
||||||
this.strokeWidth = 4,
|
|
||||||
this.glow = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
void paint(Canvas canvas, Size size) {
|
|
||||||
final rect = Rect.fromLTWH(0, 0, size.width, size.height)
|
|
||||||
.deflate(strokeWidth / 2);
|
|
||||||
|
|
||||||
if (glow) {
|
|
||||||
final glowPaint = Paint()
|
|
||||||
..color = const Color.fromRGBO(0, 229, 255, 0.15)
|
|
||||||
..style = PaintingStyle.stroke
|
|
||||||
..strokeWidth = strokeWidth + 8
|
|
||||||
..strokeCap = StrokeCap.round
|
|
||||||
..maskFilter = const MaskFilter.blur(BlurStyle.normal, 8);
|
|
||||||
canvas.drawArc(rect, -pi / 2, 2 * pi * progress, false, glowPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
final paint = Paint()
|
|
||||||
..color = color
|
|
||||||
..style = PaintingStyle.stroke
|
|
||||||
..strokeWidth = strokeWidth
|
|
||||||
..strokeCap = StrokeCap.round;
|
|
||||||
|
|
||||||
canvas.drawArc(rect, -pi / 2, 2 * pi * progress, false, paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool shouldRepaint(covariant _ArcPainter old) =>
|
|
||||||
old.progress != progress || old.color != color;
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,19 @@ class SessionTimer extends ChangeNotifier {
|
|||||||
int _lastUsedBytes = 0;
|
int _lastUsedBytes = 0;
|
||||||
double _currentSpeedKbps = 0.0; // Total speed (RX+TX)
|
double _currentSpeedKbps = 0.0; // Total speed (RX+TX)
|
||||||
|
|
||||||
SessionTimer({required this.vpnConnection});
|
SessionTimer({required this.vpnConnection}) {
|
||||||
|
vpnConnection.addListener(_onVpnConnectionChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fires whenever VpnConnection state changes.
|
||||||
|
/// Only acts during startup restoration — normal connects go through ConnectButton.
|
||||||
|
void _onVpnConnectionChanged() {
|
||||||
|
if (vpnConnection.status == VpnStatus.connected &&
|
||||||
|
!isRunning &&
|
||||||
|
vpnConnection.isStartupRestoration) {
|
||||||
|
start('resume');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int get remaining => _remainingSeconds;
|
int get remaining => _remainingSeconds;
|
||||||
bool get isRunning => _timer != null && _timer!.isActive;
|
bool get isRunning => _timer != null && _timer!.isActive;
|
||||||
@@ -181,6 +193,7 @@ class SessionTimer extends ChangeNotifier {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
vpnConnection.removeListener(_onVpnConnectionChanged);
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
VpnNotificationManager.cancel();
|
VpnNotificationManager.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ class VpnConnection extends ChangeNotifier {
|
|||||||
VpnStatus _status = VpnStatus.disconnected;
|
VpnStatus _status = VpnStatus.disconnected;
|
||||||
VpnStatus get status => _status;
|
VpnStatus get status => _status;
|
||||||
|
|
||||||
|
// True only during the brief window after startup where we detected an
|
||||||
|
// already-running tunnel — lets SessionTimer know to auto-resume.
|
||||||
|
bool _isStartupRestoration = false;
|
||||||
|
bool get isStartupRestoration => _isStartupRestoration;
|
||||||
|
|
||||||
// Short message shown to the user under the connect button
|
// Short message shown to the user under the connect button
|
||||||
String _statusMessage = 'Tap to connect';
|
String _statusMessage = 'Tap to connect';
|
||||||
String get statusMessage => _statusMessage;
|
String get statusMessage => _statusMessage;
|
||||||
@@ -84,6 +89,20 @@ class VpnConnection extends ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
_stageSub = _wireguard.vpnStageSnapshot.listen(_mapStage);
|
_stageSub = _wireguard.vpnStageSnapshot.listen(_mapStage);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
|
// Check if the VPN was already running before the app started.
|
||||||
|
// This handles the case where the user swiped the app away and reopened it.
|
||||||
|
try {
|
||||||
|
final currentStage = await _wireguard.stage();
|
||||||
|
if (currentStage == VpnStage.connected) {
|
||||||
|
_isStartupRestoration = true;
|
||||||
|
_mapStage(currentStage);
|
||||||
|
// Clear the flag after a few seconds — only needed during app startup
|
||||||
|
Future.delayed(const Duration(seconds: 5), () {
|
||||||
|
_isStartupRestoration = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Native State Mapping ──────────────────────────────────────────────────
|
// ── Native State Mapping ──────────────────────────────────────────────────
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.0.1+3
|
version: 1.0.2+4
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
|
|||||||
Reference in new issue
Block a user