Skip to content

Commit 9eeae0b

Browse files
authored
Merge pull request #33 from headlines-toolkit/refactor_enhance_ui
Refactor enhance UI
2 parents fcff01b + e99df53 commit 9eeae0b

17 files changed

+1387
-1072
lines changed

l10n.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
arb-dir: lib/l10n/arb
22
template-arb-file: app_en.arb
33
output-localization-file: app_localizations.dart
4-
nullable-getter: false
4+
output-dir: lib/l10n
5+
nullable-getter: false

lib/account/view/account_page.dart

Lines changed: 75 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -22,105 +22,122 @@ class AccountPage extends StatelessWidget {
2222
// Watch AppBloc for user details and authentication status
2323
final appState = context.watch<AppBloc>().state;
2424
final user = appState.user;
25-
final status = appState.status; // Use AppStatus from AppBloc state
26-
27-
// Determine if the user is anonymous
28-
final isAnonymous =
29-
status == AppStatus.anonymous; // Use AppStatus.anonymous
25+
final status = appState.status;
26+
final isAnonymous = status == AppStatus.anonymous;
27+
final theme = Theme.of(context); // Get theme for AppBar
28+
final textTheme = theme.textTheme; // Get textTheme for AppBar
3029

3130
return Scaffold(
32-
appBar: AppBar(title: Text(l10n.accountPageTitle)),
31+
appBar: AppBar(
32+
title: Text(
33+
l10n.accountPageTitle,
34+
style: textTheme.titleLarge, // Consistent AppBar title style
35+
),
36+
),
3337
body: ListView(
34-
// Use ListView for potential scrolling if content grows
35-
padding: const EdgeInsets.all(AppSpacing.lg), // Use AppSpacing
38+
padding: const EdgeInsets.all(AppSpacing.paddingMedium), // Adjusted padding
3639
children: [
37-
// --- User Header ---
3840
_buildUserHeader(context, user, isAnonymous),
39-
const SizedBox(height: AppSpacing.xl), // Use AppSpacing
40-
// --- Action Tiles ---
41-
// Content Preferences Tile
41+
const SizedBox(height: AppSpacing.lg), // Adjusted spacing
4242
ListTile(
43-
leading: const Icon(Icons.tune_outlined),
44-
title: Text(l10n.accountContentPreferencesTile),
43+
leading: Icon(Icons.tune_outlined, color: theme.colorScheme.primary),
44+
title: Text(
45+
l10n.accountContentPreferencesTile,
46+
style: textTheme.titleMedium,
47+
),
4548
trailing: const Icon(Icons.chevron_right),
4649
onTap: () {
47-
context.goNamed(Routes.manageFollowedItemsName); // Updated route
50+
context.goNamed(Routes.manageFollowedItemsName);
4851
},
4952
),
50-
const Divider(), // Divider after Content Preferences
51-
// Saved Headlines Tile
53+
const Divider(indent: AppSpacing.paddingMedium, endIndent: AppSpacing.paddingMedium),
5254
ListTile(
53-
leading: const Icon(Icons.bookmark_outline),
54-
title: Text(l10n.accountSavedHeadlinesTile),
55+
leading: Icon(Icons.bookmark_outline, color: theme.colorScheme.primary),
56+
title: Text(
57+
l10n.accountSavedHeadlinesTile,
58+
style: textTheme.titleMedium,
59+
),
5560
trailing: const Icon(Icons.chevron_right),
5661
onTap: () {
5762
context.goNamed(Routes.accountSavedHeadlinesName);
5863
},
5964
),
60-
const Divider(), // Divider after Saved Headlines
61-
// Settings Tile
65+
const Divider(indent: AppSpacing.paddingMedium, endIndent: AppSpacing.paddingMedium),
6266
_buildSettingsTile(context),
63-
const Divider(), // Divider after settings
67+
const Divider(indent: AppSpacing.paddingMedium, endIndent: AppSpacing.paddingMedium),
6468
],
6569
),
6670
);
6771
}
6872

69-
/// Builds the header section displaying user avatar, name, and status.
7073
Widget _buildUserHeader(BuildContext context, User? user, bool isAnonymous) {
7174
final l10n = context.l10n;
7275
final theme = Theme.of(context);
7376
final textTheme = theme.textTheme;
77+
final colorScheme = theme.colorScheme; // Get colorScheme
7478

75-
// Use a generic icon for the avatar
76-
const avatarIcon = Icon(Icons.person, size: 40);
79+
final avatarIcon = Icon(
80+
Icons.person_outline, // Use outlined version
81+
size: AppSpacing.xxl, // Standardized size
82+
color: colorScheme.onPrimaryContainer,
83+
);
7784

78-
// Determine display name and status text
7985
final String displayName;
8086
final Widget statusWidget;
8187

8288
if (isAnonymous) {
8389
displayName = l10n.accountAnonymousUser;
8490
statusWidget = Padding(
85-
padding: const EdgeInsets.only(top: AppSpacing.sm),
86-
child: TextButton(
91+
padding: const EdgeInsets.only(top: AppSpacing.md), // Increased padding
92+
child: ElevatedButton.icon( // Changed to ElevatedButton
93+
icon: const Icon(Icons.link_outlined),
94+
label: Text(l10n.accountSignInPromptButton),
95+
style: ElevatedButton.styleFrom(
96+
padding: const EdgeInsets.symmetric(
97+
horizontal: AppSpacing.lg, vertical: AppSpacing.sm,
98+
),
99+
textStyle: textTheme.labelLarge,
100+
),
87101
onPressed: () {
88-
// Navigate to the authentication page in linking mode
89102
context.goNamed(
90103
Routes.authenticationName,
91104
queryParameters: {'context': 'linking'},
92105
);
93106
},
94-
child: Text(l10n.accountSignInPromptButton),
95107
),
96108
);
97109
} else {
98-
// For authenticated users, display email and role
99110
displayName = user?.email ?? l10n.accountNoNameUser;
100111
statusWidget = Column(
112+
mainAxisSize: MainAxisSize.min, // To keep column tight
101113
children: [
102-
const SizedBox(height: AppSpacing.sm),
103-
Text(
104-
l10n.accountRoleLabel(user?.role.name ?? 'unknown'), // Display role
105-
style: textTheme.bodyMedium?.copyWith(
106-
color: theme.colorScheme.onSurfaceVariant,
114+
if (user?.role != null) ...[ // Show role only if available
115+
const SizedBox(height: AppSpacing.xs),
116+
Text(
117+
l10n.accountRoleLabel(user!.role.name),
118+
style: textTheme.bodyMedium?.copyWith(
119+
color: colorScheme.onSurfaceVariant,
120+
),
121+
textAlign: TextAlign.center,
107122
),
108-
textAlign: TextAlign.center,
109-
),
110-
const SizedBox(height: AppSpacing.sm),
111-
OutlinedButton(
123+
],
124+
const SizedBox(height: AppSpacing.md), // Consistent spacing
125+
OutlinedButton.icon( // Changed to OutlinedButton.icon
126+
icon: Icon(Icons.logout, color: colorScheme.error),
127+
label: Text(l10n.accountSignOutTile),
112128
style: OutlinedButton.styleFrom(
113-
foregroundColor: theme.colorScheme.error,
114-
side: BorderSide(color: theme.colorScheme.error),
129+
foregroundColor: colorScheme.error,
130+
side: BorderSide(color: colorScheme.error.withOpacity(0.5)),
131+
padding: const EdgeInsets.symmetric(
132+
horizontal: AppSpacing.lg, vertical: AppSpacing.sm,
133+
),
134+
textStyle: textTheme.labelLarge,
115135
),
116136
onPressed: () {
117-
// Dispatch AuthenticationSignOutRequested from Auth Bloc
118-
context.read<AuthenticationBloc>().add(
119-
const AuthenticationSignOutRequested(),
120-
);
121-
// Global redirect will be handled by AppBloc/GoRouter
137+
context
138+
.read<AuthenticationBloc>()
139+
.add(const AuthenticationSignOutRequested());
122140
},
123-
child: Text(l10n.accountSignOutTile),
124141
),
125142
],
126143
);
@@ -129,30 +146,31 @@ class AccountPage extends StatelessWidget {
129146
return Column(
130147
children: [
131148
CircleAvatar(
132-
radius: 40,
133-
backgroundColor: theme.colorScheme.primaryContainer,
149+
radius: AppSpacing.xxl - AppSpacing.sm, // Standardized radius (40)
150+
backgroundColor: colorScheme.primaryContainer,
134151
child: avatarIcon,
135152
),
136-
const SizedBox(height: AppSpacing.lg), // Use AppSpacing
153+
const SizedBox(height: AppSpacing.md), // Adjusted spacing
137154
Text(
138155
displayName,
139-
style: textTheme.titleLarge,
156+
style: textTheme.headlineSmall, // More prominent style
140157
textAlign: TextAlign.center,
141158
),
142-
statusWidget, // Display sign-in button or role/logout button
159+
statusWidget,
143160
],
144161
);
145162
}
146163

147-
/// Builds the ListTile for navigating to Settings.
148164
Widget _buildSettingsTile(BuildContext context) {
149165
final l10n = context.l10n;
166+
final theme = Theme.of(context);
167+
final textTheme = theme.textTheme;
168+
150169
return ListTile(
151-
leading: const Icon(Icons.settings_outlined),
152-
title: Text(l10n.accountSettingsTile),
170+
leading: Icon(Icons.settings_outlined, color: theme.colorScheme.primary),
171+
title: Text(l10n.accountSettingsTile, style: textTheme.titleMedium),
153172
trailing: const Icon(Icons.chevron_right),
154173
onTap: () {
155-
// Navigate to the existing settings route
156174
context.goNamed(Routes.settingsName);
157175
},
158176
);

0 commit comments

Comments
 (0)