Skip to content

Commit 90c419f

Browse files
committed
MainScreen の状態管理を改善し、WebView からの問題 ID の取得と処理を強化
1 parent 68efdc3 commit 90c419f

File tree

1 file changed

+56
-68
lines changed

1 file changed

+56
-68
lines changed

lib/main.dart

Lines changed: 56 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ void main() async {
3434
child: const MyApp(),
3535
),
3636
);
37+
developer.log('App started successfully');
3738
}
3839

3940
// デフォルトのカラースキーム
@@ -149,104 +150,89 @@ class MainScreen extends StatefulWidget {
149150

150151
class _MainScreenState extends State<MainScreen> {
151152
int _selectedIndex = 0;
152-
String _currentProblemId = 'default_problem'; // Keep this for EditorScreen
153+
String _currentProblemId = 'default_problem'; // For EditorScreen
154+
String? _problemIdFromWebView; // State variable to hold ID from WebView click
153155

154-
// This callback is for ProblemDetailScreen -> EditorScreen update
156+
// Callback for ProblemDetailScreen -> EditorScreen update
155157
void _updateProblemIdForEditor(String newProblemUrl) {
156-
// Extract problemId from URL if needed, or adjust Problem model/service
157-
// Assuming AtCoderService returns a Problem object with an id field like 'abc388_a'
158-
// Or modify ProblemDetailScreen's onProblemChanged to pass the id directly
159158
final uri = Uri.parse(newProblemUrl);
160159
if (uri.host == 'atcoder.jp' && uri.pathSegments.length == 4 &&
161160
uri.pathSegments[0] == 'contests' && uri.pathSegments[2] == 'tasks') {
162161
final problemId = uri.pathSegments[3]; // e.g., abc388_a
163-
setState(() {
164-
_currentProblemId = problemId;
165-
});
162+
// Check if mounted before calling setState
163+
if (mounted) {
164+
setState(() {
165+
_currentProblemId = problemId;
166+
});
167+
}
166168
developer.log('Editor Problem ID updated via ProblemDetailScreen: $_currentProblemId', name: 'MainScreen');
167169
} else {
168170
developer.log('Could not extract problem ID from URL: $newProblemUrl', name: 'MainScreen');
169-
// Handle cases where URL might not be a standard problem URL if necessary
170-
// Maybe set _currentProblemId = 'default_problem' or some error state
171171
}
172172
}
173173

174-
// This function handles navigation from HomeScreen (WebView)
175-
void navigateToProblemTabWithId(String problemId) {
176-
developer.log('navigateToProblemTabWithId called with problemId: $problemId', name: 'MainScreen');
177-
setState(() {
178-
_selectedIndex = 1; // Switch to Problems tab
179-
// We don't directly set _currentProblemId here for ProblemDetailScreen,
180-
// instead, we pass it down. We update _currentProblemId via _updateProblemIdForEditor
181-
// when ProblemDetailScreen successfully fetches.
182-
});
183-
// Trigger update in ProblemsScreen/ProblemDetailScreen by passing the new ID
184-
// This requires ProblemsScreen to handle the ID change.
185-
// Let's modify _buildScreens to pass the ID intended for ProblemDetailScreen.
174+
// Handles navigation from HomeScreen (WebView) - Now a class method
175+
void _navigateToProblemTabWithId(String problemId) {
176+
developer.log('_navigateToProblemTabWithId called with problemId: $problemId', name: 'MainScreen');
177+
// Check if mounted before calling setState
178+
if (mounted) {
179+
setState(() {
180+
_selectedIndex = 1; // Switch to Problems tab
181+
_problemIdFromWebView = problemId; // Store the ID in the state variable
182+
});
183+
}
186184
}
187185

186+
// Builds the list of screens - Now a class method
187+
List<Widget> _buildScreens() {
188+
String? idToPass = _problemIdFromWebView;
189+
developer.log('_buildScreens: Passing problemIdToLoad=$idToPass', name: 'MainScreen');
190+
191+
// Reset the ID after using it in this build cycle.
192+
// Use addPostFrameCallback to schedule the reset after the build.
193+
if (_problemIdFromWebView != null) {
194+
WidgetsBinding.instance.addPostFrameCallback((_) {
195+
// Check if still mounted and if the ID hasn't been changed again by another event
196+
if (mounted && _problemIdFromWebView == idToPass) {
197+
setState(() {
198+
_problemIdFromWebView = null;
199+
developer.log('Reset _problemIdFromWebView in post frame callback', name: 'MainScreen');
200+
});
201+
}
202+
});
203+
}
188204

189-
List<Widget> _buildScreens(String problemIdToLoad) { // Accept problemId
190205
return [
191-
HomeScreen(navigateToProblem: navigateToProblemTabWithId), // Pass the correct function
192-
// Pass the problemId from WebView and the callback for manual fetch
206+
HomeScreen(navigateToProblem: _navigateToProblemTabWithId), // Pass the class method
193207
ProblemsScreen(
194-
problemIdToLoad: problemIdToLoad, // Pass the ID from WebView click
195-
onProblemChanged: _updateProblemIdForEditor // For manual fetch update
208+
problemIdToLoad: idToPass, // Pass the ID from state
209+
onProblemChanged: _updateProblemIdForEditor
196210
),
197211
EditorScreen(
198212
key: ValueKey(_currentProblemId),
199-
problemId: _currentProblemId, // Editor uses the ID updated by onProblemChanged
213+
problemId: _currentProblemId,
200214
),
201215
const SettingsScreen(),
202216
];
203217
}
204218

205219
void _onItemTapped(int index) {
206-
setState(() {
207-
_selectedIndex = index;
208-
});
209-
}
210-
211-
@override
212-
Widget build(BuildContext context) {
213-
// Determine the problemId to load based on current state or navigation trigger
214-
// This logic needs refinement. How do we pass the ID from navigateToProblemTabWithId
215-
// into the build method cleanly? Using a state variable specifically for this might work.
216-
217-
// Let's introduce a state variable for the ID triggered by WebView
218-
String? _problemIdFromWebView;
219-
220-
// Modify navigateToProblemTabWithId to update this state variable
221-
void navigateToProblemTabWithId(String problemId) {
222-
developer.log('navigateToProblemTabWithId called with problemId: $problemId', name: 'MainScreen');
220+
// Check if mounted before calling setState
221+
if (mounted) {
223222
setState(() {
224-
_selectedIndex = 1; // Switch to Problems tab
225-
_problemIdFromWebView = problemId; // Store the ID to pass down
223+
_selectedIndex = index;
224+
// Optional: Clear the pending problem ID if user manually switches tabs
225+
// if (_problemIdFromWebView != null) {
226+
// _problemIdFromWebView = null;
227+
// developer.log('Reset _problemIdFromWebView due to manual tab switch', name: 'MainScreen');
228+
// }
226229
});
227230
}
231+
}
228232

229-
// Rebuild _buildScreens to use the state variable
230-
List<Widget> _buildScreens() {
231-
String? idToPass = _problemIdFromWebView;
232-
_problemIdFromWebView = null; // Reset after passing down once
233-
234-
return [
235-
HomeScreen(navigateToProblem: navigateToProblemTabWithId),
236-
ProblemsScreen(
237-
// Pass the ID only if it came from WebView this build cycle
238-
problemIdToLoad: idToPass,
239-
onProblemChanged: _updateProblemIdForEditor
240-
),
241-
EditorScreen(
242-
key: ValueKey(_currentProblemId),
243-
problemId: _currentProblemId,
244-
),
245-
const SettingsScreen(),
246-
];
247-
}
248-
249-
233+
@override
234+
Widget build(BuildContext context) {
235+
// Now _buildScreens is a class method and uses the state variable _problemIdFromWebView
250236
final screens = _buildScreens();
251237

252238
return Scaffold(
@@ -353,6 +339,8 @@ class ProblemsScreen extends StatelessWidget {
353339

354340
@override
355341
Widget build(BuildContext context) {
342+
// Add log to see the value being passed down
343+
developer.log('ProblemsScreen build: problemIdToLoad=$problemIdToLoad', name: 'ProblemsScreen');
356344
// Pass both the ID to load and the callback
357345
return ProblemDetailScreen(
358346
problemIdToLoad: problemIdToLoad, // Pass the ID down

0 commit comments

Comments
 (0)