first working version

This commit is contained in:
stopflock committed 2026-09-23 14:39:11 -05:00
1 parent c95171a3ad
commit 54ef1b8afc
26 files changed
+745 -27

No files matched your search

+22 -2
View File
@@ -37,7 +37,7 @@ class HomeScreen extends StatefulWidget {
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin, WidgetsBindingObserver {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final GlobalKey<MapViewState> _mapViewKey = GlobalKey<MapViewState>();
late final AnimatedMapController _mapController;
@@ -62,6 +62,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_mapController = AnimatedMapController(vsync: this);
_sheetCoordinator = SheetCoordinator();
_navigationCoordinator = NavigationCoordinator();
@@ -71,11 +72,24 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
DeepLinkService().onNodeDeepLink = null;
_mapController.dispose();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
// Re-check for an active OSM block when the user returns to the app,
// in case they resolved it (or got blocked) while away.
if (state == AppLifecycleState.resumed) {
final appState = context.read<AppState>();
if (appState.isLoggedIn) {
appState.checkAndPromptForActiveBlock(context);
}
}
}
String _getFollowMeTooltip(FollowMeMode mode) {
final locService = LocalizationService.instance;
switch (mode) {
@@ -474,6 +488,10 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
_checkForPopup();
// Check if re-authentication is needed for message notifications
appState.checkAndPromptReauthForMessages(context);
// Check for an active OSM block on app launch
if (appState.isLoggedIn) {
appState.checkAndPromptForActiveBlock(context);
}
});
}
@@ -544,7 +562,9 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
return IconButton(
tooltip: LocalizationService.instance.settings,
icon: Badge(
isLabelVisible: appState.hasUnreadNotifications,
isLabelVisible: appState.hasActiveBlock || appState.hasUnreadNotifications,
backgroundColor: appState.hasActiveBlock ? Colors.red : null,
label: appState.hasActiveBlock ? const Icon(Icons.block, size: 10, color: Colors.white) : null,
child: const Icon(Icons.settings),
),
onPressed: () => Navigator.pushNamed(context, '/settings'),
+30 -2
View File
@@ -17,11 +17,12 @@ class _OSMAccountScreenState extends State<OSMAccountScreen> {
@override
void initState() {
super.initState();
// Check for messages when screen loads
// Check for messages and active blocks when screen loads
WidgetsBinding.instance.addPostFrameCallback((_) {
final appState = context.read<AppState>();
if (appState.isLoggedIn) {
appState.checkMessages();
appState.checkAndPromptForActiveBlock(context);
}
});
}
@@ -83,13 +84,40 @@ class _OSMAccountScreenState extends State<OSMAccountScreen> {
),
if (appState.isLoggedIn) ...[
// Active block warning - shown whenever a check has
// found the user's OSM account currently blocked.
if (appState.hasActiveBlock) ...[
const Divider(),
ListTile(
leading: Badge(
isLabelVisible: true,
backgroundColor: Colors.red,
child: const Icon(Icons.block, color: Colors.red),
),
title: Text(locService.t('auth.activeBlockTitle')),
subtitle: Text(locService.t('auth.activeBlockMessage')),
trailing: const Icon(Icons.open_in_new),
onTap: () async {
final url = Uri.parse(appState.getMessagesUrl());
if (await canLaunchUrl(url)) {
await launchUrl(url, mode: LaunchMode.externalApplication);
} else {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(locService.t('advancedEdit.couldNotOpenOSMWebsite'))),
);
}
}
},
),
],
const Divider(),
ListTile(
leading: const Icon(Icons.wifi_protected_setup),
title: Text(locService.t('auth.testConnection')),
subtitle: Text(locService.t('auth.testConnectionSubtitle')),
onTap: () async {
final isValid = await appState.validateToken();
final isValid = await appState.testConnection(context);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
@@ -53,7 +53,7 @@ class AuthSection extends StatelessWidget {
title: Text(locService.t('auth.testConnection')),
subtitle: Text(locService.t('auth.testConnectionSubtitle')),
onTap: () async {
final isValid = await appState.validateToken();
final isValid = await appState.testConnection(context);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
+3 -1
View File
@@ -118,7 +118,9 @@ class SettingsScreen extends StatelessWidget {
return ListTile(
leading: Badge(
isLabelVisible: appState.hasUnreadNotifications,
isLabelVisible: appState.hasActiveBlock || appState.hasUnreadNotifications,
backgroundColor: appState.hasActiveBlock ? Colors.red : null,
label: appState.hasActiveBlock ? const Icon(Icons.block, size: 10, color: Colors.white) : null,
child: const Icon(Icons.account_circle),
),
title: Text(locService.t('auth.osmAccountTitle')),
+6 -4
View File
@@ -111,7 +111,7 @@ class UploadQueueScreen extends StatelessWidget {
final appState = context.watch<AppState>();
// Check if queue processing is paused
final isQueuePaused = appState.offlineMode || appState.pauseQueueProcessing;
final isQueuePaused = appState.offlineMode || appState.pauseQueueProcessing || appState.isQueuePausedDueToBlock;
return Scaffold(
appBar: AppBar(
@@ -151,9 +151,11 @@ class UploadQueueScreen extends StatelessWidget {
),
),
Text(
appState.offlineMode
? locService.t('queue.pausedDueToOffline')
: locService.t('queue.pausedByUser'),
appState.isQueuePausedDueToBlock
? locService.t('queue.pausedDueToBlock')
: appState.offlineMode
? locService.t('queue.pausedDueToOffline')
: locService.t('queue.pausedByUser'),
style: TextStyle(
fontSize: 12,
color: Colors.orange.shade700,