2026-03-06 13:01:23 -08:00
|
|
|
import 'package:flutter/material.dart';
|
2026-03-10 09:11:25 -07:00
|
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
2026-03-06 13:01:23 -08:00
|
|
|
import 'screens/login_screen.dart';
|
2026-03-10 09:11:25 -07:00
|
|
|
import 'screens/phone_screen.dart';
|
2026-03-06 13:01:23 -08:00
|
|
|
|
|
|
|
|
class TwpSoftphoneApp extends StatefulWidget {
|
|
|
|
|
const TwpSoftphoneApp({super.key});
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
State<TwpSoftphoneApp> createState() => _TwpSoftphoneAppState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _TwpSoftphoneAppState extends State<TwpSoftphoneApp> {
|
2026-03-10 09:11:25 -07:00
|
|
|
static const _storage = FlutterSecureStorage();
|
|
|
|
|
String? _serverUrl;
|
|
|
|
|
bool _loading = true;
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
_checkSavedSession();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _checkSavedSession() async {
|
|
|
|
|
final url = await _storage.read(key: 'server_url');
|
|
|
|
|
if (mounted) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_serverUrl = url;
|
|
|
|
|
_loading = false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _onLoginSuccess(String serverUrl) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_serverUrl = serverUrl;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _onLogout() async {
|
|
|
|
|
await _storage.delete(key: 'server_url');
|
|
|
|
|
if (mounted) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_serverUrl = null;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _onSessionExpired() {
|
|
|
|
|
// Server URL is still saved, but session cookie is gone.
|
|
|
|
|
// Show login screen but keep the server URL pre-filled.
|
|
|
|
|
if (mounted) {
|
|
|
|
|
setState(() {
|
|
|
|
|
_serverUrl = null;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-06 13:01:23 -08:00
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
2026-03-10 09:11:25 -07:00
|
|
|
return MaterialApp(
|
|
|
|
|
title: 'TWP Softphone',
|
|
|
|
|
debugShowCheckedModeBanner: false,
|
|
|
|
|
theme: ThemeData(
|
|
|
|
|
colorSchemeSeed: Colors.blue,
|
|
|
|
|
useMaterial3: true,
|
|
|
|
|
brightness: Brightness.light,
|
|
|
|
|
),
|
|
|
|
|
darkTheme: ThemeData(
|
|
|
|
|
colorSchemeSeed: Colors.blue,
|
|
|
|
|
useMaterial3: true,
|
|
|
|
|
brightness: Brightness.dark,
|
2026-03-06 13:01:23 -08:00
|
|
|
),
|
2026-03-10 09:11:25 -07:00
|
|
|
home: _loading
|
|
|
|
|
? const Scaffold(
|
|
|
|
|
body: Center(child: CircularProgressIndicator()),
|
|
|
|
|
)
|
|
|
|
|
: _serverUrl != null
|
|
|
|
|
? PhoneScreen(
|
|
|
|
|
serverUrl: _serverUrl!,
|
|
|
|
|
onLogout: _onLogout,
|
|
|
|
|
onSessionExpired: _onSessionExpired,
|
|
|
|
|
)
|
|
|
|
|
: LoginScreen(onLoginSuccess: _onLoginSuccess),
|
2026-03-06 13:01:23 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|