From 6335220e57b63530ca919a0e498ba12f0b04abf2 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Wed, 19 Nov 2025 18:13:21 +0900 Subject: [PATCH] ... --- .dart_tool/package_config.json | 6 + .dart_tool/package_graph.json | 17 ++ apps/app_finddiff/ios/Flutter/Debug.xcconfig | 1 + .../app_finddiff/ios/Flutter/Release.xcconfig | 1 + apps/app_finddiff/ios/Podfile | 43 ++++ apps/app_finddiff/ios/Podfile.lock | 129 ++++++++++ .../ios/Runner.xcodeproj/project.pbxproj | 130 ++++++++++ .../contents.xcworkspacedata | 3 + apps/app_finddiff/ios/Runner/Info.plist | 2 + apps/app_finddiff/lib/main.dart | 147 +++--------- .../flutter/generated_plugin_registrant.cc | 8 + .../linux/flutter/generated_plugins.cmake | 2 + .../macos/Flutter/Flutter-Debug.xcconfig | 1 + .../macos/Flutter/Flutter-Release.xcconfig | 1 + .../Flutter/GeneratedPluginRegistrant.swift | 14 ++ apps/app_finddiff/macos/Podfile | 42 ++++ apps/app_finddiff/pubspec.lock | 213 ----------------- apps/app_finddiff/pubspec.yaml | 4 +- .../flutter/generated_plugin_registrant.cc | 6 + .../windows/flutter/generated_plugins.cmake | 2 + .../lib/feature_game_finddiff.dart | 9 +- .../lib/services/identity_service.dart | 226 ++++-------------- pubspec.yaml | 1 + 23 files changed, 506 insertions(+), 502 deletions(-) create mode 100644 apps/app_finddiff/ios/Podfile create mode 100644 apps/app_finddiff/ios/Podfile.lock create mode 100644 apps/app_finddiff/macos/Podfile delete mode 100644 apps/app_finddiff/pubspec.lock diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index 83c1588..508c84d 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json @@ -691,6 +691,12 @@ "packageUri": "lib/", "languageVersion": "3.9" }, + { + "name": "app_finddiff", + "rootUri": "../apps/app_finddiff", + "packageUri": "lib/", + "languageVersion": "3.9" + }, { "name": "service_api", "rootUri": "../packages/service_api", diff --git a/.dart_tool/package_graph.json b/.dart_tool/package_graph.json index 5ce8888..48789ad 100644 --- a/.dart_tool/package_graph.json +++ b/.dart_tool/package_graph.json @@ -2,6 +2,7 @@ "roots": [ "app_cardflip", "app_colormatch", + "app_finddiff", "app_mathquiz", "app_sequence", "app_spider", @@ -124,6 +125,22 @@ "flutter_test" ] }, + { + "name": "app_finddiff", + "version": "0.0.0", + "dependencies": [ + "feature_common", + "feature_game_finddiff", + "flutter", + "google_mobile_ads", + "provider", + "service_api" + ], + "devDependencies": [ + "flutter_lints", + "flutter_test" + ] + }, { "name": "service_api", "version": "1.0.0", diff --git a/apps/app_finddiff/ios/Flutter/Debug.xcconfig b/apps/app_finddiff/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/apps/app_finddiff/ios/Flutter/Debug.xcconfig +++ b/apps/app_finddiff/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/apps/app_finddiff/ios/Flutter/Release.xcconfig b/apps/app_finddiff/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/apps/app_finddiff/ios/Flutter/Release.xcconfig +++ b/apps/app_finddiff/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/apps/app_finddiff/ios/Podfile b/apps/app_finddiff/ios/Podfile new file mode 100644 index 0000000..620e46e --- /dev/null +++ b/apps/app_finddiff/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.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! + + 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/apps/app_finddiff/ios/Podfile.lock b/apps/app_finddiff/ios/Podfile.lock new file mode 100644 index 0000000..8e0f490 --- /dev/null +++ b/apps/app_finddiff/ios/Podfile.lock @@ -0,0 +1,129 @@ +PODS: + - AppAuth (2.0.0): + - AppAuth/Core (= 2.0.0) + - AppAuth/ExternalUserAgent (= 2.0.0) + - AppAuth/Core (2.0.0) + - AppAuth/ExternalUserAgent (2.0.0): + - AppAuth/Core + - AppCheckCore (11.2.0): + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) + - Flutter (1.0.0) + - flutter_secure_storage (6.0.0): + - Flutter + - Google-Mobile-Ads-SDK (11.13.0): + - GoogleUserMessagingPlatform (>= 1.1) + - google_mobile_ads (5.3.1): + - Flutter + - Google-Mobile-Ads-SDK (~> 11.13.0) + - webview_flutter_wkwebview + - google_sign_in_ios (0.0.1): + - Flutter + - FlutterMacOS + - GoogleSignIn (~> 9.0) + - GTMSessionFetcher (>= 3.4.0) + - GoogleSignIn (9.0.0): + - AppAuth (~> 2.0) + - AppCheckCore (~> 11.0) + - GTMAppAuth (~> 5.0) + - GTMSessionFetcher/Core (~> 3.3) + - GoogleUserMessagingPlatform (3.1.0) + - GoogleUtilities/Environment (8.1.0): + - GoogleUtilities/Privacy + - GoogleUtilities/Logger (8.1.0): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (8.1.0) + - GoogleUtilities/UserDefaults (8.1.0): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GTMAppAuth (5.0.0): + - AppAuth/Core (~> 2.0) + - GTMSessionFetcher/Core (< 4.0, >= 3.3) + - GTMSessionFetcher (3.5.0): + - GTMSessionFetcher/Full (= 3.5.0) + - GTMSessionFetcher/Core (3.5.0) + - GTMSessionFetcher/Full (3.5.0): + - GTMSessionFetcher/Core + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - PromisesObjC (2.4.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sign_in_with_apple (0.0.1): + - Flutter + - url_launcher_ios (0.0.1): + - Flutter + - webview_flutter_wkwebview (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - Flutter (from `Flutter`) + - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) + - google_mobile_ads (from `.symlinks/plugins/google_mobile_ads/ios`) + - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`) + +SPEC REPOS: + trunk: + - AppAuth + - AppCheckCore + - Google-Mobile-Ads-SDK + - GoogleSignIn + - GoogleUserMessagingPlatform + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - PromisesObjC + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + flutter_secure_storage: + :path: ".symlinks/plugins/flutter_secure_storage/ios" + google_mobile_ads: + :path: ".symlinks/plugins/google_mobile_ads/ios" + google_sign_in_ios: + :path: ".symlinks/plugins/google_sign_in_ios/darwin" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sign_in_with_apple: + :path: ".symlinks/plugins/sign_in_with_apple/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + webview_flutter_wkwebview: + :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" + +SPEC CHECKSUMS: + AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063 + AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 + Google-Mobile-Ads-SDK: 14f57f2dc33532a24db288897e26494640810407 + google_mobile_ads: fe0e2c1764ad95323dd0e3081d0bb2d58411f957 + google_sign_in_ios: 055d43c4754f2860a53decd5133b78d05615fffd + GoogleSignIn: c7f09cfbc85a1abf69187be091997c317cc33b77 + GoogleUserMessagingPlatform: befe603da6501006420c206222acd449bba45a9c + GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 + GTMAppAuth: 217a876b249c3c585a54fd6f73e6b58c4f5c4238 + GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 + path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 + sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440 + url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa + webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4 + +PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e + +COCOAPODS: 1.16.2 diff --git a/apps/app_finddiff/ios/Runner.xcodeproj/project.pbxproj b/apps/app_finddiff/ios/Runner.xcodeproj/project.pbxproj index cd2b2e8..b28ad62 100644 --- a/apps/app_finddiff/ios/Runner.xcodeproj/project.pbxproj +++ b/apps/app_finddiff/ios/Runner.xcodeproj/project.pbxproj @@ -7,10 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + 03339EEA8E6DA5F2A308271D /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BAF8A81C47A594AF4F191CA8 /* Pods_RunnerTests.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 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 */; }; + 816F8C9F395B027965436A41 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D28CF413E92AFF9DCD10EF99 /* Pods_Runner.framework */; }; 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 */; }; @@ -45,6 +47,9 @@ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 50F87C3E61118622689C1CDF /* 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 = ""; }; + 68C5FF1ED057A7BFAA083D39 /* 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 = ""; }; + 73FC5B88C4FDFAEC4E95F8B8 /* 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 = ""; }; 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 = ""; }; @@ -55,13 +60,27 @@ 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 = ""; }; + 9E1BC2E30768D01B36B6CBBC /* 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 = ""; }; + BAF8A81C47A594AF4F191CA8 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C8DFEB2F18EE5B84BD73860E /* 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 = ""; }; + D28CF413E92AFF9DCD10EF99 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45781DB7F0067BA9E1F5EE5 /* 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 9211BBC188379C1D7E6354E8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 03339EEA8E6DA5F2A308271D /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 816F8C9F395B027965436A41 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -94,6 +113,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + FD991F423D65CE374280E6C1 /* Pods */, + C9FEBEAF1A87A2090AD4DED1 /* Frameworks */, ); sourceTree = ""; }; @@ -121,6 +142,29 @@ path = Runner; sourceTree = ""; }; + C9FEBEAF1A87A2090AD4DED1 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D28CF413E92AFF9DCD10EF99 /* Pods_Runner.framework */, + BAF8A81C47A594AF4F191CA8 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + FD991F423D65CE374280E6C1 /* Pods */ = { + isa = PBXGroup; + children = ( + 73FC5B88C4FDFAEC4E95F8B8 /* Pods-Runner.debug.xcconfig */, + D45781DB7F0067BA9E1F5EE5 /* Pods-Runner.release.xcconfig */, + 68C5FF1ED057A7BFAA083D39 /* Pods-Runner.profile.xcconfig */, + 50F87C3E61118622689C1CDF /* Pods-RunnerTests.debug.xcconfig */, + 9E1BC2E30768D01B36B6CBBC /* Pods-RunnerTests.release.xcconfig */, + C8DFEB2F18EE5B84BD73860E /* 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 = ( + AB01B513A1082FF6337FB957 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + 9211BBC188379C1D7E6354E8 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +191,15 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 828E3714E29052776B453C06 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + FB7CDFAD475CD9EAA9BCC886 /* [CP] Embed Pods Frameworks */, + BD29BE108F00AD1571128E5B /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -238,6 +287,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 828E3714E29052776B453C06 /* [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; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +324,62 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + AB01B513A1082FF6337FB957 /* [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; + }; + BD29BE108F00AD1571128E5B /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + FB7CDFAD475CD9EAA9BCC886 /* [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 +506,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 50F87C3E61118622689C1CDF /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +524,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9E1BC2E30768D01B36B6CBBC /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +540,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = C8DFEB2F18EE5B84BD73860E /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/apps/app_finddiff/ios/Runner.xcworkspace/contents.xcworkspacedata b/apps/app_finddiff/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/apps/app_finddiff/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/apps/app_finddiff/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/apps/app_finddiff/ios/Runner/Info.plist b/apps/app_finddiff/ios/Runner/Info.plist index cfce375..030eb75 100644 --- a/apps/app_finddiff/ios/Runner/Info.plist +++ b/apps/app_finddiff/ios/Runner/Info.plist @@ -45,5 +45,7 @@ UIApplicationSupportsIndirectInputEvents + GADApplicationIdentifier + ca-app-pub-3940256099942544~1458002511 diff --git a/apps/app_finddiff/lib/main.dart b/apps/app_finddiff/lib/main.dart index 7b7f5b6..18ed2cd 100644 --- a/apps/app_finddiff/lib/main.dart +++ b/apps/app_finddiff/lib/main.dart @@ -1,122 +1,51 @@ import 'package:flutter/material.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; +import 'package:provider/provider.dart'; -void main() { - runApp(const MyApp()); +// [C] 공통 서비스 +import 'package:service_api/service_api.dart'; +// [A] 공통 UI 셸 (인트로 화면) +import 'package:feature_common/feature_common.dart'; +// [B] 다른 그림 찾기 게임 (로비 화면) +import 'package:feature_game_finddiff/feature_game_finddiff.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await MobileAds.instance.initialize(); + + runApp( + MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => ThemeNotifier()), + ChangeNotifierProvider(create: (_) => SessionNotifier()), + Provider(create: (_) => PuzzleService()), + Provider(create: (_) => IdentityService()), + ], + child: const MyApp(), + ), + ); } class MyApp extends StatelessWidget { const MyApp({super.key}); - // This widget is the root of your application. @override Widget build(BuildContext context) { + final themeData = context.select((ThemeNotifier n) => n.currentTheme); + final darkThemeData = context.select((ThemeNotifier n) => n.currentDarkTheme); + final themeMode = context.select((ThemeNotifier n) => n.currentThemeMode); + return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - // This is the theme of your application. - // - // TRY THIS: Try running your application with "flutter run". You'll see - // the application has a purple toolbar. Then, without quitting the app, - // try changing the seedColor in the colorScheme below to Colors.green - // and then invoke "hot reload" (save your changes or press the "hot - // reload" button in a Flutter-supported IDE, or press "r" if you used - // the command line to start the app). - // - // Notice that the counter didn't reset back to zero; the application - // state is not lost during the reload. To reset the state, use hot - // restart instead. - // - // This works for code too, not just values: Most code changes can be - // tested with just a hot reload. - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + title: '다른 그림 찾기', + theme: themeData, + darkTheme: darkThemeData, + themeMode: themeMode, + debugShowCheckedModeBanner: false, + + // 🔽 FindDiffLobbyScreen으로 연결 + home: IntroScreen( + nextScreenBuilder: (context) => const FindDiffLobbyScreen(), ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('You have pushed the button this many times:'), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } -} +} \ No newline at end of file diff --git a/apps/app_finddiff/linux/flutter/generated_plugin_registrant.cc b/apps/app_finddiff/linux/flutter/generated_plugin_registrant.cc index e71a16d..38dd0bc 100644 --- a/apps/app_finddiff/linux/flutter/generated_plugin_registrant.cc +++ b/apps/app_finddiff/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,14 @@ #include "generated_plugin_registrant.h" +#include +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/apps/app_finddiff/linux/flutter/generated_plugins.cmake b/apps/app_finddiff/linux/flutter/generated_plugins.cmake index 2e1de87..65240e9 100644 --- a/apps/app_finddiff/linux/flutter/generated_plugins.cmake +++ b/apps/app_finddiff/linux/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_linux + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/apps/app_finddiff/macos/Flutter/Flutter-Debug.xcconfig b/apps/app_finddiff/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b..4b81f9b 100644 --- a/apps/app_finddiff/macos/Flutter/Flutter-Debug.xcconfig +++ b/apps/app_finddiff/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/apps/app_finddiff/macos/Flutter/Flutter-Release.xcconfig b/apps/app_finddiff/macos/Flutter/Flutter-Release.xcconfig index c2efd0b..5caa9d1 100644 --- a/apps/app_finddiff/macos/Flutter/Flutter-Release.xcconfig +++ b/apps/app_finddiff/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/apps/app_finddiff/macos/Flutter/GeneratedPluginRegistrant.swift b/apps/app_finddiff/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..e156e5f 100644 --- a/apps/app_finddiff/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/apps/app_finddiff/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,20 @@ import FlutterMacOS import Foundation +import flutter_secure_storage_macos +import google_sign_in_ios +import path_provider_foundation +import shared_preferences_foundation +import sign_in_with_apple +import url_launcher_macos +import webview_flutter_wkwebview func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) } diff --git a/apps/app_finddiff/macos/Podfile b/apps/app_finddiff/macos/Podfile new file mode 100644 index 0000000..ff5ddb3 --- /dev/null +++ b/apps/app_finddiff/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# 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! + + 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/apps/app_finddiff/pubspec.lock b/apps/app_finddiff/pubspec.lock deleted file mode 100644 index c1b51d3..0000000 --- a/apps/app_finddiff/pubspec.lock +++ /dev/null @@ -1,213 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.dev" - source: hosted - version: "5.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.dev" - source: hosted - version: "5.1.1" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.dev" - source: hosted - version: "0.7.6" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" - source: hosted - version: "15.0.2" -sdks: - dart: ">=3.9.2 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" diff --git a/apps/app_finddiff/pubspec.yaml b/apps/app_finddiff/pubspec.yaml index 4e6ad5b..d19686e 100644 --- a/apps/app_finddiff/pubspec.yaml +++ b/apps/app_finddiff/pubspec.yaml @@ -24,8 +24,8 @@ dependencies: path: ../../packages/feature_common # [B] 수학 퀴즈 게임 로직 - feature_game_sequence: - path: ../../packages/feature_game_sequence + feature_game_finddiff: + path: ../../packages/feature_game_finddiff dev_dependencies: diff --git a/apps/app_finddiff/windows/flutter/generated_plugin_registrant.cc b/apps/app_finddiff/windows/flutter/generated_plugin_registrant.cc index 8b6d468..2048c45 100644 --- a/apps/app_finddiff/windows/flutter/generated_plugin_registrant.cc +++ b/apps/app_finddiff/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,12 @@ #include "generated_plugin_registrant.h" +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/apps/app_finddiff/windows/flutter/generated_plugins.cmake b/apps/app_finddiff/windows/flutter/generated_plugins.cmake index b93c4c3..de626cc 100644 --- a/apps/app_finddiff/windows/flutter/generated_plugins.cmake +++ b/apps/app_finddiff/windows/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_windows + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/packages/feature_game_finddiff/lib/feature_game_finddiff.dart b/packages/feature_game_finddiff/lib/feature_game_finddiff.dart index 298576d..3536025 100644 --- a/packages/feature_game_finddiff/lib/feature_game_finddiff.dart +++ b/packages/feature_game_finddiff/lib/feature_game_finddiff.dart @@ -1,5 +1,4 @@ -/// A Calculator. -class Calculator { - /// Returns [value] plus 1. - int addOne(int value) => value + 1; -} +// packages/feature_game_finddiff/lib/feature_game_finddiff.dart + +// 메인 앱이 사용할 로비 화면 export +export 'screens/finddiff_lobby_screen.dart'; \ No newline at end of file diff --git a/packages/service_api/lib/services/identity_service.dart b/packages/service_api/lib/services/identity_service.dart index 3925b0b..c4d9db1 100644 --- a/packages/service_api/lib/services/identity_service.dart +++ b/packages/service_api/lib/services/identity_service.dart @@ -4,11 +4,10 @@ import 'dart:convert'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:uuid/uuid.dart'; -// 현재 로그인 세션을 담을 모델 class UserSession { final String userId; final String? userName; - final String loginProvider; // "guest", "google", "apple" + final String loginProvider; final String? email; UserSession({ @@ -21,221 +20,119 @@ class UserSession { bool get isGuest => loginProvider == "guest"; } -// 앱-고유 ID와 사용자 이름, 레벨 진행 상황을 관리하는 서비스 class IdentityService { static const String _userIdKey = 'app_user_id'; static const String _userNameKey = 'app_user_name'; static const String _loginProviderKey = 'app_login_provider'; static const String _userEmailKey = 'app_user_email'; - // 게임별 저장 키 정의 + // 기존 게임 키들 static const String _sudokuMaxLevelKey = 'max_unlocked_level'; static const String _sudokuRankMapKey = 'last_checked_rank_map'; - static const String _spiderMaxLevelKey = 'max_unlocked_spider_level'; static const String _spiderRankMapKey = 'last_checked_spider_rank_map'; - static const String _mathQuizMaxLevelKey = 'max_unlocked_mathquiz_level'; static const String _mathQuizRankMapKey = 'last_checked_mathquiz_rank_map'; - - // [🔥 신규] 색상 일치 게임 키 static const String _colorMatchMaxLevelKey = 'max_unlocked_colormatch_level'; static const String _colorMatchRankMapKey = 'last_checked_colormatch_rank_map'; - - // [🔥 신규] 순서 기억 게임 키 static const String _sequenceMaxLevelKey = 'max_unlocked_sequence_level'; static const String _sequenceRankMapKey = 'last_checked_sequence_rank_map'; - - // [🔥 신규] 카드 뒤집기 게임 키 static const String _cardFlipMaxLevelKey = 'max_unlocked_cardflip_level'; static const String _cardFlipRankMapKey = 'last_checked_cardflip_rank_map'; + // 🔽 [🔥 신규] 다른 그림 찾기 키 추가 + static const String _findDiffMaxLevelKey = 'max_unlocked_finddiff_level'; + static const String _findDiffRankMapKey = 'last_checked_finddiff_rank_map'; + final _storage = const FlutterSecureStorage(); IOSOptions _getIOSOptions() => const IOSOptions(); - - AndroidOptions _getAndroidOptions() => const AndroidOptions( - encryptedSharedPreferences: true, - ); + AndroidOptions _getAndroidOptions() => const AndroidOptions(encryptedSharedPreferences: true); - // 1. 현재 세션 정보를 '객체'로 가져오기 Future getUserSession() async { final userId = await getOrCreateUserId(); final userName = await getSavedUserName(); - final loginProvider = await _storage.read( - key: _loginProviderKey, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions() - ) ?? "guest"; - final email = await _storage.read( - key: _userEmailKey, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions() - ); - - return UserSession( - userId: userId, - userName: userName, - loginProvider: loginProvider, - email: email, - ); + final loginProvider = await _storage.read(key: _loginProviderKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()) ?? "guest"; + final email = await _storage.read(key: _userEmailKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); + return UserSession(userId: userId, userName: userName, loginProvider: loginProvider, email: email); } - // 2. 앱-고유 ID 가져오기 (없으면 생성) Future getOrCreateUserId() async { - String? userId = await _storage.read( - key: _userIdKey, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); - + String? userId = await _storage.read(key: _userIdKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); if (userId == null) { userId = const Uuid().v4(); - await _storage.write( - key: _userIdKey, - value: userId, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + await _storage.write(key: _userIdKey, value: userId, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); } return userId; } - // 3. 랭킹에 등록한 사용자 이름 가져오기 Future getSavedUserName() async { - return await _storage.read( - key: _userNameKey, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + return await _storage.read(key: _userNameKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); } - // 4. 랭킹 등록 성공 시, 사용자 이름 저장하기 Future saveUserName(String name) async { - await _storage.write( - key: _userNameKey, - value: name, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + await _storage.write(key: _userNameKey, value: name, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); } - // 5. 소셜 로그인 성공 시 호출 (계정 연결) - Future saveSocialLogin({ - required String newUserId, - required String newUserName, - required String newEmail, - required String provider, - }) async { + Future saveSocialLogin({required String newUserId, required String newUserName, required String newEmail, required String provider}) async { await _storage.write(key: _userIdKey, value: newUserId, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); await _storage.write(key: _userNameKey, value: newUserName, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); await _storage.write(key: _userEmailKey, value: newEmail, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); await _storage.write(key: _loginProviderKey, value: provider, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); - - return UserSession( - userId: newUserId, - userName: newUserName, - loginProvider: provider, - email: newEmail, - ); + return UserSession(userId: newUserId, userName: newUserName, loginProvider: provider, email: newEmail); } - // 6. 로그아웃 (게스트 계정으로 되돌리기) Future logout() async { await _storage.delete(key: _userNameKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); await _storage.delete(key: _userEmailKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); await _storage.delete(key: _loginProviderKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); - return await getUserSession(); } - // 7. [수정] 최대 레벨 가져오기 (모든 게임 타입 지원) + // 7. [수정] 최대 레벨 가져오기 Future getMaxUnlockedLevel({String gameType = 'SUDOKU'}) async { String key; switch (gameType) { - case 'SPIDER': - key = _spiderMaxLevelKey; - break; - case 'MATH_QUIZ': - key = _mathQuizMaxLevelKey; - break; - case 'COLOR_MATCH': // 👈 추가 - key = _colorMatchMaxLevelKey; - break; - case 'SEQUENCE': // 👈 추가 - key = _sequenceMaxLevelKey; - break; - case 'CARD_FLIP': // 👈 추가 - key = _cardFlipMaxLevelKey; - break; - default: // 'SUDOKU' - key = _sudokuMaxLevelKey; + case 'SPIDER': key = _spiderMaxLevelKey; break; + case 'MATH_QUIZ': key = _mathQuizMaxLevelKey; break; + case 'COLOR_MATCH': key = _colorMatchMaxLevelKey; break; + case 'SEQUENCE': key = _sequenceMaxLevelKey; break; + case 'CARD_FLIP': key = _cardFlipMaxLevelKey; break; + case 'FIND_DIFF': key = _findDiffMaxLevelKey; break; // 👈 추가 + default: key = _sudokuMaxLevelKey; } - String? levelString = await _storage.read( - key: key, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + String? levelString = await _storage.read(key: key, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); return int.parse(levelString ?? '1'); } - // 8. [수정] 최대 레벨 저장하기 (모든 게임 타입 지원) + // 8. [수정] 최대 레벨 저장하기 Future saveMaxUnlockedLevel(int level, {String gameType = 'SUDOKU'}) async { String key; switch (gameType) { - case 'SPIDER': - key = _spiderMaxLevelKey; - break; - case 'MATH_QUIZ': - key = _mathQuizMaxLevelKey; - break; - case 'COLOR_MATCH': // 👈 추가 - key = _colorMatchMaxLevelKey; - break; - case 'SEQUENCE': // 👈 추가 - key = _sequenceMaxLevelKey; - break; - case 'CARD_FLIP': // 👈 추가 - key = _cardFlipMaxLevelKey; - break; - default: // 'SUDOKU' - key = _sudokuMaxLevelKey; + case 'SPIDER': key = _spiderMaxLevelKey; break; + case 'MATH_QUIZ': key = _mathQuizMaxLevelKey; break; + case 'COLOR_MATCH': key = _colorMatchMaxLevelKey; break; + case 'SEQUENCE': key = _sequenceMaxLevelKey; break; + case 'CARD_FLIP': key = _cardFlipMaxLevelKey; break; + case 'FIND_DIFF': key = _findDiffMaxLevelKey; break; // 👈 추가 + default: key = _sudokuMaxLevelKey; } - await _storage.write( - key: key, - value: level.toString(), - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + await _storage.write(key: key, value: level.toString(), iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); } - // 9. [수정] 마지막 랭킹 맵 가져오기 (모든 게임 타입 지원) + // 9. [수정] 마지막 랭킹 맵 가져오기 Future> getLastSavedRankMap({String gameType = 'SUDOKU'}) async { String key; switch (gameType) { - case 'SPIDER': - key = _spiderRankMapKey; - break; - case 'MATH_QUIZ': - key = _mathQuizRankMapKey; - break; - case 'COLOR_MATCH': // 👈 추가 - key = _colorMatchRankMapKey; - break; - case 'SEQUENCE': // 👈 추가 - key = _sequenceRankMapKey; - break; - case 'CARD_FLIP': // 👈 추가 - key = _cardFlipRankMapKey; - break; - default: // 'SUDOKU' - key = _sudokuRankMapKey; + case 'SPIDER': key = _spiderRankMapKey; break; + case 'MATH_QUIZ': key = _mathQuizRankMapKey; break; + case 'COLOR_MATCH': key = _colorMatchRankMapKey; break; + case 'SEQUENCE': key = _sequenceRankMapKey; break; + case 'CARD_FLIP': key = _cardFlipRankMapKey; break; + case 'FIND_DIFF': key = _findDiffRankMapKey; break; // 👈 추가 + default: key = _sudokuRankMapKey; } - String? jsonString = await _storage.read( - key: key, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + String? jsonString = await _storage.read(key: key, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); if (jsonString == null) return {}; try { @@ -246,38 +143,21 @@ class IdentityService { } } - // 10. [수정] 마지막 랭킹 맵 저장하기 (모든 게임 타입 지원) + // 10. [수정] 마지막 랭킹 맵 저장하기 Future saveLastRankMap(Map rankMap, {String gameType = 'SUDOKU'}) async { String key; switch (gameType) { - case 'SPIDER': - key = _spiderRankMapKey; - break; - case 'MATH_QUIZ': - key = _mathQuizRankMapKey; - break; - case 'COLOR_MATCH': // 👈 추가 - key = _colorMatchRankMapKey; - break; - case 'SEQUENCE': // 👈 추가 - key = _sequenceRankMapKey; - break; - case 'CARD_FLIP': // 👈 추가 - key = _cardFlipRankMapKey; - break; - default: // 'SUDOKU' - key = _sudokuRankMapKey; + case 'SPIDER': key = _spiderRankMapKey; break; + case 'MATH_QUIZ': key = _mathQuizRankMapKey; break; + case 'COLOR_MATCH': key = _colorMatchRankMapKey; break; + case 'SEQUENCE': key = _sequenceRankMapKey; break; + case 'CARD_FLIP': key = _cardFlipRankMapKey; break; + case 'FIND_DIFF': key = _findDiffRankMapKey; break; // 👈 추가 + default: key = _sudokuRankMapKey; } - final Map stringKeyMap = - rankMap.map((key, value) => MapEntry(key.toString(), value)); - + final Map stringKeyMap = rankMap.map((key, value) => MapEntry(key.toString(), value)); String jsonString = jsonEncode(stringKeyMap); - await _storage.write( - key: key, - value: jsonString, - iOptions: _getIOSOptions(), - aOptions: _getAndroidOptions(), - ); + await _storage.write(key: key, value: jsonString, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()); } } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index f80ac5e..842ea6e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,6 +15,7 @@ workspace: - apps/app_colormatch - apps/app_sequence - apps/app_cardflip + - apps/app_finddiff - packages/service_api - packages/feature_common - packages/feature_game_sudoku