Merge branch 'dev' into dev

This commit is contained in:
PacoX
2026-05-28 08:51:23 +02:00
committed by GitHub
60 changed files with 1450 additions and 325 deletions
+44 -2
View File
@@ -6,11 +6,15 @@ import '../l10n/l10n.dart';
class QuickSwitchBar extends StatelessWidget {
final int selectedIndex;
final ValueChanged<int> onDestinationSelected;
final int contactsUnreadCount;
final int channelsUnreadCount;
const QuickSwitchBar({
super.key,
required this.selectedIndex,
required this.onDestinationSelected,
this.contactsUnreadCount = 0,
this.channelsUnreadCount = 0,
});
@override
@@ -62,15 +66,30 @@ class QuickSwitchBar extends StatelessWidget {
onDestinationSelected: onDestinationSelected,
destinations: [
NavigationDestination(
icon: const Icon(Icons.people_outline),
icon: _buildIconWithBadge(
const Icon(Icons.people_outline),
contactsUnreadCount,
),
selectedIcon: _buildIconWithBadge(
const Icon(Icons.people),
contactsUnreadCount,
),
label: context.l10n.nav_contacts,
),
NavigationDestination(
icon: const Icon(Icons.tag),
icon: _buildIconWithBadge(
const Icon(Icons.tag),
channelsUnreadCount,
),
selectedIcon: _buildIconWithBadge(
const Icon(Icons.tag),
channelsUnreadCount,
),
label: context.l10n.nav_channels,
),
NavigationDestination(
icon: const Icon(Icons.map_outlined),
selectedIcon: const Icon(Icons.map),
label: context.l10n.nav_map,
),
],
@@ -81,4 +100,27 @@ class QuickSwitchBar extends StatelessWidget {
),
);
}
Widget _buildIconWithBadge(Icon icon, int count) {
if (count <= 0) return icon;
return Stack(
clipBehavior: Clip.none,
children: [
icon,
Positioned(
right: -2,
top: -2,
child: Container(
width: 8,
height: 8,
decoration: const BoxDecoration(
color: Colors.redAccent,
shape: BoxShape.circle,
),
),
),
],
);
}
}
+60
View File
@@ -0,0 +1,60 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../connector/meshcore_connector.dart';
class SyncProgressAppBarBottom extends StatelessWidget
implements PreferredSizeWidget {
static const double height = 3;
const SyncProgressAppBarBottom({super.key});
@override
Size get preferredSize => const Size.fromHeight(height);
@override
Widget build(BuildContext context) {
return Consumer<MeshCoreConnector>(
builder: (context, connector, _) {
final state = _SyncProgressState.fromConnector(connector);
if (state == null) return const SizedBox(height: height);
return SizedBox(
height: height,
child: LinearProgressIndicator(
value: state.value,
minHeight: height,
color: state.color,
backgroundColor: state.color.withValues(alpha: 0.18),
),
);
},
);
}
}
class _SyncProgressState {
final double? value;
final Color color;
const _SyncProgressState({required this.value, required this.color});
static _SyncProgressState? fromConnector(MeshCoreConnector connector) {
if (connector.isLoadingContacts) {
return _SyncProgressState(
value: connector.contactSyncProgress,
color: Colors.red,
);
}
if (connector.isSyncingChannels) {
return _SyncProgressState(
value: connector.channelSyncProgress / 100,
color: Colors.blue,
);
}
if (connector.isShowingQueuedMessageSyncProgress) {
return const _SyncProgressState(value: null, color: Colors.green);
}
return null;
}
}