diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3285dbf --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.sourceDirectory": "/Users/prathmeshbhardwaj/Desktop/co/Internship Proj/Aarthi/flutter_app/linux" +} diff --git a/flutter_app/assets/quiz-logo-svg.svg b/flutter_app/assets/quiz-logo-svg.svg new file mode 100644 index 0000000..4071370 --- /dev/null +++ b/flutter_app/assets/quiz-logo-svg.svg @@ -0,0 +1,4 @@ + + + Q + diff --git a/flutter_app/ios/Flutter/Debug.xcconfig b/flutter_app/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/flutter_app/ios/Flutter/Debug.xcconfig +++ b/flutter_app/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/flutter_app/ios/Flutter/Release.xcconfig b/flutter_app/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/flutter_app/ios/Flutter/Release.xcconfig +++ b/flutter_app/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/flutter_app/ios/Podfile b/flutter_app/ios/Podfile new file mode 100644 index 0000000..d97f17e --- /dev/null +++ b/flutter_app/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/flutter_app/ios/Podfile.lock b/flutter_app/ios/Podfile.lock new file mode 100644 index 0000000..c043b1f --- /dev/null +++ b/flutter_app/ios/Podfile.lock @@ -0,0 +1,23 @@ +PODS: + - Flutter (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + +SPEC CHECKSUMS: + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + +PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 + +COCOAPODS: 1.15.2 diff --git a/flutter_app/ios/Runner.xcodeproj/project.pbxproj b/flutter_app/ios/Runner.xcodeproj/project.pbxproj index ece13bc..6635b08 100644 --- a/flutter_app/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter_app/ios/Runner.xcodeproj/project.pbxproj @@ -8,12 +8,14 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3233B25737E8617AA19013AC /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BAA74B0EB3B400DBFA862EA8 /* Pods_RunnerTests.framework */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B7FF437AB4CEFCB24AA86BE6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C25B06409AA530C36C1CBC64 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,6 +42,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0DBB39E45549F9015360685F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; @@ -48,6 +51,7 @@ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7E4B202BA030D4804562EAC9 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -55,6 +59,12 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B51F213103AFE7D2022882F1 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + BAA74B0EB3B400DBFA862EA8 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C25B06409AA530C36C1CBC64 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DA80B873FFC019E86572EFD3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + DAAE73E19F1FE5D4682DC72E /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + E76AA0378D1E8A0E8712B846 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,6 +72,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B7FF437AB4CEFCB24AA86BE6 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DF82A8C821B6CED516631A86 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3233B25737E8617AA19013AC /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -76,6 +95,15 @@ path = RunnerTests; sourceTree = ""; }; + 55CDBBA573D8ABA2FF561218 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C25B06409AA530C36C1CBC64 /* Pods_Runner.framework */, + BAA74B0EB3B400DBFA862EA8 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +122,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + B3C505BC59406911BAF0A808 /* Pods */, + 55CDBBA573D8ABA2FF561218 /* Frameworks */, ); sourceTree = ""; }; @@ -121,6 +151,20 @@ path = Runner; sourceTree = ""; }; + B3C505BC59406911BAF0A808 /* Pods */ = { + isa = PBXGroup; + children = ( + DA80B873FFC019E86572EFD3 /* Pods-Runner.debug.xcconfig */, + B51F213103AFE7D2022882F1 /* Pods-Runner.release.xcconfig */, + 0DBB39E45549F9015360685F /* Pods-Runner.profile.xcconfig */, + DAAE73E19F1FE5D4682DC72E /* Pods-RunnerTests.debug.xcconfig */, + 7E4B202BA030D4804562EAC9 /* Pods-RunnerTests.release.xcconfig */, + E76AA0378D1E8A0E8712B846 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -128,8 +172,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 0E1CAB483FAF50736765DA41 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + DF82A8C821B6CED516631A86 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +191,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + D3581CEC0E57FAF2B07840CC /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + E3CF59B9DAA58A4B8866145E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -222,6 +270,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0E1CAB483FAF50736765DA41 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +323,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + D3581CEC0E57FAF2B07840CC /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E3CF59B9DAA58A4B8866145E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -379,6 +488,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DAAE73E19F1FE5D4682DC72E /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +506,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7E4B202BA030D4804562EAC9 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +522,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E76AA0378D1E8A0E8712B846 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/flutter_app/ios/Runner.xcworkspace/contents.xcworkspacedata b/flutter_app/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/flutter_app/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/flutter_app/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/flutter_app/lib/main.dart b/flutter_app/lib/main.dart index 641a6f1..e01bf83 100644 --- a/flutter_app/lib/main.dart +++ b/flutter_app/lib/main.dart @@ -1,25 +1,58 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; -import 'dart:async'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:confetti/confetti.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'dart:async'; void main() { - runApp(QuizApp()); + runApp(ProviderScope(child: QuizApp())); } -class QuizApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return CupertinoApp( - title: 'Purple Quiz App', - theme: CupertinoThemeData( - primaryColor: CupertinoColors.systemPurple, - brightness: Brightness.light, +// Theme provider +final themeProvider = StateNotifierProvider((ref) => ThemeNotifier()); + +class ThemeNotifier extends StateNotifier { + ThemeNotifier() : super(_lightTheme); + + static final _lightTheme = ThemeData( + primarySwatch: Colors.purple, + brightness: Brightness.light, + scaffoldBackgroundColor: Colors.purple[50], + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.purple[700], + foregroundColor: Colors.white, + ), + ), + ); + + static final _darkTheme = ThemeData( + primarySwatch: Colors.purple, + brightness: Brightness.dark, + scaffoldBackgroundColor: Colors.grey[900], + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.purple[300], + foregroundColor: Colors.black, ), + ), + ); + + void toggleTheme() { + state = state.brightness == Brightness.light ? _darkTheme : _lightTheme; + } +} + +class QuizApp extends ConsumerWidget { + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themeProvider); + return MaterialApp( + title: 'Enhanced Quiz App', + theme: theme, home: HomeScreen(), ); } @@ -28,11 +61,19 @@ class QuizApp extends StatelessWidget { class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text('Purple Quiz'), + return Scaffold( + appBar: AppBar( + title: Text('Enhanced Quiz App'), + actions: [ + Consumer( + builder: (context, ref, _) => IconButton( + icon: Icon(Icons.brightness_6), + onPressed: () => ref.read(themeProvider.notifier).toggleTheme(), + ), + ), + ], ), - child: SafeArea( + body: SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -43,49 +84,34 @@ class HomeScreen extends StatelessWidget { ), SizedBox(height: 30), Text( - 'Welcome to Purple Quiz!', - style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: CupertinoColors.systemPurple), + 'Welcome to Enhanced Quiz!', + style: Theme.of(context).textTheme.headlineMedium, ), SizedBox(height: 20), Text( 'Test your knowledge and have fun!', - style: TextStyle(fontSize: 18, color: CupertinoColors.systemGrey), + style: Theme.of(context).textTheme.bodyLarge, ), SizedBox(height: 40), - CupertinoButton.filled( + ElevatedButton( child: Text('Start Quiz'), - onPressed: () { - Navigator.push( - context, - CupertinoPageRoute(builder: (context) => QuizScreen()), - ); - }, + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (context) => QuizScreen()), + ), ), SizedBox(height: 20), - CupertinoButton( + ElevatedButton( + child: Text('Create Quiz'), + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (context) => CreateQuizScreen()), + ), + ), + SizedBox(height: 20), + TextButton( child: Text('How to Play'), - onPressed: () { - showCupertinoModalPopup( - context: context, - builder: (BuildContext context) => CupertinoActionSheet( - title: Text('How to Play'), - message: Text( - '1. Answer questions within the time limit\n' - '2. Use hints if you need help\n' - '3. Score points for correct answers\n' - '4. Try to beat your high score!', - ), - actions: [ - CupertinoActionSheetAction( - child: Text('Got it!'), - onPressed: () { - Navigator.pop(context); - }, - ), - ], - ), - ); - }, + onPressed: () => _showHowToPlay(context), ), ], ), @@ -93,10 +119,32 @@ class HomeScreen extends StatelessWidget { ), ); } + + void _showHowToPlay(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: Text('How to Play'), + content: Text( + '1. Answer questions within the time limit\n' + '2. Use hints if you need help\n' + '3. Score points for correct answers\n' + '4. Try to beat your high score!\n' + '5. Create your own quizzes to challenge friends', + ), + actions: [ + TextButton( + child: Text('Got it!'), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ), + ); + } } class Question { - final int id; + final String id; final String text; final List options; final int answer; @@ -114,7 +162,7 @@ class Question { factory Question.fromJson(Map json) { return Question( - id: json['id'], + id: json['id'].toString(), text: json['text'], options: List.from(json['options']), answer: json['answer'], @@ -122,319 +170,299 @@ class Question { imageUrl: json['imageUrl'], ); } + + Map toJson() => { + 'id': id, + 'text': text, + 'options': options, + 'answer': answer, + 'hint': hint, + 'imageUrl': imageUrl, + }; } -class QuizScreen extends StatefulWidget { +// Quiz provider +final quizProvider = FutureProvider>((ref) async { + final response = await http.get(Uri.parse('http://localhost:8080/api/quiz')); + if (response.statusCode == 200) { + final data = json.decode(response.body); + return (data['questions'] as List).map((q) => Question.fromJson(q)).toList(); + } else { + throw Exception('Failed to load questions'); + } +}); + +class QuizScreen extends ConsumerStatefulWidget { + final List? questions; + + QuizScreen({this.questions}); + @override _QuizScreenState createState() => _QuizScreenState(); } -class _QuizScreenState extends State with SingleTickerProviderStateMixin { - List questions = []; +class _QuizScreenState extends ConsumerState with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _animation; int currentQuestion = 0; int score = 0; - bool isLoading = true; bool isHintVisible = false; - late AnimationController _animationController; - late Animation _animation; - Timer? _timer; - int _timeLeft = 30; late ConfettiController _confettiController; + int _timeLeft = 30; + Timer? _timer; @override void initState() { super.initState(); - fetchQuestions(); _animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 500), ); _animation = CurvedAnimation(parent: _animationController, curve: Curves.easeInOut); _confettiController = ConfettiController(duration: const Duration(seconds: 1)); + startTimer(); } @override void dispose() { _animationController.dispose(); - _timer?.cancel(); _confettiController.dispose(); + _timer?.cancel(); super.dispose(); } - Future fetchQuestions() async { - try { - final response = await http.get(Uri.parse('http://localhost:8080/api/quiz')); - if (response.statusCode == 200) { - final data = json.decode(response.body); + void startTimer() { + _timer?.cancel(); + setState(() { + _timeLeft = 30; + }); + _timer = Timer.periodic(Duration(seconds: 1), (timer) { + if (_timeLeft > 0) { setState(() { - questions = (data['questions'] as List) - .map((q) => Question.fromJson(q)) - .toList(); - isLoading = false; + _timeLeft--; }); - startTimer(); - _animationController.forward(); } else { - throw Exception('Failed to load questions. Status code: ${response.statusCode}'); + timer.cancel(); + _answerQuestion(false); } - } catch (e) { - setState(() { - isLoading = false; - }); - showErrorDialog('Error loading questions: $e'); - } + }); } - void showErrorDialog(String message) { - showCupertinoDialog( - context: context, - builder: (BuildContext context) => CupertinoAlertDialog( - title: Text('Error'), - content: Text(message), - actions: [ - CupertinoDialogAction( - child: Text('OK'), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); // Return to home screen - }, + @override + Widget build(BuildContext context) { + final quizAsync = widget.questions != null + ? AsyncValue.data(widget.questions!) + : ref.watch(quizProvider); + + return Scaffold( + appBar: AppBar( + title: Text('Quiz'), + actions: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Text( + 'Time: $_timeLeft', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.red), + ), + ), ), ], ), + body: quizAsync.when( + loading: () => Center(child: CircularProgressIndicator()), + error: (err, stack) => Center(child: Text('Error: $err')), + data: (questions) => _buildQuizContent(questions), + ), ); } - String cleanImageUrl(String url) { - final regex = RegExp(r'(https?:\/\/)+(.*)', caseSensitive: false); - final match = regex.firstMatch(url); - if (match != null) { - return '${match.group(1)}${match.group(2)}'; + Widget _buildQuizContent(List questions) { + if (currentQuestion >= questions.length) { + return _buildResultScreen(); } - return url; - } - void startTimer() { - _timer = Timer.periodic(Duration(seconds: 1), (timer) { - if (_timeLeft > 0) { - setState(() { - _timeLeft--; - }); - } else { - timer.cancel(); - goToNextQuestion(); - } - }); + Question question = questions[currentQuestion]; + return SafeArea( + child: Stack( + children: [ + SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + LinearProgressIndicator(value: (currentQuestion + 1) / questions.length), + SizedBox(height: 20), + Text( + 'Question ${currentQuestion + 1}/${questions.length}', + style: Theme.of(context).textTheme.titleLarge, + ), + SizedBox(height: 20), + Text( + question.text, + style: Theme.of(context).textTheme.headlineSmall, + ), + SizedBox(height: 20), + if (question.imageUrl.isNotEmpty) + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + question.imageUrl, + height: 200, + width: double.infinity, + fit: BoxFit.cover, + ), + ), + SizedBox(height: 20), + ...question.options.asMap().entries.map((entry) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: ElevatedButton( + child: Text(entry.value), + onPressed: () => _answerQuestion(entry.key == question.answer), + ), + ); + }).toList(), + SizedBox(height: 20), + if (!isHintVisible) + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.orange, + foregroundColor: Colors.white, + ), + child: Text('Show Hint'), + onPressed: () => setState(() => isHintVisible = true), + ), + if (isHintVisible) + Text( + question.hint, + style: TextStyle(fontStyle: FontStyle.italic), + ), + ], + ), + ), + ), + Align( + alignment: Alignment.topCenter, + child: ConfettiWidget( + confettiController: _confettiController, + blastDirection: -3.14 / 2, + colors: [Colors.purple, Colors.orange], + emissionFrequency: 0.05, + ), + ), + ], + ), + ); } - void resetTimer() { + void _answerQuestion(bool isCorrect) { _timer?.cancel(); - setState(() { - _timeLeft = 30; - isHintVisible = false; - }); - startTimer(); - } - - void answerQuestion(int selectedAnswer) async { - if (selectedAnswer == questions[currentQuestion].answer) { + if (isCorrect) { score++; _confettiController.play(); - await playSound('correct.wav'); - } else { - await playSound('incorrect.wav'); - } - goToNextQuestion(); - } - - void goToNextQuestion() { - if (currentQuestion < questions.length - 1) { - setState(() { - currentQuestion++; - isHintVisible = false; - }); - _animationController.forward(from: 0.0); - resetTimer(); - } else { - _timer?.cancel(); - Navigator.pushReplacement( - context, - CupertinoPageRoute( - builder: (context) => ResultsScreen(score: score, total: questions.length), - ), - ); } - } - - void showHint() { setState(() { - isHintVisible = true; + currentQuestion++; + isHintVisible = false; }); + _animationController.forward(from: 0.0); + if (currentQuestion < (widget.questions ?? ref.read(quizProvider).value!).length) { + startTimer(); + } } - Future playSound(String soundFile) async { - await SystemSound.play(SystemSoundType.click); - } - - @override - Widget build(BuildContext context) { - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text('Quiz'), - ), - child: SafeArea( - child: Stack( - children: [ - isLoading - ? Center(child: CupertinoActivityIndicator()) - : Column( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Question ${currentQuestion + 1}/${questions.length}', - style: TextStyle(fontSize: 18), - ), - Container( - padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), - decoration: BoxDecoration( - color: CupertinoColors.systemRed, - borderRadius: BorderRadius.circular(15), - ), - child: Text( - '$_timeLeft s', - style: TextStyle(fontSize: 18, color: CupertinoColors.white), - ), - ), - ], - ), - ), - LinearProgressIndicator( - value: (currentQuestion + 1) / questions.length, - backgroundColor: CupertinoColors.systemGrey5, - valueColor: AlwaysStoppedAnimation(CupertinoColors.activeBlue), - ), - Expanded( - child: FadeTransition( - opacity: _animation, - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - questions[currentQuestion].text, - style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), - textAlign: TextAlign.center, - ), - ), - if (questions[currentQuestion].imageUrl.isNotEmpty) - Padding( - padding: const EdgeInsets.all(16.0), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: Image.network( - cleanImageUrl(questions[currentQuestion].imageUrl), - height: 200, - width: double.infinity, - fit: BoxFit.cover, - ), - ), - ), - for (int i = 0; i < questions[currentQuestion].options.length; i++) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), - child: CupertinoButton( - color: CupertinoColors.activeBlue, - onPressed: () => answerQuestion(i), - child: Text(questions[currentQuestion].options[i]), - ), - ), - if (!isHintVisible) - CupertinoButton( - child: Text('Show Hint'), - onPressed: showHint, - ), - if (isHintVisible) - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - questions[currentQuestion].hint, - style: TextStyle(fontSize: 16, color: CupertinoColors.systemGrey), - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ), - ], - ), - Align( - alignment: Alignment.topCenter, - child: ConfettiWidget( - confettiController: _confettiController, - blastDirection: -3.14 / 2, // Upwards - colors: [CupertinoColors.systemPurple, CupertinoColors.systemOrange], - emissionFrequency: 0.05, - ), - ), - ], - ), + Widget _buildResultScreen() { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Quiz Completed!', + style: Theme.of(context).textTheme.headlineMedium, + ), + SizedBox(height: 20), + Text( + 'Your Score: $score', + style: Theme.of(context).textTheme.headlineSmall, + ), + SizedBox(height: 40), + ElevatedButton( + child: Text('Return to Home'), + onPressed: () => Navigator.of(context).popUntil((route) => route.isFirst), + ), + ], ), ); } } -class ResultsScreen extends StatelessWidget { - final int score; - final int total; +class CreateQuizScreen extends StatefulWidget { + @override + _CreateQuizScreenState createState() => _CreateQuizScreenState(); +} - ResultsScreen({required this.score, required this.total}); +class _CreateQuizScreenState extends State { + final _formKey = GlobalKey(); + String _questionText = ''; + List _options = ['', '', '', '']; + int _correctAnswer = 0; + String _hint = ''; @override Widget build(BuildContext context) { - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text('Results'), - ), - child: SafeArea( - child: Center( + return Scaffold( + appBar: AppBar(title: Text('Create Quiz')), + body: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Form( + key: _formKey, child: Column( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - 'You scored:', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + TextFormField( + decoration: InputDecoration(labelText: 'Question'), + validator: (value) => value!.isEmpty ? 'Please enter a question' : null, + onSaved: (value) => _questionText = value!, ), SizedBox(height: 20), - Text( - '$score / $total', - style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold, color: CupertinoColors.systemPurple), + ...List.generate(4, (index) { + return Padding( + padding: EdgeInsets.only(bottom: 10), + child: TextFormField( + decoration: InputDecoration(labelText: 'Option ${index + 1}'), + validator: (value) => value!.isEmpty ? 'Please enter an option' : null, + onSaved: (value) => _options[index] = value!, + ), + ); + }), + SizedBox(height: 20), + DropdownButtonFormField( + decoration: InputDecoration(labelText: 'Correct Answer'), + items: [0, 1, 2, 3].map((int value) { + return DropdownMenuItem( + value: value, + child: Text('Option ${value + 1}'), + ); + }).toList(), + onChanged: (value) => setState(() => _correctAnswer = value!), + validator: (value) => value == null ? 'Please select the correct answer' : null, + ), + SizedBox(height: 20), + TextFormField( + decoration: InputDecoration(labelText: 'Hint'), + onSaved: (value) => _hint = value!, ), SizedBox(height: 40), - CupertinoButton.filled( - child: Text('Play Again'), - onPressed: () { - Navigator.pushReplacement( - context, - CupertinoPageRoute(builder: (context) => QuizScreen()), - ); - }, + ElevatedButton( + child: Text('Preview Question'), + onPressed: _previewQuestion, ), SizedBox(height: 20), - CupertinoButton( - child: Text('Go to Home'), - onPressed: () { - Navigator.pushReplacement( - context, - CupertinoPageRoute(builder: (context) => HomeScreen()), - ); - }, + ElevatedButton( + child: Text('Save Question'), + onPressed: _saveQuestion, ), ], ), @@ -442,4 +470,51 @@ class ResultsScreen extends StatelessWidget { ), ); } -} + + void _previewQuestion() { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + Question previewQuestion = Question( + id: DateTime.now().millisecondsSinceEpoch.toString(), + text: _questionText, + options: _options, + answer: _correctAnswer, + hint: _hint, + imageUrl: '', + ); + + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => QuizScreen(questions: [previewQuestion]), + ), + ); + } + } + + void _saveQuestion() async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + Question newQuestion = Question( + id: DateTime.now().millisecondsSinceEpoch.toString(), + text: _questionText, + options: _options, + answer: _correctAnswer, + hint: _hint, + imageUrl: '', + ); + + SharedPreferences prefs = await SharedPreferences.getInstance(); + List savedQuestions = prefs.getStringList('custom_questions') ?? []; + savedQuestions.add(json.encode(newQuestion.toJson())); + await prefs.setStringList('custom_questions', savedQuestions); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Question saved successfully!')), + ); + + Navigator.of(context).pop(); + } + } +} \ No newline at end of file diff --git a/flutter_app/macos/Flutter/Flutter-Debug.xcconfig b/flutter_app/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b..4b81f9b 100644 --- a/flutter_app/macos/Flutter/Flutter-Debug.xcconfig +++ b/flutter_app/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/flutter_app/macos/Flutter/Flutter-Release.xcconfig b/flutter_app/macos/Flutter/Flutter-Release.xcconfig index c2efd0b..5caa9d1 100644 --- a/flutter_app/macos/Flutter/Flutter-Release.xcconfig +++ b/flutter_app/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift b/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..724bb2a 100644 --- a/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/flutter_app/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/flutter_app/macos/Podfile b/flutter_app/macos/Podfile new file mode 100644 index 0000000..c795730 --- /dev/null +++ b/flutter_app/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/flutter_app/pubspec.lock b/flutter_app/pubspec.lock index 19f7305..7e2c612 100644 --- a/flutter_app/pubspec.lock +++ b/flutter_app/pubspec.lock @@ -1,14 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - args: - dependency: transitive - description: - name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" - url: "https://pub.dev" - source: hosted - version: "2.5.0" async: dependency: transitive description: @@ -65,6 +57,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" flutter: dependency: "direct main" description: flutter @@ -78,27 +86,40 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" + url: "https://pub.dev" + source: hosted + version: "2.5.1" flutter_svg: dependency: "direct main" description: name: flutter_svg - sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + sha256: "6ff9fa12892ae074092de2fa6a9938fb21dbabfdaa2ff57dc697ff912fc8d4b2" url: "https://pub.dev" source: hosted - version: "2.0.10+1" + version: "1.1.6" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" http: dependency: "direct main" description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "0.13.6" http_parser: dependency: transitive description: @@ -171,6 +192,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_parsing: dependency: transitive description: @@ -179,6 +208,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" petitparser: dependency: transitive description: @@ -187,6 +240,86 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + riverpod: + dependency: transitive + description: + name: riverpod + sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d + url: "https://pub.dev" + source: hosted + version: "2.5.1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f + url: "https://pub.dev" + source: hosted + version: "2.5.2" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -208,6 +341,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.11.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -248,30 +389,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" - url: "https://pub.dev" - source: hosted - version: "1.1.11+1" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da - url: "https://pub.dev" - source: hosted - version: "1.1.11+1" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" - url: "https://pub.dev" - source: hosted - version: "1.1.11+1" vector_math: dependency: transitive description: @@ -296,6 +413,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" xml: dependency: transitive description: @@ -306,4 +431,4 @@ packages: version: "6.5.0" sdks: dart: ">=3.4.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + flutter: ">=3.22.0" diff --git a/flutter_app/pubspec.yaml b/flutter_app/pubspec.yaml index 737ee41..25a7cd3 100644 --- a/flutter_app/pubspec.yaml +++ b/flutter_app/pubspec.yaml @@ -10,9 +10,11 @@ environment: dependencies: flutter: sdk: flutter - flutter_svg: ^2.0.7 - confetti: ^0.7.0 - http: ^1.1.0 + flutter_riverpod: ^2.1.1 + http: ^0.13.4 + flutter_svg: ^1.0.3 + confetti: ^0.7.0 + shared_preferences: ^2.0.13 dev_dependencies: flutter_test: diff --git a/go-backend/quiz.db b/go-backend/quiz.db new file mode 100644 index 0000000..997af35 Binary files /dev/null and b/go-backend/quiz.db differ