Skip to content

Commit 5ca757b

Browse files
committed
style
1 parent f7d9a93 commit 5ca757b

File tree

4 files changed

+103
-95
lines changed

4 files changed

+103
-95
lines changed

lib/app/view/app.dart

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ class _AppViewState extends State<_AppView> {
108108

109109
// Initial check in case status is already known *at the end of initState*
110110
if (_currentAppStatus != AppStatus.initial) {
111-
_isAuthStatusKnown = true;
112-
_updateRouterNotifier();
111+
_isAuthStatusKnown = true;
112+
_updateRouterNotifier();
113113
}
114114
}
115115

@@ -215,20 +215,21 @@ class _AppViewState extends State<_AppView> {
215215

216216
// If the status is no longer initial, mark it as known
217217
if (state.status != AppStatus.initial) {
218-
if (!_isAuthStatusKnown) { // Only update state if it changes
219-
setState(() {
220-
_isAuthStatusKnown = true;
221-
});
218+
if (!_isAuthStatusKnown) {
219+
// Only update state if it changes
220+
setState(() {
221+
_isAuthStatusKnown = true;
222+
});
222223
}
223224
_updateRouterNotifier(); // Check if we can navigate away
224225
}
225226
// If the status somehow reverts to initial (unlikely), reset flag
226227
else if (_isAuthStatusKnown) {
227-
setState(() {
228-
_isAuthStatusKnown = false;
229-
});
230-
// Ensure router notifier reflects initial state again
231-
_routerNotifier.value = AppStatus.initial;
228+
setState(() {
229+
_isAuthStatusKnown = false;
230+
});
231+
// Ensure router notifier reflects initial state again
232+
_routerNotifier.value = AppStatus.initial;
232233
}
233234
},
234235
child: BlocBuilder<AppBloc, AppState>(

lib/headlines-search/view/headlines_search_page.dart

Lines changed: 75 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//
2+
// ignore_for_file: lines_longer_than_80_chars
3+
14
import 'package:flutter/material.dart';
25
import 'package:flutter_bloc/flutter_bloc.dart';
36
import 'package:ht_headlines_repository/ht_headlines_repository.dart';
@@ -20,9 +23,10 @@ class HeadlinesSearchPage extends StatelessWidget {
2023
@override
2124
Widget build(BuildContext context) {
2225
return BlocProvider(
23-
create: (_) => HeadlinesSearchBloc(
24-
headlinesRepository: context.read<HtHeadlinesRepository>(),
25-
),
26+
create:
27+
(_) => HeadlinesSearchBloc(
28+
headlinesRepository: context.read<HtHeadlinesRepository>(),
29+
),
2630
// The actual UI is built by the private _HeadlinesSearchView widget.
2731
child: const _HeadlinesSearchView(),
2832
);
@@ -40,7 +44,8 @@ class _HeadlinesSearchView extends StatefulWidget {
4044

4145
class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
4246
final _scrollController = ScrollController();
43-
final _textController = TextEditingController(); // Controller for the TextField
47+
final _textController =
48+
TextEditingController(); // Controller for the TextField
4449
bool _showClearButton = false; // State to control clear button visibility
4550

4651
@override
@@ -68,11 +73,11 @@ class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
6873
void _onScroll() {
6974
final state = context.read<HeadlinesSearchBloc>().state;
7075
if (_isBottom && state is HeadlinesSearchSuccess) {
71-
final searchTerm = state.lastSearchTerm; // Use lastSearchTerm from state
76+
final searchTerm = state.lastSearchTerm;
7277
if (state.hasMore) {
7378
context.read<HeadlinesSearchBloc>().add(
74-
HeadlinesSearchFetchRequested(searchTerm: searchTerm!),
75-
);
79+
HeadlinesSearchFetchRequested(searchTerm: searchTerm!),
80+
);
7681
}
7782
}
7883
}
@@ -89,8 +94,8 @@ class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
8994
/// Triggers a search request based on the current text input.
9095
void _performSearch() {
9196
context.read<HeadlinesSearchBloc>().add(
92-
HeadlinesSearchFetchRequested(searchTerm: _textController.text),
93-
);
97+
HeadlinesSearchFetchRequested(searchTerm: _textController.text),
98+
);
9499
}
95100

96101
@override
@@ -105,12 +110,13 @@ class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
105110
// Enhanced TextField integrated into the AppBar title
106111
title: TextField(
107112
controller: _textController,
108-
// Use text style that contrasts well with AppBar background
113+
109114
style: appBarTheme.titleTextStyle ?? theme.textTheme.titleLarge,
110115
decoration: InputDecoration(
111116
hintText: l10n.headlinesSearchHintText,
112-
// Use hint style that contrasts well
113-
hintStyle: appBarTheme.titleTextStyle?.copyWith(
117+
118+
hintStyle:
119+
appBarTheme.titleTextStyle?.copyWith(
114120
color: (appBarTheme.titleTextStyle?.color ??
115121
colorScheme.onSurface)
116122
.withOpacity(0.6),
@@ -126,28 +132,28 @@ class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
126132
enabledBorder: InputBorder.none,
127133
// Add a subtle background fill
128134
filled: true,
129-
// Use a subtle color from the theme for the fill
135+
130136
fillColor: colorScheme.surface.withOpacity(0.1),
131137
// Apply consistent padding using AppSpacing
132138
contentPadding: const EdgeInsets.symmetric(
133139
horizontal: AppSpacing.paddingMedium,
134-
vertical: AppSpacing.paddingSmall, // Adjust vertical padding as needed
140+
vertical:
141+
AppSpacing.paddingSmall, // Adjust vertical padding as needed
135142
),
136143
// Add a clear button that appears when text is entered
137-
suffixIcon: _showClearButton
138-
? IconButton(
139-
icon: Icon(
140-
Icons.clear,
141-
// Use icon color appropriate for AppBar
142-
color: appBarTheme.iconTheme?.color ?? colorScheme.onSurface,
143-
),
144-
onPressed: () {
145-
_textController.clear();
146-
// Optionally trigger an empty search or reset state
147-
// _performSearch(); // Uncomment if clearing should trigger search
148-
},
149-
)
150-
: null, // No icon when text field is empty
144+
suffixIcon:
145+
_showClearButton
146+
? IconButton(
147+
icon: Icon(
148+
Icons.clear,
149+
150+
color:
151+
appBarTheme.iconTheme?.color ??
152+
colorScheme.onSurface,
153+
),
154+
onPressed: _textController.clear,
155+
)
156+
: null, // No icon when text field is empty
151157
),
152158
// Trigger search on submit (e.g., pressing Enter on keyboard)
153159
onSubmitted: (_) => _performSearch(),
@@ -157,7 +163,7 @@ class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
157163
IconButton(
158164
icon: const Icon(Icons.search),
159165
tooltip: l10n.headlinesSearchActionTooltip, // Re-added tooltip
160-
onPressed: _performSearch, // Use the dedicated search method
166+
onPressed: _performSearch,
161167
),
162168
],
163169
),
@@ -167,57 +173,57 @@ class _HeadlinesSearchViewState extends State<_HeadlinesSearchView> {
167173
return switch (state) {
168174
// Loading state
169175
HeadlinesSearchLoading() => InitialStateWidget(
170-
icon: Icons.manage_search, // Changed icon
171-
headline: l10n.headlinesSearchInitialHeadline, // Keep initial text for loading phase
172-
subheadline: l10n.headlinesSearchInitialSubheadline,
173-
),
176+
icon: Icons.manage_search, // Changed icon
177+
headline:
178+
l10n.headlinesSearchInitialHeadline, // Keep initial text for loading phase
179+
subheadline: l10n.headlinesSearchInitialSubheadline,
180+
),
174181
// Success state with results
175182
HeadlinesSearchSuccess(
176183
:final headlines,
177184
:final hasMore,
178185
:final errorMessage, // Check for specific error message within success
179-
:final lastSearchTerm, // Use lastSearchTerm for retries
186+
:final lastSearchTerm,
180187
) =>
181188
errorMessage != null
182189
// Display error if present within success state
183190
? FailureStateWidget(
184-
message: errorMessage,
185-
onRetry: () {
186-
// Retry with the last successful search term
187-
context.read<HeadlinesSearchBloc>().add(
188-
HeadlinesSearchFetchRequested(
189-
searchTerm: lastSearchTerm ?? '',
190-
),
191-
);
192-
},
193-
)
191+
message: errorMessage,
192+
onRetry: () {
193+
// Retry with the last successful search term
194+
context.read<HeadlinesSearchBloc>().add(
195+
HeadlinesSearchFetchRequested(
196+
searchTerm: lastSearchTerm ?? '',
197+
),
198+
);
199+
},
200+
)
194201
// Display "no results" if list is empty
195202
: headlines.isEmpty
196-
? InitialStateWidget(
197-
icon: Icons.search_off,
198-
headline: l10n.headlinesSearchNoResultsHeadline,
199-
subheadline:
200-
l10n.headlinesSearchNoResultsSubheadline,
201-
)
202-
// Display the list of headlines
203-
: ListView.builder(
204-
controller: _scrollController,
205-
// Add 1 for loading indicator if more items exist
206-
itemCount:
207-
hasMore ? headlines.length + 1 : headlines.length,
208-
itemBuilder: (context, index) {
209-
// Show loading indicator at the end if hasMore
210-
if (index >= headlines.length) {
211-
// Ensure loading indicator is visible
212-
return const Padding(
213-
padding: EdgeInsets.all(AppSpacing.paddingLarge),
214-
child: Center(child: CircularProgressIndicator()),
215-
);
216-
}
217-
// Display headline item
218-
return HeadlineItemWidget(headline: headlines[index]);
219-
},
220-
),
203+
? InitialStateWidget(
204+
icon: Icons.search_off,
205+
headline: l10n.headlinesSearchNoResultsHeadline,
206+
subheadline: l10n.headlinesSearchNoResultsSubheadline,
207+
)
208+
// Display the list of headlines
209+
: ListView.builder(
210+
controller: _scrollController,
211+
// Add 1 for loading indicator if more items exist
212+
itemCount:
213+
hasMore ? headlines.length + 1 : headlines.length,
214+
itemBuilder: (context, index) {
215+
// Show loading indicator at the end if hasMore
216+
if (index >= headlines.length) {
217+
// Ensure loading indicator is visible
218+
return const Padding(
219+
padding: EdgeInsets.all(AppSpacing.paddingLarge),
220+
child: Center(child: CircularProgressIndicator()),
221+
);
222+
}
223+
// Display headline item
224+
return HeadlineItemWidget(headline: headlines[index]);
225+
},
226+
),
221227
// Default case (should ideally not be reached if states are handled)
222228
_ => const SizedBox.shrink(),
223229
};

lib/router/router.dart

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
66
import 'package:go_router/go_router.dart';
77
import 'package:ht_main/account/view/account_page.dart';
88
import 'package:ht_main/app/bloc/app_bloc.dart';
9-
import 'package:ht_main/app/view/app_shell.dart'; // Import the AppShell
9+
import 'package:ht_main/app/view/app_shell.dart';
1010
import 'package:ht_main/authentication/view/authentication_page.dart';
1111
import 'package:ht_main/authentication/view/email_link_sent_page.dart';
1212
import 'package:ht_main/authentication/view/email_sign_in_page.dart';
@@ -15,7 +15,7 @@ import 'package:ht_main/headlines-feed/view/headlines_feed_page.dart';
1515
import 'package:ht_main/headlines-search/view/headlines_search_page.dart';
1616
import 'package:ht_main/l10n/l10n.dart';
1717
import 'package:ht_main/router/routes.dart';
18-
import 'package:ht_main/splash/view/splash_page.dart'; // Import SplashPage
18+
import 'package:ht_main/splash/view/splash_page.dart';
1919

2020
/// Creates and configures the GoRouter instance for the application.
2121
///
@@ -96,16 +96,17 @@ GoRouter createRouter({required ValueNotifier<AppStatus> authStatusNotifier}) {
9696
print(' Action: Redirecting to $authenticationPath');
9797
return authenticationPath;
9898
} else if (appStatus == AppStatus.authenticated ||
99-
appStatus == AppStatus.anonymous) {
99+
appStatus == AppStatus.anonymous) {
100100
print(' Action: Redirecting to $feedPath');
101101
return feedPath;
102102
}
103103
// Fallback: Should not happen if status is known, but stay on splash if needed.
104-
print(' Action: Unknown status after initial, staying on splash (fallback).');
104+
print(
105+
' Action: Unknown status after initial, staying on splash (fallback).',
106+
);
105107
return null;
106108
}
107109

108-
109110
// --- Case 1: Unauthenticated User (After Initial Load) ---
110111
// If the user is unauthenticated and NOT on the splash screen...
111112
if (appStatus == AppStatus.unauthenticated) {
@@ -132,7 +133,6 @@ GoRouter createRouter({required ValueNotifier<AppStatus> authStatusNotifier}) {
132133
final isGoingToSearch = currentLocation.startsWith(searchPath);
133134
final isGoingToAccount = currentLocation.startsWith(accountPath);
134135

135-
136136
// **Sub-Case 2.1: Navigating to the BASE Authentication Path (`/authentication`)**
137137
if (isGoingToBaseAuthPath) {
138138
// Allow access ONLY if they are explicitly starting the linking flow
@@ -163,7 +163,8 @@ GoRouter createRouter({required ValueNotifier<AppStatus> authStatusNotifier}) {
163163
}
164164
// **Sub-Case 2.3: Navigating Within the Main App Sections (Feed, Search, Account)**
165165
// Allow anonymous users to access the main content sections and their sub-routes.
166-
else if (isGoingToFeed || isGoingToSearch || isGoingToAccount) { // Added checks for search and account
166+
else if (isGoingToFeed || isGoingToSearch || isGoingToAccount) {
167+
// Added checks for search and account
167168
print(
168169
' Action: Allowing navigation within main app section ($currentLocation).', // Updated log message
169170
);
@@ -200,10 +201,10 @@ GoRouter createRouter({required ValueNotifier<AppStatus> authStatusNotifier}) {
200201
// This case is less likely now with explicit initial handling.
201202
// If somehow the status is unknown after the initial phase, allow navigation.
202203
else {
203-
print(
204-
' Redirect Decision: AppStatus is UNEXPECTED ($appStatus). Allowing navigation (fallback).',
205-
);
206-
return null; // Allow access as a safe default
204+
print(
205+
' Redirect Decision: AppStatus is UNEXPECTED ($appStatus). Allowing navigation (fallback).',
206+
);
207+
return null; // Allow access as a safe default
207208
}
208209

209210
// --- Default: No Redirect (Should not be reached if logic is exhaustive) ---

lib/splash/view/splash_page.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,26 @@ class SplashPage extends StatelessWidget {
1616
body: Center(
1717
child: Padding(
1818
// Add horizontal padding for content safety
19-
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.lg), // Corrected constant
19+
padding: const EdgeInsets.symmetric(
20+
horizontal: AppSpacing.lg,
21+
), // Corrected constant
2022
child: Column(
2123
mainAxisAlignment: MainAxisAlignment.center,
2224
children: [
2325
// Icon representing news/articles
2426
Icon(
2527
Icons.article_outlined,
26-
size: 64.0,
28+
size: 64,
2729
color: colorScheme.primary, // Use primary theme color
2830
),
2931
const SizedBox(height: AppSpacing.xl), // Use defined spacing
30-
3132
// App Title
3233
Text(
3334
'Headlines Toolkit', // App Name
3435
style: textTheme.headlineMedium, // Use theme text style
3536
textAlign: TextAlign.center,
3637
),
3738
const SizedBox(height: AppSpacing.md), // Use defined spacing
38-
3939
// Subheadline/Tagline
4040
Text(
4141
'Develop News Headlines Apps Rapidly & Reliably.', // Tagline

0 commit comments

Comments
 (0)