chore: release v1.4.0
- Decentralized Room Registry pattern - Each room registers itself with central registry - Dynamic navigation tabs and settings dropdown - New Media Room and Parlor feature folders - Permission-based room filtering support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
40ba6a869d
commit
c3f6d27a52
@@ -4,9 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:tatlock_ui/core/auth/auth_provider.dart';
|
||||
import 'package:tatlock_ui/core/config/app_config.dart';
|
||||
import 'package:tatlock_ui/features/control_room/router.dart';
|
||||
import 'package:tatlock_ui/features/security/router.dart';
|
||||
import 'package:tatlock_ui/routing/app_router.dart';
|
||||
import 'package:tatlock_ui/routing/room_registry.dart';
|
||||
import 'package:tatlock_ui/shared/layouts/widgets/top_header_bar.dart';
|
||||
|
||||
/// Main application scaffold with top header navigation.
|
||||
@@ -217,22 +215,13 @@ class _AppScaffoldState extends ConsumerState<AppScaffold> {
|
||||
|
||||
int _selectedIndex(BuildContext context) {
|
||||
final location = GoRouterState.of(context).matchedLocation;
|
||||
|
||||
if (location.startsWith(ControlRoomRoutes.base)) return 1;
|
||||
if (location.startsWith(SecurityRoutes.base)) return 2;
|
||||
if (location.startsWith(AppRoutes.parlor)) return 3;
|
||||
// Settings is no longer in main nav (accessed via Profile dropdown)
|
||||
return 0; // Front Hall
|
||||
return roomRegistry.indexOfRoute(location);
|
||||
}
|
||||
|
||||
void _onNavSelected(BuildContext context, int index) {
|
||||
final route = switch (index) {
|
||||
0 => AppRoutes.frontHall,
|
||||
1 => ControlRoomRoutes.containers,
|
||||
2 => SecurityRoutes.users,
|
||||
3 => AppRoutes.parlor,
|
||||
_ => AppRoutes.frontHall,
|
||||
};
|
||||
context.go(route);
|
||||
final rooms = roomRegistry.all;
|
||||
if (index >= 0 && index < rooms.length) {
|
||||
context.go(rooms[index].defaultRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tatlock_ui/core/semantics/semantic_ids.dart';
|
||||
import 'package:tatlock_ui/routing/room_registry.dart';
|
||||
|
||||
import 'profile_dropdown.dart';
|
||||
|
||||
@@ -24,28 +25,8 @@ class TopHeaderBar extends StatelessWidget {
|
||||
static const double _logoCircleRadius = (_logoSize + _logoMargin * 2) / 2; // 64px
|
||||
static const double _bulgeFraction = 0.20; // 20% of circle below header line
|
||||
|
||||
static const _rooms = [
|
||||
_RoomDestination(
|
||||
icon: Icons.door_front_door_outlined,
|
||||
selectedIcon: Icons.door_front_door,
|
||||
label: 'Front Hall',
|
||||
),
|
||||
_RoomDestination(
|
||||
icon: Icons.dns_outlined,
|
||||
selectedIcon: Icons.dns,
|
||||
label: 'Control Room',
|
||||
),
|
||||
_RoomDestination(
|
||||
icon: Icons.security_outlined,
|
||||
selectedIcon: Icons.security,
|
||||
label: 'Security',
|
||||
),
|
||||
_RoomDestination(
|
||||
icon: Icons.lightbulb_outline,
|
||||
selectedIcon: Icons.lightbulb,
|
||||
label: 'Parlor',
|
||||
),
|
||||
];
|
||||
/// Get rooms from the registry.
|
||||
List<RoomDefinition> get _rooms => roomRegistry.all;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -121,9 +102,10 @@ class TopHeaderBar extends StatelessWidget {
|
||||
|
||||
List<Widget> _buildRoomTabs(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final rooms = _rooms;
|
||||
|
||||
return List.generate(_rooms.length, (index) {
|
||||
final room = _rooms[index];
|
||||
return List.generate(rooms.length, (index) {
|
||||
final room = rooms[index];
|
||||
final isSelected = index == selectedIndex;
|
||||
|
||||
return Padding(
|
||||
@@ -257,14 +239,3 @@ class _HeaderPainter extends CustomPainter {
|
||||
}
|
||||
}
|
||||
|
||||
class _RoomDestination {
|
||||
const _RoomDestination({
|
||||
required this.icon,
|
||||
required this.selectedIcon,
|
||||
required this.label,
|
||||
});
|
||||
|
||||
final IconData icon;
|
||||
final IconData selectedIcon;
|
||||
final String label;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user