diff --git a/README.md b/README.md index 1450319..2678694 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ This project is a starting point for a Flutter application. A few resources to get you started if this is your first Flutter project: -- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) -For help getting started with Flutter, view our -[online documentation](https://flutter.io/docs), which offers tutorials, +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..0a741cb --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,11 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/android/app/build.gradle b/android/app/build.gradle index 696c0d0..af48816 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -22,23 +22,23 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 27 + compileSdkVersion 30 - lintOptions { - disable 'InvalidPackage' + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "n.dev.solitaireflutter" + applicationId "n.dev.solitaireflutter.flutter_solitaire" minSdkVersion 16 - targetSdkVersion 27 + targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -55,7 +55,5 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9d513e4..7fe5bc2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,33 +1,41 @@ - - - + - + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + + + + diff --git a/android/app/src/main/java/n/dev/solitaireflutter/MainActivity.java b/android/app/src/main/java/n/dev/solitaireflutter/MainActivity.java deleted file mode 100644 index 4840c22..0000000 --- a/android/app/src/main/java/n/dev/solitaireflutter/MainActivity.java +++ /dev/null @@ -1,13 +0,0 @@ -package n.dev.solitaireflutter; - -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; - -public class MainActivity extends FlutterActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - GeneratedPluginRegistrant.registerWith(this); - } -} diff --git a/android/app/src/main/kotlin/br/com/jhonatanserafim/flutter_solitaire/MainActivity.kt b/android/app/src/main/kotlin/br/com/jhonatanserafim/flutter_solitaire/MainActivity.kt new file mode 100644 index 0000000..b69e17d --- /dev/null +++ b/android/app/src/main/kotlin/br/com/jhonatanserafim/flutter_solitaire/MainActivity.kt @@ -0,0 +1,6 @@ +package n.dev.solitaireflutter.flutter_solitaire + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..449a9f9 --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 00fa441..d74aa35 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,8 +1,18 @@ - + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 0f31bee..884704f 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="n.dev.solitaireflutter.flutter_solitaire"> diff --git a/android/build.gradle b/android/build.gradle index bb8a303..9b6ed06 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,11 +1,13 @@ buildscript { + ext.kotlin_version = '1.3.50' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -19,8 +21,6 @@ allprojects { rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { project.evaluationDependsOn(':app') } diff --git a/android/gradle.properties b/android/gradle.properties index 8bd86f6..94adc3a 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1 +1,3 @@ org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 2819f02..bc6a58a 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..151026b --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,33 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 2ec4806..3349188 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -8,14 +8,8 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 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 */; }; @@ -28,8 +22,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -39,15 +31,12 @@ /* Begin PBXFileReference section */ 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 = ""; }; - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; 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 = ""; }; 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 = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -60,8 +49,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -71,10 +58,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -106,7 +90,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, @@ -115,13 +98,6 @@ path = Runner; sourceTree = ""; }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -151,18 +127,18 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0910; - ORGANIZATIONNAME = "The Chromium Authors"; + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0910; + LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -185,9 +161,7 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -207,7 +181,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -259,7 +233,6 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -271,12 +244,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -297,9 +272,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -310,29 +286,21 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = S8QB4VV633; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = n.dev.solitaireFlutter; + PRODUCT_BUNDLE_IDENTIFIER = n.dev.solitaireflutter.flutterSolitaire; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -344,12 +312,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -376,7 +346,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -386,7 +356,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -398,12 +367,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -424,9 +395,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -441,22 +413,13 @@ CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = n.dev.solitaireFlutter; + PRODUCT_BUNDLE_IDENTIFIER = n.dev.solitaireflutter.flutterSolitaire; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -469,21 +432,12 @@ CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = n.dev.solitaireFlutter; + PRODUCT_BUNDLE_IDENTIFIER = n.dev.solitaireflutter.flutterSolitaire; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -512,7 +466,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a1..919434a 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 786d6aa..a28140c 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -46,7 +45,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings index 949b678..f9b0d7c 100644 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -2,7 +2,7 @@ - BuildSystemType - Original + PreviewsEnabled + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 71cc41e..70693e4 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -5,7 +5,7 @@ import Flutter @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 3d43d11..dc9ada4 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 0ebd4bf..2132dda 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h index 7335fdf..308a2a5 100644 --- a/ios/Runner/Runner-Bridging-Header.h +++ b/ios/Runner/Runner-Bridging-Header.h @@ -1 +1 @@ -#import "GeneratedPluginRegistrant.h" \ No newline at end of file +#import "GeneratedPluginRegistrant.h" diff --git a/lib/card_column.dart b/lib/card_column.dart index 1b1a1d5..60a8916 100644 --- a/lib/card_column.dart +++ b/lib/card_column.dart @@ -1,8 +1,12 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; -import 'package:solitaire_flutter/playing_card.dart'; -import 'package:solitaire_flutter/transformed_card.dart'; + +import 'playing_card.dart'; +import 'transformed_card.dart'; typedef Null CardAcceptCallback(List card, int fromIndex); +typedef Null CardDoubleTapCallback(PlayingCard cardClicked); // This is a stack of overlayed cards (implemented using a stack) class CardColumn extends StatefulWidget { @@ -13,13 +17,17 @@ class CardColumn extends StatefulWidget { // Callback when card is added to the stack final CardAcceptCallback onCardsAdded; + final CardDoubleTapCallback onCardDoubleTap; + // The index of the list in the game final int columnIndex; - CardColumn( - {@required this.cards, - @required this.onCardsAdded, - @required this.columnIndex}); + CardColumn({ + required this.cards, + required this.onCardsAdded, + required this.onCardDoubleTap, + required this.columnIndex, + }); @override _CardColumnState createState() => _CardColumnState(); @@ -29,20 +37,21 @@ class _CardColumnState extends State { @override Widget build(BuildContext context) { return Container( - //alignment: Alignment.topCenter, - height: 13.0 * 15.0, - width: 70.0, - margin: EdgeInsets.all(2.0), + height: 80 + (18.0 * max(widget.cards.length - 1, 7)), + width: 40.0, + margin: EdgeInsets.all(4.0), child: DragTarget( builder: (context, listOne, listTwo) { return Stack( - children: widget.cards.map((card) { + alignment: Alignment.topCenter, + children: widget.cards.map((card) { int index = widget.cards.indexOf(card); return TransformedCard( playingCard: card, transformIndex: index, attachedCards: widget.cards.sublist(index, widget.cards.length), columnIndex: widget.columnIndex, + onCardDoubleTap: widget.onCardDoubleTap, ); }).toList(), ); @@ -54,32 +63,34 @@ class _CardColumnState extends State { } // Get dragged cards list - List draggedCards = value["cards"]; + List draggedCards = value!["cards"]; PlayingCard firstCard = draggedCards.first; if (firstCard.cardColor == CardColor.red) { if (widget.cards.last.cardColor == CardColor.red) { return false; } - int lastColumnCardIndex = CardType.values.indexOf(widget.cards.last.cardType); - int firstDraggedCardIndex = CardType.values.indexOf(firstCard.cardType); + int lastColumnCardIndex = + CardType.values.indexOf(widget.cards.last.cardType); + int firstDraggedCardIndex = + CardType.values.indexOf(firstCard.cardType); - if(lastColumnCardIndex != firstDraggedCardIndex + 1) { + if (lastColumnCardIndex != firstDraggedCardIndex + 1) { return false; } - } else { if (widget.cards.last.cardColor == CardColor.black) { return false; } - int lastColumnCardIndex = CardType.values.indexOf(widget.cards.last.cardType); - int firstDraggedCardIndex = CardType.values.indexOf(firstCard.cardType); + int lastColumnCardIndex = + CardType.values.indexOf(widget.cards.last.cardType); + int firstDraggedCardIndex = + CardType.values.indexOf(firstCard.cardType); - if(lastColumnCardIndex != firstDraggedCardIndex + 1) { + if (lastColumnCardIndex != firstDraggedCardIndex + 1) { return false; } - } return true; }, diff --git a/lib/empty_card.dart b/lib/empty_card.dart index feaaca3..21c42ae 100644 --- a/lib/empty_card.dart +++ b/lib/empty_card.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:solitaire_flutter/card_column.dart'; -import 'package:solitaire_flutter/playing_card.dart'; -import 'package:solitaire_flutter/transformed_card.dart'; + +import 'card_column.dart'; +import 'playing_card.dart'; +import 'transformed_card.dart'; // The deck of cards which accept the final cards (Ace to King) class EmptyCardDeck extends StatefulWidget { @@ -11,10 +12,10 @@ class EmptyCardDeck extends StatefulWidget { final int columnIndex; EmptyCardDeck({ - @required this.cardSuit, - @required this.cardsAdded, - @required this.onCardAdded, - this.columnIndex, + required this.cardSuit, + required this.cardsAdded, + required this.onCardAdded, + required this.columnIndex, }); @override @@ -60,7 +61,7 @@ class _EmptyCardDeckState extends State { ); }, onWillAccept: (value) { - PlayingCard cardAdded = value["cards"].last; + PlayingCard cardAdded = value!["cards"].last; if (cardAdded.cardSuit == widget.cardSuit) { if (CardType.values.indexOf(cardAdded.cardType) == @@ -88,10 +89,8 @@ class _EmptyCardDeckState extends State { return Image.asset('images/diamonds.png'); case CardSuit.clubs: return Image.asset('images/clubs.png'); - case CardSuit.spades: - return Image.asset('images/spades.png'); default: - return null; + return Image.asset('images/spades.png'); } } } diff --git a/lib/game_screen.dart b/lib/game_screen.dart index 6b5c6b5..9ee811b 100644 --- a/lib/game_screen.dart +++ b/lib/game_screen.dart @@ -1,10 +1,11 @@ import 'dart:math'; import 'package:flutter/material.dart'; -import 'package:solitaire_flutter/card_column.dart'; -import 'package:solitaire_flutter/empty_card.dart'; -import 'package:solitaire_flutter/playing_card.dart'; -import 'package:solitaire_flutter/transformed_card.dart'; + +import 'card_column.dart'; +import 'empty_card.dart'; +import 'playing_card.dart'; +import 'transformed_card.dart'; class GameScreen extends StatefulWidget { @override @@ -56,134 +57,159 @@ class _GameScreenState extends State { ), splashColor: Colors.white, onTap: () { - _initialiseGame(); + _handleStartNewGame(); }, ) ], ), - body: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - _buildCardDeck(), - _buildFinalDecks(), - ], - ), - SizedBox( - height: 16.0, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: CardColumn( - cards: cardColumn1, - onCardsAdded: (cards, index) { - setState(() { - cardColumn1.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 1, + body: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildCardDeck(), + _buildFinalDecks(), + ], + ), + SizedBox( + height: 16.0, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: CardColumn( + cards: cardColumn1, + onCardsAdded: (cards, index) { + setState(() { + cardColumn1.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 1); + }, + columnIndex: 1, + ), ), - ), - Expanded( - child: CardColumn( - cards: cardColumn2, - onCardsAdded: (cards, index) { - setState(() { - cardColumn2.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 2, + Expanded( + child: CardColumn( + cards: cardColumn2, + onCardsAdded: (cards, index) { + setState(() { + cardColumn2.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 2); + }, + columnIndex: 2, + ), ), - ), - Expanded( - child: CardColumn( - cards: cardColumn3, - onCardsAdded: (cards, index) { - setState(() { - cardColumn3.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 3, + Expanded( + child: CardColumn( + cards: cardColumn3, + onCardsAdded: (cards, index) { + setState(() { + cardColumn3.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 3); + }, + columnIndex: 3, + ), ), - ), - Expanded( - child: CardColumn( - cards: cardColumn4, - onCardsAdded: (cards, index) { - setState(() { - cardColumn4.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 4, + Expanded( + child: CardColumn( + cards: cardColumn4, + onCardsAdded: (cards, index) { + setState(() { + cardColumn4.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 4); + }, + columnIndex: 4, + ), ), - ), - Expanded( - child: CardColumn( - cards: cardColumn5, - onCardsAdded: (cards, index) { - setState(() { - cardColumn5.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 5, + Expanded( + child: CardColumn( + cards: cardColumn5, + onCardsAdded: (cards, index) { + setState(() { + cardColumn5.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 5); + }, + columnIndex: 5, + ), ), - ), - Expanded( - child: CardColumn( - cards: cardColumn6, - onCardsAdded: (cards, index) { - setState(() { - cardColumn6.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 6, + Expanded( + child: CardColumn( + cards: cardColumn6, + onCardsAdded: (cards, index) { + setState(() { + cardColumn6.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 6); + }, + columnIndex: 6, + ), ), - ), - Expanded( - child: CardColumn( - cards: cardColumn7, - onCardsAdded: (cards, index) { - setState(() { - cardColumn7.addAll(cards); - int length = _getListFromIndex(index).length; - _getListFromIndex(index) - .removeRange(length - cards.length, length); - _refreshList(index); - }); - }, - columnIndex: 7, + Expanded( + child: CardColumn( + cards: cardColumn7, + onCardsAdded: (cards, index) { + setState(() { + cardColumn7.addAll(cards); + int length = _getListFromIndex(index).length; + _getListFromIndex(index) + .removeRange(length - cards.length, length); + _refreshList(index); + }); + }, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 7); + }, + columnIndex: 7, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ); } @@ -199,6 +225,7 @@ class _GameScreenState extends State { padding: const EdgeInsets.all(4.0), child: TransformedCard( playingCard: cardDeckClosed.last, + attachedCards: [], ), ) : Opacity( @@ -210,6 +237,7 @@ class _GameScreenState extends State { cardSuit: CardSuit.diamonds, cardType: CardType.five, ), + attachedCards: [], ), ), ), @@ -241,10 +269,24 @@ class _GameScreenState extends State { cardDeckOpened.last, ], columnIndex: 0, + onCardDoubleTap: (cardClicked) { + _onCardDoubleTap(cardClicked, 0); + }, ), ) - : Container( - width: 40.0, + : Opacity( + opacity: 0.4, + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Container( + decoration: BoxDecoration( + color: Colors.black12, + borderRadius: BorderRadius.circular(8.0), + ), + height: 60.0, + width: 40.0, + ), + ), ), ], ), @@ -356,90 +398,84 @@ class _GameScreenState extends State { Random random = Random(); + // Shuffle cards randomly + for (int i = 0; i < 20000; i++) { + int randomNumber = random.nextInt(allCards.length); + PlayingCard card = allCards.removeAt(randomNumber); + allCards.add(card); + } + // Add cards to columns and remaining to deck for (int i = 0; i < 28; i++) { int randomNumber = random.nextInt(allCards.length); + PlayingCard card = allCards.removeAt(randomNumber); if (i == 0) { - PlayingCard card = allCards[randomNumber]; cardColumn1.add( card ..opened = true ..faceUp = true, ); - allCards.removeAt(randomNumber); } else if (i > 0 && i < 3) { if (i == 2) { - PlayingCard card = allCards[randomNumber]; cardColumn2.add( card ..opened = true ..faceUp = true, ); } else { - cardColumn2.add(allCards[randomNumber]); + cardColumn2.add(card); } - allCards.removeAt(randomNumber); } else if (i > 2 && i < 6) { if (i == 5) { - PlayingCard card = allCards[randomNumber]; cardColumn3.add( card ..opened = true ..faceUp = true, ); } else { - cardColumn3.add(allCards[randomNumber]); + cardColumn3.add(card); } - allCards.removeAt(randomNumber); } else if (i > 5 && i < 10) { if (i == 9) { - PlayingCard card = allCards[randomNumber]; cardColumn4.add( card ..opened = true ..faceUp = true, ); } else { - cardColumn4.add(allCards[randomNumber]); + cardColumn4.add(card); } - allCards.removeAt(randomNumber); } else if (i > 9 && i < 15) { if (i == 14) { - PlayingCard card = allCards[randomNumber]; cardColumn5.add( card ..opened = true ..faceUp = true, ); } else { - cardColumn5.add(allCards[randomNumber]); + cardColumn5.add(card); } - allCards.removeAt(randomNumber); } else if (i > 14 && i < 21) { if (i == 20) { - PlayingCard card = allCards[randomNumber]; cardColumn6.add( card ..opened = true ..faceUp = true, ); } else { - cardColumn6.add(allCards[randomNumber]); + cardColumn6.add(card); } - allCards.removeAt(randomNumber); } else { if (i == 27) { - PlayingCard card = allCards[randomNumber]; cardColumn7.add( card ..opened = true ..faceUp = true, ); } else { - cardColumn7.add(allCards[randomNumber]); + cardColumn7.add(card); } - allCards.removeAt(randomNumber); } } @@ -459,7 +495,7 @@ class _GameScreenState extends State { finalClubsDeck.length + finalSpadesDeck.length == 52) { - _handleWin(); + _handleGameWin(); } setState(() { if (_getListFromIndex(index).length != 0) { @@ -470,8 +506,35 @@ class _GameScreenState extends State { }); } + // Handle a start new game condition + void _handleStartNewGame() { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text("Start new game?"), + actions: [ + TextButton( + onPressed: () { + _initialiseGame(); + Navigator.pop(context); + }, + child: Text("Yes"), + ), + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text("Cancel"), + ), + ], + ); + }, + ); + } + // Handle a win condition - void _handleWin() { + void _handleGameWin() { showDialog( context: context, builder: (context) { @@ -479,7 +542,7 @@ class _GameScreenState extends State { title: Text("Congratulations!"), content: Text("You Win!"), actions: [ - FlatButton( + TextButton( onPressed: () { _initialiseGame(); Navigator.pop(context); @@ -516,10 +579,34 @@ class _GameScreenState extends State { return finalDiamondsDeck; case 10: return finalSpadesDeck; - case 11: + default: return finalClubsDeck; + } + } + + void _onCardDoubleTap(PlayingCard cardClicked, int index) { + List finalDeck; + switch (cardClicked.cardSuit) { + case CardSuit.hearts: + finalDeck = finalHeartsDeck; + break; + case CardSuit.diamonds: + finalDeck = finalDiamondsDeck; + break; + case CardSuit.spades: + finalDeck = finalSpadesDeck; + break; default: - return null; + finalDeck = finalClubsDeck; + break; + } + + if (CardType.values.indexOf(cardClicked.cardType) == finalDeck.length && + cardClicked.faceUp && cardClicked.opened) { + finalDeck.add(cardClicked); + int length = _getListFromIndex(index).length; + _getListFromIndex(index).removeRange(length - 1, length); + _refreshList(index); } } } diff --git a/lib/main.dart b/lib/main.dart index 4828708..9ee72b0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:solitaire_flutter/game_screen.dart'; + +import 'game_screen.dart'; void main() => runApp(MyApp()); diff --git a/lib/playing_card.dart b/lib/playing_card.dart index c6c8fb8..4309b68 100644 --- a/lib/playing_card.dart +++ b/lib/playing_card.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - enum CardSuit { spades, hearts, @@ -36,8 +34,8 @@ class PlayingCard { bool opened; PlayingCard({ - @required this.cardSuit, - @required this.cardType, + required this.cardSuit, + required this.cardType, this.faceUp = false, this.opened = false, }); diff --git a/lib/transformed_card.dart b/lib/transformed_card.dart index c460a23..01b450b 100644 --- a/lib/transformed_card.dart +++ b/lib/transformed_card.dart @@ -2,21 +2,25 @@ import 'package:flutter/material.dart'; import 'package:solitaire_flutter/card_column.dart'; import 'package:solitaire_flutter/playing_card.dart'; +typedef Null CardDoubleTapCallback(PlayingCard cardClicked); + // TransformedCard makes the card draggable and translates it according to // position in the stack. class TransformedCard extends StatefulWidget { final PlayingCard playingCard; final double transformDistance; final int transformIndex; - final int columnIndex; + final int? columnIndex; final List attachedCards; + final CardDoubleTapCallback? onCardDoubleTap; TransformedCard({ - @required this.playingCard, - this.transformDistance = 15.0, + required this.playingCard, + this.transformDistance = 18.0, this.transformIndex = 0, this.columnIndex, - this.attachedCards, + required this.attachedCards, + this.onCardDoubleTap, }); @override @@ -48,18 +52,26 @@ class _TransformedCardState extends State { borderRadius: BorderRadius.circular(8.0), ), ) - : Draggable( - child: _buildFaceUpCard(), - feedback: CardColumn( - cards: widget.attachedCards, - columnIndex: 1, - onCardsAdded: (card, position) {}, - ), - childWhenDragging: _buildFaceUpCard(), - data: { - "cards": widget.attachedCards, - "fromIndex": widget.columnIndex, + : GestureDetector( + onDoubleTap: () { + if (widget.onCardDoubleTap != null) { + widget.onCardDoubleTap!(widget.playingCard); + } }, + child: Draggable( + child: _buildFaceUpCard(), + feedback: CardColumn( + cards: widget.attachedCards, + columnIndex: 1, + onCardsAdded: (card, position) {}, + onCardDoubleTap: (cardClicked) {}, + ), + childWhenDragging: _buildFaceUpCard(), + data: { + "cards": widget.attachedCards, + "fromIndex": widget.columnIndex, + }, + ), ); } @@ -97,24 +109,24 @@ class _TransformedCardState extends State { ), Padding( padding: const EdgeInsets.all(4.0), - child: Align( - alignment: Alignment.topRight, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _cardTypeToString(), - style: TextStyle( - fontSize: 10.0, - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _cardTypeToString(), + style: TextStyle( + fontSize: 12.0, ), - Container( - height: 10.0, + ), + Padding( + padding: const EdgeInsets.fromLTRB(1, 0, 0, 0), + child: Container( + height: 12.0, child: _suitToImage(), - ) - ], - ), + ), + ) + ], ), ), ], @@ -149,10 +161,8 @@ class _TransformedCardState extends State { return "J"; case CardType.queen: return "Q"; - case CardType.king: - return "K"; default: - return ""; + return "K"; } } @@ -164,10 +174,8 @@ class _TransformedCardState extends State { return Image.asset('images/diamonds.png'); case CardSuit.clubs: return Image.asset('images/clubs.png'); - case CardSuit.spades: - return Image.asset('images/spades.png'); default: - return null; + return Image.asset('images/spades.png'); } } } diff --git a/pubspec.lock b/pubspec.lock index a4a0fb3..7ffced4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,5 +1,5 @@ # Generated by pub -# See https://www.dartlang.org/tools/pub/glossary#lockfile +# See https://dart.dev/tools/pub/glossary#lockfile packages: async: dependency: transitive @@ -7,35 +7,56 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.6.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.2.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.15.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "1.0.3" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -52,28 +73,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.3+1" + version: "0.12.10" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" + version: "1.8.0" sky_engine: dependency: transitive description: flutter @@ -85,55 +99,55 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.4.1" + version: "1.8.1" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "1.6.8" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "0.3.0" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0" sdks: - dart: ">=2.1.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index a218ac3..62657f9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,16 +1,24 @@ name: solitaire_flutter description: A solitaire clone made in Flutter. +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +. # Both the version and the builder number may be overridden in flutter # build by specifying --build-name and --build-number, respectively. -# Read more about versioning at semver.org. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: @@ -18,15 +26,14 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.2 + cupertino_icons: ^1.0.2 dev_dependencies: flutter_test: sdk: flutter - # For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec +# following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter. flutter: @@ -49,10 +56,10 @@ flutter: # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. + # https://flutter.dev/assets-and-images/#resolution-aware. # For details regarding adding assets from package dependencies, see - # https://flutter.io/assets-and-images/#from-packages + # https://flutter.dev/assets-and-images/#from-packages # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a @@ -72,4 +79,4 @@ flutter: # weight: 700 # # For details regarding fonts from package dependencies, - # see https://flutter.io/custom-fonts/#from-packages + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/widget_test.dart b/test/widget_test.dart index 74a9c51..9184af8 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -7,7 +7,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; - import 'package:solitaire_flutter/main.dart'; void main() {