This commit is contained in:
Dmitry 2025-11-21 03:38:20 +03:00
commit 43ce663b0b
21 changed files with 63 additions and 91 deletions

View file

@ -1,15 +1,14 @@
{ {
"component": "web_v2", "component": "web_v2",
"current_task_id": null, "current_task_id": "WEB-00",
"iteration_count": 0, "iteration_count": 1,
"max_iterations": 10, "max_iterations": 10,
"started_at": null, "started_at": "2025-11-21T00:31:28.302997+00:00",
"last_commit": null, "last_commit": null,
"retry_count": 0, "retry_count": 0,
"max_retries": 3, "max_retries": 3,
"status": "idle", "status": "in_progress",
"errors": [], "errors": [],
"completed_tasks": [], "completed_tasks": [],
"skipped_tasks": [] "skipped_tasks": []
} }

View file

@ -9,7 +9,7 @@
"id": "WEB-00", "id": "WEB-00",
"title": "Fix linter errors", "title": "Fix linter errors",
"priority": "high", "priority": "high",
"status": "pending", "status": "in_progress",
"estimated_hours": 3.0, "estimated_hours": 3.0,
"description": "Fix linter errors in the project", "description": "Fix linter errors in the project",
"acceptance_criteria": [ "acceptance_criteria": [
@ -62,7 +62,9 @@
"Button is properly styled and positioned", "Button is properly styled and positioned",
"5+ widget tests pass covering button integration" "5+ widget tests pass covering button integration"
], ],
"dependencies": ["WEB-001"], "dependencies": [
"WEB-001"
],
"files_to_modify": [ "files_to_modify": [
"mnemo_cards_web_v2/lib/presentation/pages/pack_details/pack_details_page.dart", "mnemo_cards_web_v2/lib/presentation/pages/pack_details/pack_details_page.dart",
"mnemo_cards_web_v2/lib/presentation/pages/purchase/purchase_page.dart", "mnemo_cards_web_v2/lib/presentation/pages/purchase/purchase_page.dart",
@ -109,7 +111,9 @@
"Loading states and error handling are implemented", "Loading states and error handling are implemented",
"10+ widget tests pass covering all UI interactions" "10+ widget tests pass covering all UI interactions"
], ],
"dependencies": ["backend:API-007"], "dependencies": [
"backend:API-007"
],
"files_to_modify": [ "files_to_modify": [
"mnemo_cards_web_v2/lib/presentation/pages/subscription/subscription_page.dart", "mnemo_cards_web_v2/lib/presentation/pages/subscription/subscription_page.dart",
"mnemo_cards_web_v2/lib/presentation/router/app_router.dart", "mnemo_cards_web_v2/lib/presentation/router/app_router.dart",
@ -131,7 +135,9 @@
"Status updates when subscription changes", "Status updates when subscription changes",
"3+ widget tests pass covering status display" "3+ widget tests pass covering status display"
], ],
"dependencies": ["WEB-004"], "dependencies": [
"WEB-004"
],
"files_to_modify": [ "files_to_modify": [
"mnemo_cards_web_v2/lib/presentation/pages/profile/profile_page.dart", "mnemo_cards_web_v2/lib/presentation/pages/profile/profile_page.dart",
"mnemo_cards_web_v2/test/presentation/pages/profile/profile_page_test.dart" "mnemo_cards_web_v2/test/presentation/pages/profile/profile_page_test.dart"
@ -227,7 +233,9 @@
"Error handling is tested for all edge cases", "Error handling is tested for all edge cases",
"All tests pass with zero flaky tests" "All tests pass with zero flaky tests"
], ],
"dependencies": ["WEB-003"], "dependencies": [
"WEB-003"
],
"files_to_modify": [ "files_to_modify": [
"mnemo_cards_web_v2/test/domain/services/purchases_service_test.dart", "mnemo_cards_web_v2/test/domain/services/purchases_service_test.dart",
"mnemo_cards_web_v2/test/domain/state/purchase_state_manager_test.dart", "mnemo_cards_web_v2/test/domain/state/purchase_state_manager_test.dart",
@ -258,4 +266,4 @@
"component": "web_v2" "component": "web_v2"
} }
] ]
} }

View file

@ -35,13 +35,13 @@ class AppScopeContainer extends ScopeContainer
init: (_) async { init: (_) async {
_firebaseApp = await Firebase.initializeApp( _firebaseApp = await Firebase.initializeApp(
options: const FirebaseOptions( options: const FirebaseOptions(
apiKey: "AIzaSyCq0V8JebjtqSgGSueouoLiprBROgPRBQw", apiKey: 'AIzaSyCq0V8JebjtqSgGSueouoLiprBROgPRBQw',
authDomain: "mnemo-cards.firebaseapp.com", authDomain: 'mnemo-cards.firebaseapp.com',
projectId: "mnemo-cards", projectId: 'mnemo-cards',
storageBucket: "mnemo-cards.appspot.com", storageBucket: 'mnemo-cards.appspot.com',
messagingSenderId: "701767851968", messagingSenderId: '701767851968',
appId: "1:701767851968:web:714eb4fb5e3fd1ab2f7225", appId: '1:701767851968:web:714eb4fb5e3fd1ab2f7225',
measurementId: "G-C37MMWS6WC" measurementId: 'G-C37MMWS6WC'
) )
); );
}, },

View file

@ -1,6 +1,5 @@
import 'package:yx_scope/yx_scope.dart'; import 'package:yx_scope/yx_scope.dart';
import '../../../domain/services/http_repository_v2.dart';
import '../../../domain/services/statistics_service.dart'; import '../../../domain/services/statistics_service.dart';
import '../../../domain/state/statistics_state_manager.dart'; import '../../../domain/state/statistics_state_manager.dart';
import '../user_scope_container.dart'; import '../user_scope_container.dart';

View file

@ -255,7 +255,7 @@ class ApiConfigV2 {
/// Build Telegram bot deep link with payload /// Build Telegram bot deep link with payload
static String telegramBotDeepLink(String payload) { static String telegramBotDeepLink(String payload) {
return '${telegramBotDeepLinkBase}?start=$payload'; return '$telegramBotDeepLinkBase?start=$payload';
} }
// ==================== Chat Endpoints ==================== // ==================== Chat Endpoints ====================

View file

@ -1,8 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:developer'; import 'dart:developer';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import '../models/game_question.dart'; import '../models/game_question.dart';
/// Manages active game session state and user interactions /// Manages active game session state and user interactions

View file

@ -1522,7 +1522,7 @@ class HttpRepositoryV2 {
/// Delete chat session /// Delete chat session
Future<void> deleteChatSession(String sessionId) async { Future<void> deleteChatSession(String sessionId) async {
try { try {
await _dio.delete(ApiConfigV2.chatSessionDelete(sessionId)); await _dio.delete<void>(ApiConfigV2.chatSessionDelete(sessionId));
} on DioException catch (e) { } on DioException catch (e) {
if (e.error is ApiException) { if (e.error is ApiException) {
rethrow; rethrow;
@ -1555,7 +1555,7 @@ class HttpRepositoryV2 {
if (offset != null) queryParams['offset'] = offset.toString(); if (offset != null) queryParams['offset'] = offset.toString();
final queryString = ApiConfigV2.buildQuery(queryParams); final queryString = ApiConfigV2.buildQuery(queryParams);
final response = await _dio.get('${ApiConfigV2.tasks}$queryString'); final response = await _dio.get<List<dynamic>>('${ApiConfigV2.tasks}$queryString');
final data = response.data as List<dynamic>; final data = response.data as List<dynamic>;
return data.map((item) => Task.fromJson(item as Map<String, dynamic>)).toList(); return data.map((item) => Task.fromJson(item as Map<String, dynamic>)).toList();
@ -1573,7 +1573,7 @@ class HttpRepositoryV2 {
/// Get specific task by ID /// Get specific task by ID
Future<Task> getTask(String taskId) async { Future<Task> getTask(String taskId) async {
try { try {
final response = await _dio.get(ApiConfigV2.taskById(taskId)); final response = await _dio.get<Map<String, dynamic>>(ApiConfigV2.taskById(taskId));
return Task.fromJson(response.data as Map<String, dynamic>); return Task.fromJson(response.data as Map<String, dynamic>);
} on DioException catch (e) { } on DioException catch (e) {
if (e.error is ApiException) { if (e.error is ApiException) {
@ -1589,7 +1589,7 @@ class HttpRepositoryV2 {
/// Start a task (mark as in progress) /// Start a task (mark as in progress)
Future<Task> startTask(String taskId) async { Future<Task> startTask(String taskId) async {
try { try {
final response = await _dio.post(ApiConfigV2.taskStart(taskId)); final response = await _dio.post<Map<String, dynamic>>(ApiConfigV2.taskStart(taskId));
return Task.fromJson(response.data as Map<String, dynamic>); return Task.fromJson(response.data as Map<String, dynamic>);
} on DioException catch (e) { } on DioException catch (e) {
if (e.error is ApiException) { if (e.error is ApiException) {
@ -1613,7 +1613,7 @@ class HttpRepositoryV2 {
if (proofUrl != null) body['proofUrl'] = proofUrl; if (proofUrl != null) body['proofUrl'] = proofUrl;
if (notes != null) body['notes'] = notes; if (notes != null) body['notes'] = notes;
final response = await _dio.post( final response = await _dio.post<Map<String, dynamic>>(
ApiConfigV2.taskComplete(taskId), ApiConfigV2.taskComplete(taskId),
data: body, data: body,
); );
@ -1632,7 +1632,7 @@ class HttpRepositoryV2 {
/// Get user's task progress and statistics /// Get user's task progress and statistics
Future<TaskProgress> getUserTaskProgress() async { Future<TaskProgress> getUserTaskProgress() async {
try { try {
final response = await _dio.get(ApiConfigV2.usersMeTasksProgress); final response = await _dio.get<Map<String, dynamic>>(ApiConfigV2.usersMeTasksProgress);
return TaskProgress.fromJson(response.data as Map<String, dynamic>); return TaskProgress.fromJson(response.data as Map<String, dynamic>);
} on DioException catch (e) { } on DioException catch (e) {
if (e.error is ApiException) { if (e.error is ApiException) {
@ -1648,7 +1648,7 @@ class HttpRepositoryV2 {
/// Get task categories and available filters /// Get task categories and available filters
Future<TaskCategories> getTaskCategories() async { Future<TaskCategories> getTaskCategories() async {
try { try {
final response = await _dio.get(ApiConfigV2.tasksCategories); final response = await _dio.get<Map<String, dynamic>>(ApiConfigV2.tasksCategories);
return TaskCategories.fromJson(response.data as Map<String, dynamic>); return TaskCategories.fromJson(response.data as Map<String, dynamic>);
} on DioException catch (e) { } on DioException catch (e) {
if (e.error is ApiException) { if (e.error is ApiException) {

View file

@ -35,7 +35,7 @@ class ImageCacheService {
} }
/// Decode base64 string and cache with automatic key generation /// Decode base64 string and cache with automatic key generation
/// Key format: 'pack_<packId>' /// Key format: 'pack_`packId`'
MemoryImage? putPackImage(String packId, String base64String) { MemoryImage? putPackImage(String packId, String base64String) {
return putBase64('pack_$packId', base64String); return putBase64('pack_$packId', base64String);
} }

View file

@ -62,7 +62,7 @@ class StatisticsService {
/// Legacy method for backward compatibility - returns basic statistics /// Legacy method for backward compatibility - returns basic statistics
/// TODO: Remove when all components migrate to new detailed statistics /// TODO: Remove when all components migrate to new detailed statistics
@deprecated @Deprecated('Use getDetailedStatistics instead')
UserStatistics getStatistics(UserDto user) { UserStatistics getStatistics(UserDto user) {
final learnedWords = _calculateLearnedWords(user); final learnedWords = _calculateLearnedWords(user);
final testsCompleted = _calculateTestsCompleted(user); final testsCompleted = _calculateTestsCompleted(user);

View file

@ -187,12 +187,6 @@ class TasksRepository {
} }
} }
/// Update user progress
Future<void> _updateUserProgress(String taskId, TaskStatus status) async {
// TODO: Implement actual progress update
log('Updated user progress: $taskId -> $status', name: 'TasksRepository');
}
// ==================== Caching Methods ==================== // ==================== Caching Methods ====================
/// Cache tasks locally /// Cache tasks locally
@ -223,17 +217,6 @@ class TasksRepository {
} }
} }
/// Cache user progress
Future<void> _cacheUserProgress(TaskProgress progress) async {
try {
final progressJson = jsonEncode(progress.toJson());
await _prefs.setString(_userProgressKey, progressJson);
log('Cached user progress for ${progress.userId}', name: 'TasksRepository');
} catch (e) {
log('Error caching user progress', error: e, name: 'TasksRepository');
}
}
/// Get cached user progress /// Get cached user progress
Future<TaskProgress?> _getCachedUserProgress(String userId) async { Future<TaskProgress?> _getCachedUserProgress(String userId) async {
try { try {
@ -262,8 +245,8 @@ class TasksRepository {
return [ return [
Task( Task(
id: 'task_1', id: 'task_1',
title: 'Пройди 3 теста сегодня', title: '?????? 3 ????? ???????',
description: 'Выполни 3 теста по любым темам в приложении', description: '??????? 3 ????? ?? ????? ????? ? ??????????',
type: TaskType.appInternal, type: TaskType.appInternal,
difficulty: TaskDifficulty.easy, difficulty: TaskDifficulty.easy,
rewards: [ rewards: [
@ -277,46 +260,46 @@ class TasksRepository {
), ),
Task( Task(
id: 'task_2', id: 'task_2',
title: 'Подпишись на канал в Telegram', title: '????????? ?? ????? ? Telegram',
description: 'Подпишись на наш канал @mnemo_cards и пришли скриншот подписки', description: '????????? ?? ??? ????? @mnemo_cards ? ?????? ???????? ????????',
type: TaskType.social, type: TaskType.social,
difficulty: TaskDifficulty.easy, difficulty: TaskDifficulty.easy,
rewards: [ rewards: [
TaskReward(type: RewardType.xp, amount: 25), const TaskReward(type: RewardType.xp, amount: 25),
TaskReward(type: RewardType.coins, amount: 5), const TaskReward(type: RewardType.coins, amount: 5),
], ],
status: TaskStatus.available, status: TaskStatus.available,
createdAt: now.subtract(const Duration(days: 2)), createdAt: now.subtract(const Duration(days: 2)),
expiresAt: now.add(const Duration(days: 14)), expiresAt: now.add(const Duration(days: 14)),
instructions: 'Сделай скриншот страницы подписки и загрузи его как доказательство', instructions: '?????? ???????? ???????? ???????? ? ??????? ??? ??? ??????????????',
tags: ['telegram', 'social'], tags: ['telegram', 'social'],
), ),
Task( Task(
id: 'task_3', id: 'task_3',
title: 'Закажи еду на испанском', title: '?????? ??? ?? ?????????',
description: 'Сделай заказ в ресторане или кафе, используя испанский язык, и запиши это на видео', description: '?????? ????? ? ????????? ??? ????, ????????? ????????? ????, ? ?????? ??? ?? ?????',
type: TaskType.external, type: TaskType.external,
difficulty: TaskDifficulty.hard, difficulty: TaskDifficulty.hard,
rewards: [ rewards: [
TaskReward(type: RewardType.xp, amount: 200), const TaskReward(type: RewardType.xp, amount: 200),
TaskReward(type: RewardType.coins, amount: 50), const TaskReward(type: RewardType.coins, amount: 50),
TaskReward(type: RewardType.achievement, amount: 1, achievementId: 'real_world_speaker'), const TaskReward(type: RewardType.achievement, amount: 1, achievementId: 'real_world_speaker'),
], ],
status: TaskStatus.available, status: TaskStatus.available,
createdAt: now.subtract(const Duration(days: 3)), createdAt: now.subtract(const Duration(days: 3)),
expiresAt: now.add(const Duration(days: 30)), expiresAt: now.add(const Duration(days: 30)),
instructions: 'Запиши видео разговора на испанском языке и загрузи его', instructions: '?????? ????? ????????? ?? ????????? ????? ? ??????? ???',
tags: ['spanish', 'speaking', 'real_world'], tags: ['spanish', 'speaking', 'real_world'],
), ),
Task( Task(
id: 'task_4', id: 'task_4',
title: 'Изучи 10 новых слов', title: '????? 10 ????? ????',
description: 'Добавь в свой словарь и изучи 10 новых слов', description: '?????? ? ???? ??????? ? ????? 10 ????? ????',
type: TaskType.appInternal, type: TaskType.appInternal,
difficulty: TaskDifficulty.medium, difficulty: TaskDifficulty.medium,
rewards: [ rewards: [
TaskReward(type: RewardType.xp, amount: 75), const TaskReward(type: RewardType.xp, amount: 75),
TaskReward(type: RewardType.coins, amount: 15), const TaskReward(type: RewardType.coins, amount: 15),
], ],
status: TaskStatus.inProgress, status: TaskStatus.inProgress,
createdAt: now.subtract(const Duration(days: 1)), createdAt: now.subtract(const Duration(days: 1)),

View file

@ -245,12 +245,12 @@ class StatisticsStateManager extends StateManager<StatisticsState> {
/// Get completed packs count /// Get completed packs count
int get completedPacksCount { int get completedPacksCount {
return state.packsStats.where((pack) => (pack.progress ?? 0.0) >= 1.0).length; return state.packsStats.where((pack) => pack.progress >= 1.0).length;
} }
/// Get in progress packs count /// Get in progress packs count
int get inProgressPacksCount { int get inProgressPacksCount {
return state.packsStats.where((pack) => (pack.progress ?? 0.0) > 0.0 && (pack.progress ?? 0.0) < 1.0).length; return state.packsStats.where((pack) => pack.progress > 0.0 && pack.progress < 1.0).length;
} }
/// Get unlocked achievements count /// Get unlocked achievements count

View file

@ -60,7 +60,6 @@ class TestsStateManager extends StateManager<TestsState> {
final GameSoundService _gameSoundService; final GameSoundService _gameSoundService;
String? _currentPackId; String? _currentPackId;
TestDto? _currentTest; TestDto? _currentTest;
List<GameQuestion>? _currentQuestions;
/// Load tests for a pack /// Load tests for a pack
Future<void> loadPackTests(String packId) => handle((emit) async { Future<void> loadPackTests(String packId) => handle((emit) async {
@ -111,7 +110,6 @@ class TestsStateManager extends StateManager<TestsState> {
// Convert TestDto questions to GameQuestion format // Convert TestDto questions to GameQuestion format
final questions = _convertTestToGameQuestions(test); final questions = _convertTestToGameQuestions(test);
_currentQuestions = questions;
// Prepare game session // Prepare game session
emit(TestsState.gameSessionPreparing( emit(TestsState.gameSessionPreparing(
@ -177,13 +175,13 @@ class TestsStateManager extends StateManager<TestsState> {
// Auto-advance after delay if correct, or allow manual navigation // Auto-advance after delay if correct, or allow manual navigation
if (isCorrect) { if (isCorrect) {
await Future<void>.delayed(const Duration(milliseconds: 1500)); await Future<void>.delayed(const Duration(milliseconds: 1500));
await _nextQuestion(emit); await _nextQuestion.call(emit);
} }
}); });
/// Move to next question /// Move to next question
Future<void> nextQuestion() => handle((emit) async { Future<void> nextQuestion() => handle((emit) async {
await _nextQuestion(emit); await _nextQuestion.call(emit);
}); });
/// Move to previous question /// Move to previous question
@ -240,7 +238,6 @@ class TestsStateManager extends StateManager<TestsState> {
log('Resetting game session', name: 'TestsStateManager'); log('Resetting game session', name: 'TestsStateManager');
_gameSessionManager.reset(); _gameSessionManager.reset();
_currentTest = null; _currentTest = null;
_currentQuestions = null;
emit(const TestsState.loading()); emit(const TestsState.loading());
}); });
@ -314,7 +311,7 @@ class TestsStateManager extends StateManager<TestsState> {
audio: question.audio, audio: question.audio,
options: options, options: options,
correctAnswer: correctAnswer, correctAnswer: correctAnswer,
word: question.word ?? '', word: question.word,
), ),
)); ));
} else if (question is InputButtonsTestQuestionBody) { } else if (question is InputButtonsTestQuestionBody) {

View file

@ -207,7 +207,9 @@ class _AuthPageState extends State<AuthPage> {
// Copy code to clipboard for convenience // Copy code to clipboard for convenience
await Clipboard.setData(ClipboardData(text: status.code)); await Clipboard.setData(ClipboardData(text: status.code));
_startCodePolling(context, status.code); if (mounted) {
_startCodePolling(context, status.code);
}
} catch (e, s) { } catch (e, s) {
log( log(
'Error generating Telegram code', 'Error generating Telegram code',
@ -270,7 +272,7 @@ class _AuthPageState extends State<AuthPage> {
} }
} else if (status.isConsumed) { } else if (status.isConsumed) {
_stopCodePolling(); _stopCodePolling();
} else if (status.isReadyForLogin && !_autoLoginAttempted) { } else if (status.isReadyForLogin && !_autoLoginAttempted && mounted) {
_autoLoginAttempted = true; _autoLoginAttempted = true;
await _loginWithTelegram(context); await _loginWithTelegram(context);
} }
@ -476,7 +478,7 @@ class _AuthPageState extends State<AuthPage> {
// Use the Adsgram SDK to show ad with specific block ID // Use the Adsgram SDK to show ad with specific block ID
await Adsgram.instance.showAdWithBlockId(id.toString()); await Adsgram.instance.showAdWithBlockId(id.toString());
} catch (e) { } catch (e) {
print('Failed to show ad: $e'); log('Failed to show ad: $e', name: 'AuthPage');
// Fallback: show a simple alert // Fallback: show a simple alert
if (mounted) { if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(

View file

@ -14,8 +14,6 @@ import '../../../domain/state/tests_state_manager.dart';
import '../../../presentation/widgets/error_view.dart'; import '../../../presentation/widgets/error_view.dart';
import '../../../presentation/widgets/game/answer_options.dart'; import '../../../presentation/widgets/game/answer_options.dart';
import '../../../presentation/widgets/game/input_letters_widget.dart'; import '../../../presentation/widgets/game/input_letters_widget.dart';
import '../../../presentation/widgets/game/match_widget.dart';
import '../../../presentation/widgets/game/matrix_widget.dart';
import '../../../presentation/widgets/game/progress_indicator.dart'; import '../../../presentation/widgets/game/progress_indicator.dart';
import '../../../presentation/widgets/game/question_display.dart'; import '../../../presentation/widgets/game/question_display.dart';
import '../../../presentation/widgets/loading_view.dart'; import '../../../presentation/widgets/loading_view.dart';

View file

@ -39,8 +39,6 @@ class _TasksPageState extends State<TasksPage> with TickerProviderStateMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Задания'), title: const Text('Задания'),

View file

@ -3,7 +3,6 @@ import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../utils/adsgram_stub.dart'; import '../../utils/adsgram_stub.dart';
import 'package:go_router/go_router.dart';
import 'package:yx_scope_flutter/yx_scope_flutter.dart'; import 'package:yx_scope_flutter/yx_scope_flutter.dart';
import 'package:yx_state_flutter/yx_state_flutter.dart'; import 'package:yx_state_flutter/yx_state_flutter.dart';
@ -13,7 +12,6 @@ import '../../di/app_scope/app_scope_container.dart';
import '../../domain/config/api_config_v2.dart'; import '../../domain/config/api_config_v2.dart';
import '../../domain/models/ads_reward_offer.dart'; import '../../domain/models/ads_reward_offer.dart';
import '../../domain/state/ads_reward_state_manager.dart'; import '../../domain/state/ads_reward_state_manager.dart';
import '../../utils/color_extension.dart';
/// Button that allows users to unlock a pack by watching a rewarded ad. /// Button that allows users to unlock a pack by watching a rewarded ad.
/// ///

View file

@ -22,8 +22,6 @@ class AnswerOptions extends StatelessWidget {
final bool enabled; final bool enabled;
void _onAnswerSelected(BuildContext context, String option) { void _onAnswerSelected(BuildContext context, String option) {
// Play button tap sound
final appScope = context.findAncestorWidgetOfExactType<InheritedWidget>();
// Note: Sound service access would be implemented through proper DI injection // Note: Sound service access would be implemented through proper DI injection
// For now, we'll rely on the parent widget to handle sounds // For now, we'll rely on the parent widget to handle sounds

View file

@ -4,7 +4,6 @@ import 'package:yx_scope_flutter/yx_scope_flutter.dart';
import '../../../di/app_scope/app_scope_container.dart'; import '../../../di/app_scope/app_scope_container.dart';
import '../../../domain/models/game_question.dart'; import '../../../domain/models/game_question.dart';
import '../../../domain/state/tests_state_manager.dart';
/// Widget for input letters questions - user types letters to fill in blanks /// Widget for input letters questions - user types letters to fill in blanks
class InputLettersWidget extends StatefulWidget { class InputLettersWidget extends StatefulWidget {

View file

@ -4,7 +4,6 @@ import 'package:yx_scope_flutter/yx_scope_flutter.dart';
import '../../../di/app_scope/app_scope_container.dart'; import '../../../di/app_scope/app_scope_container.dart';
import '../../../domain/models/game_question.dart'; import '../../../domain/models/game_question.dart';
import '../../../domain/state/tests_state_manager.dart';
/// Widget for match questions - user connects items from two columns /// Widget for match questions - user connects items from two columns
class MatchWidget extends StatefulWidget { class MatchWidget extends StatefulWidget {

View file

@ -4,7 +4,6 @@ import 'package:yx_scope_flutter/yx_scope_flutter.dart';
import '../../../di/app_scope/app_scope_container.dart'; import '../../../di/app_scope/app_scope_container.dart';
import '../../../domain/models/game_question.dart'; import '../../../domain/models/game_question.dart';
import '../../../domain/state/tests_state_manager.dart';
/// Widget for matrix questions - user fills in a grid/table /// Widget for matrix questions - user fills in a grid/table
class MatrixWidget extends StatefulWidget { class MatrixWidget extends StatefulWidget {

View file

@ -24,7 +24,6 @@ class TaskCard extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final isCompleted = task.status == TaskStatus.completed; final isCompleted = task.status == TaskStatus.completed;
final isInProgress = task.status == TaskStatus.inProgress;
final isExpired = task.status == TaskStatus.expired; final isExpired = task.status == TaskStatus.expired;
return Semantics( return Semantics(
@ -155,8 +154,6 @@ class TaskCard extends StatelessWidget {
} }
Color _getIndicatorColor(BuildContext context) { Color _getIndicatorColor(BuildContext context) {
final theme = Theme.of(context);
switch (task.type) { switch (task.type) {
case TaskType.appInternal: case TaskType.appInternal:
return Colors.blue; return Colors.blue;