Fix settings button and dialog tab buttons

- Change 'Settings' button to 'Manage' with proper icon visibility
- Only show Manage button when in an organization (selectedOrg != null)
- Replace TabBar with custom animated tab buttons that match app styling
- Add smooth animations and visual feedback to tab buttons
- Maintain consistent splash effects across the dialog
This commit is contained in:
Leon Bösche
2026-01-24 00:00:04 +01:00
parent e10e499b6c
commit 48c9c19a64
2 changed files with 103 additions and 52 deletions

View File

@@ -493,28 +493,35 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
if (!isLoggedIn) {
return const SizedBox.shrink();
}
return Row(
mainAxisSize: MainAxisSize.min,
children: [
_buildNavButton('Drive', Icons.cloud),
const SizedBox(width: 16),
_buildNavButton('Mail', Icons.mail),
const SizedBox(width: 16),
_buildNavButton('Add', Icons.add),
const SizedBox(width: 16),
_buildNavButton(
'Settings',
Icons.settings,
onTap: () =>
_showOrganizationSettings(context),
),
const SizedBox(width: 16),
_buildNavButton(
'Profile',
Icons.person,
isAvatar: true,
),
],
return BlocBuilder<OrganizationBloc, OrganizationState>(
builder: (context, orgState) {
final hasSelectedOrg = orgState is OrganizationLoaded && orgState.selectedOrg != null;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
_buildNavButton('Drive', Icons.cloud),
const SizedBox(width: 16),
_buildNavButton('Mail', Icons.mail),
const SizedBox(width: 16),
_buildNavButton('Add', Icons.add),
const SizedBox(width: 16),
if (hasSelectedOrg)
_buildNavButton(
'Manage',
Icons.settings,
onTap: () =>
_showOrganizationSettings(context),
),
if (hasSelectedOrg)
const SizedBox(width: 16),
_buildNavButton(
'Profile',
Icons.person,
isAvatar: true,
),
],
);
},
);
},
),

View File

@@ -25,9 +25,8 @@ class OrganizationSettingsDialog extends StatefulWidget {
_OrganizationSettingsDialogState();
}
class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
with TickerProviderStateMixin {
late TabController _tabController;
class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog> {
int _selectedTabIndex = 0;
List<Member> _members = [];
List<Invitation> _invitations = [];
List<JoinRequest> _joinRequests = [];
@@ -39,16 +38,9 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
@override
void initState() {
super.initState();
_tabController = TabController(length: 4, vsync: this);
_loadData();
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
Future<void> _loadData() async {
if (!mounted) return;
setState(() => _isLoading = true);
@@ -226,18 +218,14 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
),
const SizedBox(height: 16),
// Tabs
TabBar(
controller: _tabController,
tabs: const [
Tab(text: 'Members'),
Tab(text: 'Invite'),
Tab(text: 'Requests'),
Tab(text: 'Link'),
// Custom Tabs
Row(
children: [
_buildTabButton('Members', 0),
_buildTabButton('Invite', 1),
_buildTabButton('Requests', 2),
_buildTabButton('Link', 3),
],
labelColor: AppTheme.accentColor,
unselectedLabelColor: AppTheme.secondaryText,
indicatorColor: AppTheme.accentColor,
),
const SizedBox(height: 16),
@@ -262,15 +250,7 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
],
),
)
: TabBarView(
controller: _tabController,
children: [
_buildMembersTab(),
_buildInviteTab(),
_buildRequestsTab(),
_buildLinkTab(),
],
),
: _buildTabContent(),
),
],
),
@@ -278,6 +258,70 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
);
}
Widget _buildTabButton(String text, int index) {
final isSelected = _selectedTabIndex == index;
return Expanded(
child: GestureDetector(
onTap: () => setState(() => _selectedTabIndex = index),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
margin: const EdgeInsets.symmetric(horizontal: 2),
decoration: BoxDecoration(
color: isSelected
? AppTheme.accentColor.withValues(alpha: 0.15)
: Colors.transparent,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: isSelected
? AppTheme.accentColor
: AppTheme.secondaryText.withValues(alpha: 0.3),
width: 1.5,
),
boxShadow: isSelected
? [
BoxShadow(
color: AppTheme.accentColor.withValues(alpha: 0.3),
blurRadius: 8,
spreadRadius: 1,
),
]
: null,
),
child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 200),
style: TextStyle(
color: isSelected
? AppTheme.accentColor
: AppTheme.secondaryText,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
fontSize: 14,
),
child: Text(
text,
textAlign: TextAlign.center,
),
),
),
),
);
}
Widget _buildTabContent() {
switch (_selectedTabIndex) {
case 0:
return _buildMembersTab();
case 1:
return _buildInviteTab();
case 2:
return _buildRequestsTab();
case 3:
return _buildLinkTab();
default:
return _buildMembersTab();
}
}
Widget _buildMembersTab() {
return ListView.builder(
itemCount: _members.length,