feat: erweiterte Chat-Funktionalität, UI-Verbesserungen und Lokalisierungsupdates
- Chat: Nachrichten-Status (read/unread), WebSocket-Verbesserungen - App: Login-Optimierung, Job-Übersicht verbessert, neue Übersetzungen - Backend: Dialog-Styling, Invoice-Generator, Job-Verwaltung erweitert - Mehrsprachigkeit: Neue Übersetzungen für DE, EN, ES, ET, FR, LT, LV, PL, RU, TR
This commit is contained in:
@@ -13,6 +13,7 @@ import 'services/chat_service.dart';
|
||||
import 'app_state.dart';
|
||||
import 'navigation_observer.dart';
|
||||
import 'services/notification_service.dart';
|
||||
import 'services/websocket_service.dart';
|
||||
import 'l10n/app_localizations.dart';
|
||||
|
||||
void main() async {
|
||||
@@ -43,14 +44,59 @@ void main() async {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
class MyApp extends StatefulWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
State<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
static const Duration _resumeReconnectThreshold = Duration(seconds: 30);
|
||||
final AppState _appState = AppState();
|
||||
final WebSocketService _webSocketService = WebSocketService();
|
||||
DateTime? _lastPausedAt;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (state == AppLifecycleState.paused) {
|
||||
_lastPausedAt = DateTime.now();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
final pausedAt = _lastPausedAt;
|
||||
_lastPausedAt = null;
|
||||
if (pausedAt == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final standbyDuration = DateTime.now().difference(pausedAt);
|
||||
if (standbyDuration < _resumeReconnectThreshold ||
|
||||
!_appState.isLoggedIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
_webSocketService.reconnectForAppResume();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Check if user is already logged in
|
||||
final appState = AppState();
|
||||
final initialRoute = appState.isLoggedIn ? '/jobs' : '/login';
|
||||
final initialRoute = _appState.isLoggedIn ? '/jobs' : '/login';
|
||||
|
||||
return ValueListenableBuilder<Locale>(
|
||||
valueListenable: localeNotifier,
|
||||
@@ -58,11 +104,20 @@ class MyApp extends StatelessWidget {
|
||||
return MaterialApp(
|
||||
title: 'VotianLT App',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true),
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
// Localization configuration
|
||||
locale: locale,
|
||||
localizationsDelegates: const [AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate],
|
||||
supportedLocales: supportedLanguageCodes.map((code) => Locale(code)).toList(),
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales:
|
||||
supportedLanguageCodes.map((code) => Locale(code)).toList(),
|
||||
navigatorObservers: [routeObserver],
|
||||
initialRoute: initialRoute,
|
||||
onGenerateRoute: (settings) {
|
||||
@@ -70,21 +125,30 @@ class MyApp extends StatelessWidget {
|
||||
case '/login':
|
||||
final arg = settings.arguments;
|
||||
final suppress = (arg is bool) ? arg : false;
|
||||
return MaterialPageRoute(builder: (_) => LoginView(suppressConnectionSnack: suppress));
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => LoginView(suppressConnectionSnack: suppress),
|
||||
);
|
||||
case '/jobs':
|
||||
return MaterialPageRoute(builder: (_) => const JobsView());
|
||||
case '/cargo_items':
|
||||
final job = settings.arguments as Job;
|
||||
return MaterialPageRoute(builder: (_) => CargoItemsView(job: job));
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => CargoItemsView(job: job),
|
||||
);
|
||||
case '/chats':
|
||||
return MaterialPageRoute(builder: (_) => const ChatsView());
|
||||
case '/chat_details':
|
||||
final chat = settings.arguments as Chat;
|
||||
return MaterialPageRoute(builder: (_) => ChatDetailsView(chat: chat));
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => ChatDetailsView(chat: chat),
|
||||
);
|
||||
case '/settings':
|
||||
return MaterialPageRoute(builder: (_) => const SettingsView());
|
||||
default:
|
||||
return MaterialPageRoute(builder: (_) => const LoginView(suppressConnectionSnack: false));
|
||||
return MaterialPageRoute(
|
||||
builder:
|
||||
(_) => const LoginView(suppressConnectionSnack: false),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -114,9 +178,27 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
|
||||
body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[const Text('You have pushed the button this many times:'), Text('$_counter', style: Theme.of(context).textTheme.headlineMedium)])),
|
||||
floatingActionButton: FloatingActionButton(onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add)), // This trailing comma makes auto-formatting nicer for build methods.
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text('You have pushed the button this many times:'),
|
||||
Text(
|
||||
'$_counter',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _incrementCounter,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.add),
|
||||
), // This trailing comma makes auto-formatting nicer for build methods.
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user