├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ └── main.dart ├── pubspec.lock └── pubspec.yaml ├── images ├── animate-many.gif ├── animate-single.gif ├── board-arrows.png ├── board-orientation.png ├── board.png ├── drag-drop.png └── hints.gif ├── lib ├── components │ ├── animated_piece_wrap.dart │ ├── arrows.dart │ ├── drop_targets.dart │ ├── hints.dart │ ├── hints │ │ └── move_hint.dart │ ├── pieces.dart │ └── squares.dart ├── models │ ├── arrow.dart │ ├── arrow_list.dart │ ├── board_orientation.dart │ ├── chess_state.dart │ ├── drop_indicator_args.dart │ ├── hint_map.dart │ ├── piece_drop_event.dart │ ├── piece_map.dart │ ├── square.dart │ └── square_info.dart └── wp_chessboard.dart ├── pubspec.yaml ├── react_example ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ └── index.html └── src │ ├── App.js │ ├── index.css │ ├── index.js │ └── wp_chessboard │ └── wp_chessboard.jsx └── web_example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── build.sh ├── lib ├── main.dart └── src │ ├── js_interop.dart │ └── js_interop │ ├── dom.dart │ ├── helper.dart │ └── state_manager.dart ├── pubspec.lock ├── pubspec.yaml ├── test └── widget_test.dart └── web ├── favicon.png └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 25 | /pubspec.lock 26 | **/doc/api/ 27 | .dart_tool/ 28 | .packages 29 | build/ 30 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 7e9793dee1b85a243edd0e06cb1658e98b077561 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.4 2 | 3 | * Prevent an exception when "reusing" the controller (fixed by @topse) 4 | 5 | ## 0.0.3 6 | 7 | * Fix static analysis 8 | 9 | * Update Example to allow casteling 10 | 11 | ## 0.0.2 12 | 13 | * Export all important models directly 14 | 15 | ## 0.0.1 16 | 17 | * Initial Release 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2022 Khadim Fall 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 19 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 | USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WP_CHESSBOARD 2 | 3 | ![Chessboard](https://github.com/mono424/wp_chessboard/blob/main/images/board.png?raw=true) 4 | 5 | A very customizable Chessboard with awesomeness already onboard: 6 | 7 | 👇️ Dragable Pieces 8 | 9 | 🎬️ Move Animations 10 | 11 | 🔄 Orientation 12 | 13 | 💡 Hints 14 | 15 | 💡 Arrows 16 | 17 | ## Features 18 | 19 | ### 👇️ Dragable Pieces 20 | 21 | ![Drag-Drop](https://github.com/mono424/wp_chessboard/blob/main/images/drag-drop.png?raw=true) 22 | 23 | ### 🎬️ Piece Animations for Single Moves 24 | 25 | ![Animate-Single](https://github.com/mono424/wp_chessboard/blob/main/images/animate-single.gif?raw=true) 26 | 27 | ### 🎬️ Piece Animations for position changes/reset 28 | 29 | ![Animate-Many](https://github.com/mono424/wp_chessboard/blob/main/images/animate-many.gif?raw=true) 30 | 31 | ### 🔄 Change Orientation 32 | 33 | ![Board-Orientation](https://github.com/mono424/wp_chessboard/blob/main/images/board-orientation.png?raw=true) 34 | 35 | ### 💡 Display Hints 36 | 37 | ![Hints](https://github.com/mono424/wp_chessboard/blob/main/images/hints.gif?raw=true) 38 | 39 | ### 💡 Display Arrows 40 | 41 | ![Board-Arrows](https://github.com/mono424/wp_chessboard/blob/main/images/board-arrows.png?raw=true) 42 | 43 | 44 | ## Usage 45 | 46 | First import the `WPChessboard` widget. 47 | ```dart 48 | import 'package:wp_chessboard/wp_chessboard.dart'; 49 | ``` 50 | 51 | Then, you are ready to use it 52 | 53 | > You can use your own piece set, in the example we will 54 | > use the `chess_vectors_flutter` package. 55 | 56 | ```dart 57 | WPChessboard( 58 | size: size, 59 | orientation: orienatation, 60 | squareBuilder: squareBuilder, 61 | controller: controller, 62 | // Dont pass any onPieceDrop handler to disable drag and drop 63 | onPieceDrop: onPieceDrop, 64 | onPieceTap: onPieceTap, 65 | onPieceStartDrag: onPieceStartDrag, 66 | onEmptyFieldTap: onEmptyFieldTap, 67 | turnTopPlayerPieces: false, 68 | ghostOnDrag: true, 69 | dropIndicator: DropIndicatorArgs( 70 | size: size / 2, 71 | color: Colors.lightBlue.withOpacity(0.24) 72 | ), 73 | pieceMap: PieceMap( 74 | K: (size) => WhiteKing(size: size), 75 | Q: (size) => WhiteQueen(size: size), 76 | B: (size) => WhiteBishop(size: size), 77 | N: (size) => WhiteKnight(size: size), 78 | R: (size) => WhiteRook(size: size), 79 | P: (size) => WhitePawn(size: size), 80 | k: (size) => BlackKing(size: size), 81 | q: (size) => BlackQueen(size: size), 82 | b: (size) => BlackBishop(size: size), 83 | n: (size) => BlackKnight(size: size), 84 | r: (size) => BlackRook(size: size), 85 | p: (size) => BlackPawn(size: size), 86 | ), 87 | ), 88 | ``` 89 | 90 | I know this is very short, for more information checkout the example :). 91 | 92 | ## Additional information 93 | 94 | Every contribution is very welcome. 95 | 96 | Cheers 🥂 97 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 7e9793dee1b85a243edd0e06cb1658e98b077561 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.example.example" 47 | minSdkVersion flutter.minSdkVersion 48 | targetSdkVersion flutter.targetSdkVersion 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1300; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | INFOPLIST_FILE = Runner/Info.plist; 293 | LD_RUNPATH_SEARCH_PATHS = ( 294 | "$(inherited)", 295 | "@executable_path/Frameworks", 296 | ); 297 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 300 | SWIFT_VERSION = 5.0; 301 | VERSIONING_SYSTEM = "apple-generic"; 302 | }; 303 | name = Profile; 304 | }; 305 | 97C147031CF9000F007C117D /* Debug */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_ANALYZER_NONNULL = YES; 310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 315 | CLANG_WARN_BOOL_CONVERSION = YES; 316 | CLANG_WARN_COMMA = YES; 317 | CLANG_WARN_CONSTANT_CONVERSION = YES; 318 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 320 | CLANG_WARN_EMPTY_BODY = YES; 321 | CLANG_WARN_ENUM_CONVERSION = YES; 322 | CLANG_WARN_INFINITE_RECURSION = YES; 323 | CLANG_WARN_INT_CONVERSION = YES; 324 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 325 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 326 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 328 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 329 | CLANG_WARN_STRICT_PROTOTYPES = YES; 330 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 331 | CLANG_WARN_UNREACHABLE_CODE = YES; 332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 334 | COPY_PHASE_STRIP = NO; 335 | DEBUG_INFORMATION_FORMAT = dwarf; 336 | ENABLE_STRICT_OBJC_MSGSEND = YES; 337 | ENABLE_TESTABILITY = YES; 338 | GCC_C_LANGUAGE_STANDARD = gnu99; 339 | GCC_DYNAMIC_NO_PIC = NO; 340 | GCC_NO_COMMON_BLOCKS = YES; 341 | GCC_OPTIMIZATION_LEVEL = 0; 342 | GCC_PREPROCESSOR_DEFINITIONS = ( 343 | "DEBUG=1", 344 | "$(inherited)", 345 | ); 346 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 347 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 348 | GCC_WARN_UNDECLARED_SELECTOR = YES; 349 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 350 | GCC_WARN_UNUSED_FUNCTION = YES; 351 | GCC_WARN_UNUSED_VARIABLE = YES; 352 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 353 | MTL_ENABLE_DEBUG_INFO = YES; 354 | ONLY_ACTIVE_ARCH = YES; 355 | SDKROOT = iphoneos; 356 | TARGETED_DEVICE_FAMILY = "1,2"; 357 | }; 358 | name = Debug; 359 | }; 360 | 97C147041CF9000F007C117D /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_ANALYZER_NONNULL = YES; 365 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 366 | CLANG_CXX_LIBRARY = "libc++"; 367 | CLANG_ENABLE_MODULES = YES; 368 | CLANG_ENABLE_OBJC_ARC = YES; 369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 370 | CLANG_WARN_BOOL_CONVERSION = YES; 371 | CLANG_WARN_COMMA = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 375 | CLANG_WARN_EMPTY_BODY = YES; 376 | CLANG_WARN_ENUM_CONVERSION = YES; 377 | CLANG_WARN_INFINITE_RECURSION = YES; 378 | CLANG_WARN_INT_CONVERSION = YES; 379 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 380 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 381 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 382 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 383 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 384 | CLANG_WARN_STRICT_PROTOTYPES = YES; 385 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 386 | CLANG_WARN_UNREACHABLE_CODE = YES; 387 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 388 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 389 | COPY_PHASE_STRIP = NO; 390 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 391 | ENABLE_NS_ASSERTIONS = NO; 392 | ENABLE_STRICT_OBJC_MSGSEND = YES; 393 | GCC_C_LANGUAGE_STANDARD = gnu99; 394 | GCC_NO_COMMON_BLOCKS = YES; 395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 397 | GCC_WARN_UNDECLARED_SELECTOR = YES; 398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 399 | GCC_WARN_UNUSED_FUNCTION = YES; 400 | GCC_WARN_UNUSED_VARIABLE = YES; 401 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 402 | MTL_ENABLE_DEBUG_INFO = NO; 403 | SDKROOT = iphoneos; 404 | SUPPORTED_PLATFORMS = iphoneos; 405 | SWIFT_COMPILATION_MODE = wholemodule; 406 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 407 | TARGETED_DEVICE_FAMILY = "1,2"; 408 | VALIDATE_PRODUCT = YES; 409 | }; 410 | name = Release; 411 | }; 412 | 97C147061CF9000F007C117D /* Debug */ = { 413 | isa = XCBuildConfiguration; 414 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 415 | buildSettings = { 416 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 417 | CLANG_ENABLE_MODULES = YES; 418 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 419 | ENABLE_BITCODE = NO; 420 | INFOPLIST_FILE = Runner/Info.plist; 421 | LD_RUNPATH_SEARCH_PATHS = ( 422 | "$(inherited)", 423 | "@executable_path/Frameworks", 424 | ); 425 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 426 | PRODUCT_NAME = "$(TARGET_NAME)"; 427 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 428 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 429 | SWIFT_VERSION = 5.0; 430 | VERSIONING_SYSTEM = "apple-generic"; 431 | }; 432 | name = Debug; 433 | }; 434 | 97C147071CF9000F007C117D /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 437 | buildSettings = { 438 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 439 | CLANG_ENABLE_MODULES = YES; 440 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 441 | ENABLE_BITCODE = NO; 442 | INFOPLIST_FILE = Runner/Info.plist; 443 | LD_RUNPATH_SEARCH_PATHS = ( 444 | "$(inherited)", 445 | "@executable_path/Frameworks", 446 | ); 447 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 448 | PRODUCT_NAME = "$(TARGET_NAME)"; 449 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 450 | SWIFT_VERSION = 5.0; 451 | VERSIONING_SYSTEM = "apple-generic"; 452 | }; 453 | name = Release; 454 | }; 455 | /* End XCBuildConfiguration section */ 456 | 457 | /* Begin XCConfigurationList section */ 458 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 97C147031CF9000F007C117D /* Debug */, 462 | 97C147041CF9000F007C117D /* Release */, 463 | 249021D3217E4FDB00AE95B9 /* Profile */, 464 | ); 465 | defaultConfigurationIsVisible = 0; 466 | defaultConfigurationName = Release; 467 | }; 468 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 469 | isa = XCConfigurationList; 470 | buildConfigurations = ( 471 | 97C147061CF9000F007C117D /* Debug */, 472 | 97C147071CF9000F007C117D /* Release */, 473 | 249021D4217E4FDB00AE95B9 /* Profile */, 474 | ); 475 | defaultConfigurationIsVisible = 0; 476 | defaultConfigurationName = Release; 477 | }; 478 | /* End XCConfigurationList section */ 479 | }; 480 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 481 | } 482 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:chess/chess.dart' as Chess; 2 | import 'package:chess_vectors_flutter/chess_vectors_flutter.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:wp_chessboard/wp_chessboard.dart'; 5 | 6 | void main() { 7 | runApp(const MyApp()); 8 | } 9 | 10 | class MyApp extends StatefulWidget { 11 | 12 | const MyApp({Key? key}) : super(key: key); 13 | 14 | @override 15 | State createState() => _MyAppState(); 16 | } 17 | 18 | class _MyAppState extends State { 19 | final controller = WPChessboardController(); 20 | Chess.Chess chess = Chess.Chess(); 21 | List>? lastMove; 22 | 23 | // not working on drop 24 | Widget squareBuilder(SquareInfo info) { 25 | Color fieldColor = (info.index + info.rank) % 2 == 0 ? Colors.grey.shade200 : Colors.grey.shade600; 26 | Color overlayColor = Colors.transparent; 27 | 28 | if (lastMove != null ) { 29 | if (lastMove!.first.first == info.rank && lastMove!.first.last == info.file) { 30 | overlayColor = Colors.blueAccent.shade400.withOpacity(0.4); 31 | } else if (lastMove!.last.first == info.rank && lastMove!.last.last == info.file) { 32 | overlayColor = Colors.blueAccent.shade400.withOpacity(0.87); 33 | } 34 | } 35 | 36 | return Container( 37 | color: fieldColor, 38 | width: info.size, 39 | height: info.size, 40 | child: AnimatedContainer( 41 | color: overlayColor, 42 | width: info.size, 43 | height: info.size, 44 | duration: const Duration(milliseconds: 200), 45 | ) 46 | ); 47 | } 48 | 49 | void onPieceStartDrag(SquareInfo square, String piece) { 50 | showHintFields(square, piece); 51 | } 52 | 53 | void onPieceTap(SquareInfo square, String piece) { 54 | if (controller.hints.key == square.index.toString()) { 55 | controller.setHints(HintMap()); 56 | return; 57 | } 58 | showHintFields(square, piece); 59 | } 60 | 61 | void showHintFields(SquareInfo square, String piece) { 62 | final moves = chess.generate_moves({ 'square': square.toString() }); 63 | final hintMap = HintMap(key: square.index.toString()); 64 | for (var move in moves) { 65 | String to = move.toAlgebraic; 66 | int rank = to.codeUnitAt(1) - "1".codeUnitAt(0) + 1; 67 | int file = to.codeUnitAt(0) - "a".codeUnitAt(0) + 1; 68 | 69 | hintMap.set(rank, file, (size) => MoveHint( 70 | size: size, 71 | onPressed: () => doMove(move), 72 | )); 73 | } 74 | controller.setHints(hintMap); 75 | } 76 | 77 | void onEmptyFieldTap(SquareInfo square) { 78 | controller.setHints(HintMap()); 79 | } 80 | 81 | void onPieceDrop(PieceDropEvent event) { 82 | chess.move({ "from": event.from.toString(), "to": event.to.toString() }); 83 | 84 | lastMove = [ 85 | [ event.from.rank, event.from.file ], 86 | [ event.to.rank, event.to.file ] 87 | ]; 88 | 89 | update(animated: false); 90 | } 91 | 92 | void doMove(Chess.Move move) { 93 | chess.move(move); 94 | 95 | int rankFrom = move.fromAlgebraic.codeUnitAt(1) - "1".codeUnitAt(0) + 1; 96 | int fileFrom = move.fromAlgebraic.codeUnitAt(0) - "a".codeUnitAt(0) + 1; 97 | int rankTo = move.toAlgebraic.codeUnitAt(1) - "1".codeUnitAt(0) + 1; 98 | int fileTo = move.toAlgebraic.codeUnitAt(0) - "a".codeUnitAt(0) + 1; 99 | lastMove = [ 100 | [ rankFrom, fileFrom ], 101 | [ rankTo, fileTo ] 102 | ]; 103 | 104 | update(); 105 | } 106 | void setDefaultFen() { 107 | setState(() { 108 | chess = Chess.Chess.fromFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); 109 | }); 110 | update(); 111 | } 112 | 113 | void setRandomFen() { 114 | setState(() { 115 | chess = Chess.Chess.fromFEN("3bK3/4B1P1/3p2N1/1rp3P1/2p2p2/p3n3/P5k1/6q1 w - - 0 1"); 116 | }); 117 | update(); 118 | } 119 | 120 | void update({bool animated = true}) { 121 | controller.setFen(chess.fen, animation: animated); 122 | } 123 | 124 | void addArrows() { 125 | controller.setArrows([ 126 | Arrow( 127 | from: SquareLocation.fromString("b1"), 128 | to: SquareLocation.fromString("c3"), 129 | ), 130 | Arrow( 131 | from: SquareLocation.fromString("g1"), 132 | to: SquareLocation.fromString("f3"), 133 | color: Colors.red 134 | ) 135 | ]); 136 | } 137 | 138 | void removeArrows() { 139 | controller.setArrows([]); 140 | } 141 | 142 | BoardOrientation orienatation = BoardOrientation.white; 143 | void toggleArrows() { 144 | setState(() { 145 | if (orienatation == BoardOrientation.white) { 146 | orienatation = BoardOrientation.black; 147 | } else { 148 | orienatation = BoardOrientation.white; 149 | } 150 | }); 151 | } 152 | 153 | @override 154 | Widget build(BuildContext context) { 155 | return MaterialApp( 156 | title: 'WPChessboard Demo', 157 | home: Scaffold( 158 | body: Builder(builder: (context) { 159 | final double size = MediaQuery.of(context).size.shortestSide; 160 | return Column( 161 | mainAxisAlignment: MainAxisAlignment.center, 162 | children: [ 163 | WPChessboard( 164 | size: size, 165 | orientation: orienatation, 166 | squareBuilder: squareBuilder, 167 | controller: controller, 168 | // Dont pass any onPieceDrop handler to disable drag and drop 169 | onPieceDrop: onPieceDrop, 170 | onPieceTap: onPieceTap, 171 | onPieceStartDrag: onPieceStartDrag, 172 | onEmptyFieldTap: onEmptyFieldTap, 173 | turnTopPlayerPieces: false, 174 | ghostOnDrag: true, 175 | dropIndicator: DropIndicatorArgs( 176 | size: size / 2, 177 | color: Colors.lightBlue.withOpacity(0.24) 178 | ), 179 | pieceMap: PieceMap( 180 | K: (size) => WhiteKing(size: size), 181 | Q: (size) => WhiteQueen(size: size), 182 | B: (size) => WhiteBishop(size: size), 183 | N: (size) => WhiteKnight(size: size), 184 | R: (size) => WhiteRook(size: size), 185 | P: (size) => WhitePawn(size: size), 186 | k: (size) => BlackKing(size: size), 187 | q: (size) => BlackQueen(size: size), 188 | b: (size) => BlackBishop(size: size), 189 | n: (size) => BlackKnight(size: size), 190 | r: (size) => BlackRook(size: size), 191 | p: (size) => BlackPawn(size: size), 192 | ), 193 | ), 194 | const SizedBox(height: 24), 195 | TextButton( 196 | onPressed: setDefaultFen, 197 | child: const Text("Set default Fen"), 198 | ), 199 | TextButton( 200 | onPressed: setRandomFen, 201 | child: const Text("Set random Fen"), 202 | ), 203 | TextButton( 204 | onPressed: addArrows, 205 | child: const Text("Add Arrows"), 206 | ), 207 | TextButton( 208 | onPressed: removeArrows, 209 | child: const Text("Remove Arrows"), 210 | ), 211 | TextButton( 212 | onPressed: toggleArrows, 213 | child: const Text("Change Orientation"), 214 | ) 215 | ], 216 | ); 217 | }, 218 | ) 219 | ) 220 | ); 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.2" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.2.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | chess: 33 | dependency: "direct main" 34 | description: 35 | name: chess 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "0.7.0" 39 | chess_vectors_flutter: 40 | dependency: "direct main" 41 | description: 42 | name: chess_vectors_flutter 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.0.16" 46 | clock: 47 | dependency: transitive 48 | description: 49 | name: clock 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.1.0" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.16.0" 60 | cupertino_icons: 61 | dependency: "direct main" 62 | description: 63 | name: cupertino_icons 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.0.4" 67 | fake_async: 68 | dependency: transitive 69 | description: 70 | name: fake_async 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.3.0" 74 | flutter: 75 | dependency: "direct main" 76 | description: flutter 77 | source: sdk 78 | version: "0.0.0" 79 | flutter_lints: 80 | dependency: "direct dev" 81 | description: 82 | name: flutter_lints 83 | url: "https://pub.dartlang.org" 84 | source: hosted 85 | version: "1.0.4" 86 | flutter_test: 87 | dependency: "direct dev" 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | lints: 92 | dependency: transitive 93 | description: 94 | name: lints 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.0.1" 98 | matcher: 99 | dependency: transitive 100 | description: 101 | name: matcher 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "0.12.11" 105 | material_color_utilities: 106 | dependency: transitive 107 | description: 108 | name: material_color_utilities 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "0.1.4" 112 | meta: 113 | dependency: transitive 114 | description: 115 | name: meta 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "1.7.0" 119 | path: 120 | dependency: transitive 121 | description: 122 | name: path 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "1.8.1" 126 | quiver: 127 | dependency: transitive 128 | description: 129 | name: quiver 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "3.0.1+1" 133 | sky_engine: 134 | dependency: transitive 135 | description: flutter 136 | source: sdk 137 | version: "0.0.99" 138 | source_span: 139 | dependency: transitive 140 | description: 141 | name: source_span 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.8.2" 145 | stack_trace: 146 | dependency: transitive 147 | description: 148 | name: stack_trace 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.10.0" 152 | stream_channel: 153 | dependency: transitive 154 | description: 155 | name: stream_channel 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "2.1.0" 159 | string_scanner: 160 | dependency: transitive 161 | description: 162 | name: string_scanner 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.1.0" 166 | term_glyph: 167 | dependency: transitive 168 | description: 169 | name: term_glyph 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.2.0" 173 | test_api: 174 | dependency: transitive 175 | description: 176 | name: test_api 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "0.4.9" 180 | tuple: 181 | dependency: transitive 182 | description: 183 | name: tuple 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.0.0" 187 | vector_math: 188 | dependency: transitive 189 | description: 190 | name: vector_math 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "2.1.2" 194 | wp_chessboard: 195 | dependency: "direct main" 196 | description: 197 | path: ".." 198 | relative: true 199 | source: path 200 | version: "0.0.3" 201 | sdks: 202 | dart: ">=2.17.0-0 <3.0.0" 203 | flutter: ">=1.17.0" 204 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.16.1 <3.0.0" 22 | 23 | # Dependencies specify other packages that your package needs in order to work. 24 | # To automatically upgrade your package dependencies to the latest versions 25 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 26 | # dependencies can be manually updated by changing the version numbers below to 27 | # the latest version available on pub.dev. To see which dependencies have newer 28 | # versions available, run `flutter pub outdated`. 29 | dependencies: 30 | flutter: 31 | sdk: flutter 32 | wp_chessboard: 33 | path: "../" 34 | chess_vectors_flutter: ^1.0.18 35 | chess: ^0.7.0 36 | 37 | 38 | # The following adds the Cupertino Icons font to your application. 39 | # Use with the CupertinoIcons class for iOS style icons. 40 | cupertino_icons: ^1.0.2 41 | 42 | dev_dependencies: 43 | flutter_test: 44 | sdk: flutter 45 | 46 | # The "flutter_lints" package below contains a set of recommended lints to 47 | # encourage good coding practices. The lint set provided by the package is 48 | # activated in the `analysis_options.yaml` file located at the root of your 49 | # package. See that file for information about deactivating specific lint 50 | # rules and activating additional ones. 51 | flutter_lints: ^1.0.0 52 | 53 | # For information on the generic Dart part of this file, see the 54 | # following page: https://dart.dev/tools/pub/pubspec 55 | 56 | # The following section is specific to Flutter. 57 | flutter: 58 | 59 | # The following line ensures that the Material Icons font is 60 | # included with your application, so that you can use the icons in 61 | # the material Icons class. 62 | uses-material-design: true 63 | 64 | # To add assets to your application, add an assets section, like this: 65 | # assets: 66 | # - images/a_dot_burr.jpeg 67 | # - images/a_dot_ham.jpeg 68 | 69 | # An image asset can refer to one or more resolution-specific "variants", see 70 | # https://flutter.dev/assets-and-images/#resolution-aware. 71 | 72 | # For details regarding adding assets from package dependencies, see 73 | # https://flutter.dev/assets-and-images/#from-packages 74 | 75 | # To add custom fonts to your application, add a fonts section here, 76 | # in this "flutter" section. Each entry in this list should have a 77 | # "family" key with the font family name, and a "fonts" key with a 78 | # list giving the asset and other descriptors for the font. For 79 | # example: 80 | # fonts: 81 | # - family: Schyler 82 | # fonts: 83 | # - asset: fonts/Schyler-Regular.ttf 84 | # - asset: fonts/Schyler-Italic.ttf 85 | # style: italic 86 | # - family: Trajan Pro 87 | # fonts: 88 | # - asset: fonts/TrajanPro.ttf 89 | # - asset: fonts/TrajanPro_Bold.ttf 90 | # weight: 700 91 | # 92 | # For details regarding fonts from package dependencies, 93 | # see https://flutter.dev/custom-fonts/#from-packages 94 | -------------------------------------------------------------------------------- /images/animate-many.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/animate-many.gif -------------------------------------------------------------------------------- /images/animate-single.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/animate-single.gif -------------------------------------------------------------------------------- /images/board-arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/board-arrows.png -------------------------------------------------------------------------------- /images/board-orientation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/board-orientation.png -------------------------------------------------------------------------------- /images/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/board.png -------------------------------------------------------------------------------- /images/drag-drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/drag-drop.png -------------------------------------------------------------------------------- /images/hints.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/images/hints.gif -------------------------------------------------------------------------------- /lib/components/animated_piece_wrap.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:wp_chessboard/models/chess_state.dart'; 5 | 6 | class AnimatedPieceWrap extends StatefulWidget { 7 | final Widget child; 8 | final StateEntry stateEntry; 9 | final double squareSize; 10 | final bool animated; 11 | 12 | const AnimatedPieceWrap({Key? key, required this.child, required this.stateEntry, required this.squareSize, required this.animated}) : super(key: key); 13 | 14 | @override 15 | State createState() => _AnimatedPieceWrapState(); 16 | } 17 | 18 | class _AnimatedPieceWrapState extends State { 19 | int rank = 0; 20 | int file = 0; 21 | 22 | @override 23 | void initState() { 24 | if (widget.animated) { 25 | SquarePosition? pos = widget.stateEntry.lastPosition(); 26 | if (pos != null) { 27 | rank = pos.rank; 28 | file = pos.file; 29 | } else { 30 | rank = widget.stateEntry.position.rank; 31 | file = widget.stateEntry.position.file; 32 | } 33 | WidgetsBinding.instance!.addPostFrameCallback((_) { 34 | setState(() { 35 | rank = widget.stateEntry.position.rank; 36 | file = widget.stateEntry.position.file; 37 | }); 38 | }); 39 | } else { 40 | rank = widget.stateEntry.position.rank; 41 | file = widget.stateEntry.position.file; 42 | } 43 | 44 | super.initState(); 45 | } 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | double left = (file) * widget.squareSize; 50 | double bottom = (rank) * widget.squareSize; 51 | 52 | return AnimatedPositioned( 53 | key: Key(widget.stateEntry.getKey() + "_a"), 54 | curve: Curves.easeInOut, 55 | duration: const Duration(milliseconds: 200), 56 | bottom: bottom, 57 | left: left, 58 | child: widget.child 59 | ); 60 | } 61 | } -------------------------------------------------------------------------------- /lib/components/arrows.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'dart:math'; 4 | import 'dart:ui'; 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:wp_chessboard/models/arrow.dart'; 8 | import 'package:wp_chessboard/models/square.dart'; 9 | 10 | class Arrows extends StatelessWidget { 11 | final double size; 12 | final List arrows; 13 | 14 | const Arrows({Key? key, required this.size, required this.arrows}) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return IgnorePointer( 19 | child: CustomPaint( 20 | painter: ArrowPainter(arrows, size), 21 | size: Size(size, size), 22 | ) 23 | ); 24 | } 25 | 26 | } 27 | 28 | class ArrowPainter extends CustomPainter { 29 | final double size; 30 | final List arrows; 31 | 32 | ArrowPainter(this.arrows, this.size); 33 | 34 | Offset getPosition(SquareLocation loc) { 35 | double squareSize = size / 8; 36 | 37 | return Offset( 38 | loc.fileIndex * squareSize + (squareSize / 2), 39 | size - loc.rankIndex * squareSize - (squareSize / 2), 40 | ); 41 | } 42 | 43 | @override 44 | void paint(Canvas canvas, Size size) { 45 | for (Arrow arrow in arrows) { 46 | 47 | double squareWidth = size.width / 8; 48 | double arrowHeadLen = squareWidth * 0.24; 49 | PointMode pointMode = PointMode.polygon; 50 | Offset from = getPosition(arrow.from); 51 | Offset to = getPosition(arrow.to); 52 | ParagraphBuilder labelBuilder = ParagraphBuilder(ParagraphStyle( 53 | textAlign: TextAlign.center, 54 | fontSize: 12, 55 | fontWeight: FontWeight.bold, 56 | )); 57 | 58 | // Line 59 | double angle = atan2(to.dy - from.dy, to.dx - from.dx); 60 | Paint linePaint = Paint() 61 | ..color = arrow.color 62 | ..strokeWidth = 4 63 | ..strokeCap = StrokeCap.round; 64 | canvas.drawPoints(pointMode, [from, to], linePaint); 65 | 66 | // Arrow 67 | canvas.drawPoints(pointMode, [Offset(to.dx - arrowHeadLen * cos(angle - pi / 6), to.dy - arrowHeadLen * sin(angle - pi / 6)), to], linePaint); 68 | canvas.drawPoints(pointMode, [Offset(to.dx - arrowHeadLen * cos(angle + pi / 6), to.dy - arrowHeadLen * sin(angle + pi / 6)), to], linePaint); 69 | 70 | // Circle 71 | // Paint circlePaint1 = Paint()..color = arrow.color; 72 | // Paint circlePaint2 = Paint()..color = Colors.white; 73 | // canvas.drawCircle(to, 14, circlePaint1); 74 | // canvas.drawCircle(to, 10, circlePaint2); 75 | 76 | canvas.drawParagraph( 77 | labelBuilder.build() 78 | ..layout(ParagraphConstraints(width: squareWidth)), 79 | Offset(to.dx - (squareWidth / 2), to.dy - 6)); 80 | } 81 | } 82 | 83 | @override 84 | bool shouldRepaint(covariant CustomPainter oldDelegate) { 85 | return true; 86 | } 87 | } -------------------------------------------------------------------------------- /lib/components/drop_targets.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:wp_chessboard/models/drop_indicator_args.dart'; 5 | import 'package:wp_chessboard/models/piece_drop_event.dart'; 6 | import 'package:wp_chessboard/models/square_info.dart'; 7 | 8 | class DropTargets extends StatefulWidget { 9 | final double size; 10 | final DropIndicatorArgs? dropIndicator; 11 | final void Function(PieceDropEvent)? onPieceDrop; 12 | 13 | 14 | const DropTargets({Key? key, required this.size, this.onPieceDrop, this.dropIndicator}) : super(key: key); 15 | 16 | @override 17 | State createState() => _DropTargetsState(); 18 | } 19 | 20 | class _DropTargetsState extends State { 21 | SquareInfo? dropHover; 22 | 23 | void onMove(SquareInfo square, SquareInfo data) { 24 | if (data.index == square.index) { 25 | if (dropHover == null) return; 26 | setState(() { 27 | dropHover = null; 28 | }); 29 | return; 30 | } 31 | 32 | if (dropHover == null || dropHover!.index != square.index) { 33 | setState(() { 34 | dropHover = square; 35 | }); 36 | } 37 | } 38 | 39 | void onLeave(SquareInfo square) { 40 | if (dropHover != null && dropHover!.index == square.index) { 41 | setState(() { 42 | dropHover = null; 43 | }); 44 | } 45 | } 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | double squareSize = widget.size / 8; 50 | 51 | return Stack( 52 | children: [ 53 | 54 | Builder( 55 | builder: (context) { 56 | if (widget.dropIndicator == null || dropHover == null) return const SizedBox(); 57 | 58 | double left = (dropHover!.file - 1) * squareSize + squareSize / 2 - (widget.dropIndicator!.size / 2); 59 | double bottom = (dropHover!.rank - 1) * squareSize + squareSize / 2 - (widget.dropIndicator!.size / 2); 60 | 61 | return Positioned( 62 | bottom: bottom, 63 | left: left, 64 | child: IgnorePointer( 65 | child: Container( 66 | width: widget.dropIndicator!.size, 67 | height: widget.dropIndicator!.size, 68 | decoration: BoxDecoration( 69 | borderRadius: widget.dropIndicator!.radius, 70 | color: widget.dropIndicator!.color, 71 | ), 72 | ), 73 | ) 74 | ); 75 | }, 76 | ), 77 | 78 | ...(List.generate(64, (i) => i + 1)).map( 79 | (i) { 80 | SquareInfo info = SquareInfo(i - 1, squareSize); 81 | 82 | double left = (info.file - 1) * squareSize; 83 | double bottom = (info.rank - 1) * squareSize; 84 | 85 | return Positioned( 86 | bottom: bottom, 87 | left: left, 88 | child: DragTarget( 89 | onWillAccept: (data) { 90 | return data != null && data.index != info.index; 91 | }, 92 | onAccept: (data) { 93 | onLeave(info); 94 | if (widget.onPieceDrop != null) { 95 | widget.onPieceDrop!(PieceDropEvent(data, info)); 96 | } 97 | }, 98 | onMove: (data) => onMove(info, data.data), 99 | onLeave: (data) => onLeave(info), 100 | builder: ( 101 | (context, candidateData, rejectedData) => SizedBox(width: squareSize, height: squareSize) 102 | ), 103 | ), 104 | ); 105 | } 106 | ).toList(), 107 | 108 | ] 109 | ); 110 | } 111 | } -------------------------------------------------------------------------------- /lib/components/hints.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:wp_chessboard/models/hint_map.dart'; 5 | import 'package:wp_chessboard/models/square_info.dart'; 6 | 7 | class Hints extends StatelessWidget { 8 | final double size; 9 | final HintMap hints; 10 | 11 | const Hints({Key? key, required this.size, required this.hints}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | double squareSize = size / 8; 16 | 17 | return Stack( 18 | children: (List.generate(64, (i) => i + 1)).map( 19 | (i) { 20 | SquareInfo info = SquareInfo(i - 1, squareSize); 21 | 22 | double left = (info.file - 1) * squareSize; 23 | double bottom = (info.rank - 1) * squareSize; 24 | 25 | HintBuilder? hint = hints.getHint(info.rank, info.file); 26 | 27 | return Positioned( 28 | bottom: bottom, 29 | left: left, 30 | child: hint != null ? hint(squareSize) : const SizedBox(), 31 | ); 32 | } 33 | ).toList(), 34 | ); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /lib/components/hints/move_hint.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class MoveHint extends StatelessWidget { 6 | final double size; 7 | final Color color; 8 | final VoidCallback? onPressed; 9 | 10 | const MoveHint({Key? key, required this.size, this.color = Colors.tealAccent, this.onPressed}) : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | double hintSize = size * 0.2; 15 | 16 | return GestureDetector( 17 | onTapDown: onPressed != null ? (_) => onPressed!() : null, 18 | child: Container( 19 | width: size, 20 | height: size, 21 | color: Colors.transparent, 22 | child: Column( 23 | mainAxisAlignment: MainAxisAlignment.center, 24 | crossAxisAlignment: CrossAxisAlignment.center, 25 | children: [ 26 | Container( 27 | width: hintSize, 28 | height: hintSize, 29 | decoration: BoxDecoration( 30 | color: color, 31 | borderRadius: BorderRadius.circular(hintSize) 32 | ), 33 | ) 34 | ], 35 | ), 36 | ) 37 | ); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /lib/components/pieces.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:wp_chessboard/components/animated_piece_wrap.dart'; 5 | import 'package:wp_chessboard/models/board_orientation.dart'; 6 | import 'package:wp_chessboard/models/chess_state.dart'; 7 | import 'package:wp_chessboard/models/piece_map.dart'; 8 | import 'package:wp_chessboard/models/square_info.dart'; 9 | 10 | class Pieces extends StatelessWidget { 11 | final double size; 12 | final PieceMap pieceMap; 13 | final ChessState state; 14 | final BoardOrientation orientation; 15 | final void Function(SquareInfo square, String piece)? onPieceTap; 16 | final void Function(SquareInfo square, String piece)? onPieceStartDrag; 17 | final void Function(SquareInfo square)? onEmptyFieldTap; 18 | final bool animated; 19 | final bool disableDrag; 20 | final bool ghostOnDrag; 21 | final bool turnTopPlayerPieces; 22 | 23 | const Pieces({Key? key, required this.size, required this.pieceMap, required this.state, this.onPieceTap, this.onEmptyFieldTap, this.onPieceStartDrag, required this.animated, required this.orientation, required this.disableDrag, required this.ghostOnDrag, required this.turnTopPlayerPieces}) : super(key: key); 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | double squareSize = size / 8; 28 | 29 | return Stack( 30 | children: (List.generate(64, (i) => i + 1)).map( 31 | (i) { 32 | SquareInfo info = SquareInfo(i - 1, squareSize); 33 | StateEntry pieceEntry = state.getEntry(info.rank, info.file); 34 | 35 | double left = (info.file - 1) * squareSize; 36 | double bottom = (info.rank - 1) * squareSize; 37 | 38 | if (pieceEntry.piece == "") { 39 | return Positioned( 40 | key: Key("piece_" + info.toString() + "_none"), 41 | bottom: bottom, 42 | left: left, 43 | child: GestureDetector( 44 | onTapDown: onEmptyFieldTap != null ? (_) => onEmptyFieldTap!(info) : null, 45 | child: Container( 46 | color: Colors.transparent, 47 | width: squareSize, 48 | height: squareSize, 49 | ) 50 | ), 51 | ); 52 | } 53 | 54 | Widget pieceWidget = pieceMap.get(pieceEntry.piece)(squareSize); 55 | 56 | bool isBlackPiece = pieceEntry.piece.toLowerCase() == pieceEntry.piece; 57 | bool shouldTurnPiece = turnTopPlayerPieces && ( 58 | (orientation == BoardOrientation.black && !isBlackPiece) 59 | || (orientation == BoardOrientation.white && isBlackPiece) 60 | ); 61 | 62 | return AnimatedPieceWrap( 63 | key: Key(pieceEntry.getKey()), 64 | squareSize: squareSize, 65 | stateEntry: pieceEntry, 66 | animated: animated, 67 | child: GestureDetector( 68 | onTapDown: onPieceTap != null ? (_) => onPieceTap!(info, pieceEntry.piece) : null, 69 | child: RotatedBox( 70 | quarterTurns: ((orientation == BoardOrientation.black) ? 2 : 0) + (shouldTurnPiece ? 2 : 0), 71 | child: disableDrag ? pieceWidget : Draggable( 72 | onDragStarted: onPieceStartDrag != null ? () => onPieceStartDrag!(info, pieceEntry.piece) : null, 73 | childWhenDragging: ghostOnDrag ? Opacity(opacity: 0.2, child: pieceWidget) : const SizedBox(), 74 | data: info, 75 | feedback: pieceWidget, 76 | child: pieceWidget, 77 | ) 78 | ), 79 | ), 80 | ); 81 | } 82 | ).toList(), 83 | ); 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /lib/components/squares.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:wp_chessboard/models/square_info.dart'; 5 | 6 | class Squares extends StatelessWidget { 7 | final double size; 8 | final Widget Function(SquareInfo) squareBuilder; 9 | 10 | const Squares({Key? key, required this.size, required this.squareBuilder}) : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | double squareSize = size / 8; 15 | 16 | return Stack( 17 | children: (List.generate(64, (i) => i + 1)).map( 18 | (i) { 19 | SquareInfo info = SquareInfo(i - 1, squareSize); 20 | 21 | double left = (info.file - 1) * squareSize; 22 | double bottom = (info.rank - 1) * squareSize; 23 | 24 | return Positioned( 25 | bottom: bottom, 26 | left: left, 27 | child: squareBuilder(info) 28 | ); 29 | } 30 | ).toList(), 31 | ); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /lib/models/arrow.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:wp_chessboard/models/square.dart'; 3 | 4 | class Arrow { 5 | final SquareLocation from; 6 | final SquareLocation to; 7 | final Color color; 8 | 9 | Arrow({required this.from, required this.to, this.color = Colors.green}); 10 | } -------------------------------------------------------------------------------- /lib/models/arrow_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:wp_chessboard/models/arrow.dart'; 2 | 3 | class ArrowList { 4 | static int _lastId = 0; 5 | late int _id; 6 | 7 | final List value; 8 | 9 | int get id { 10 | return _id; 11 | } 12 | 13 | ArrowList(this.value) { 14 | _updateId(); 15 | } 16 | 17 | void _updateId() { 18 | _id = _lastId++; 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /lib/models/board_orientation.dart: -------------------------------------------------------------------------------- 1 | enum BoardOrientation { 2 | white, black 3 | } -------------------------------------------------------------------------------- /lib/models/chess_state.dart: -------------------------------------------------------------------------------- 1 | enum StateEntryDelta { 2 | removed, none, added, replaced 3 | } 4 | 5 | class StateEntry { 6 | final String piece; 7 | final SquarePosition position; 8 | final ChessState state; 9 | 10 | StateEntry(this.piece, this.position, this.state); 11 | 12 | SquarePosition? lastPosition() { 13 | StateEntryDelta delta = state.getDelta(piece, state.last?.board[position.rank]?[position.file]?.piece ?? ""); 14 | return delta == StateEntryDelta.added || delta == StateEntryDelta.replaced ? state.findFrom(piece) : null; 15 | } 16 | 17 | String getKey() { 18 | return "ste_" + position.toString() + "_" + piece; 19 | } 20 | } 21 | 22 | class SquarePosition { 23 | final int rank; 24 | final int file; 25 | 26 | SquarePosition(this.rank, this.file); 27 | 28 | @override 29 | String toString() { 30 | return rank.toString() + file.toString(); 31 | } 32 | } 33 | 34 | class ChessState { 35 | static int zero = "0".codeUnitAt(0); 36 | static int nine = "9".codeUnitAt(0); 37 | static int space = " ".codeUnitAt(0); 38 | 39 | final ChessState? last; 40 | final String fen; 41 | late final Map> board; 42 | 43 | ChessState(this.fen, { this.last }) { 44 | Map> _board = {}; 45 | 46 | if (fen == "") { 47 | for (var i = 0; i < 8; i++) { 48 | _board[i] = {}; 49 | for (var j = 0; j < 8; j++) { 50 | _board[i]![j] = StateEntry("", SquarePosition(i, j), this); 51 | } 52 | } 53 | } else { 54 | int rank = 0; 55 | for (var fenRank in fen.split("/")) { 56 | int file = 0; 57 | int currRank = 7 - rank; 58 | _board[currRank] = {}; 59 | 60 | for (var i = 0; i < fenRank.length; i++) { 61 | int piece = fenRank.codeUnitAt(i); 62 | if (piece == space) break; 63 | 64 | if (piece >= zero && piece <= nine) { 65 | for (int j = 0; j < piece-zero; j++) { 66 | _board[currRank]![file] = StateEntry("", SquarePosition(currRank, file), this); 67 | file++; 68 | } 69 | } else { 70 | String pieceNotation = String.fromCharCode(piece); 71 | _board[currRank]![file] = StateEntry(pieceNotation, SquarePosition(currRank, file), this); 72 | file++; 73 | } 74 | } 75 | rank++; 76 | } 77 | } 78 | 79 | board = _board; 80 | } 81 | 82 | StateEntryDelta getDelta(String piece, String lastPiece) { 83 | if (piece == lastPiece) return StateEntryDelta.none; 84 | if (lastPiece == "") return StateEntryDelta.added; 85 | if (piece == "") return StateEntryDelta.removed; 86 | return StateEntryDelta.replaced; 87 | } 88 | 89 | StateEntry getEntry(int rank, int file) { 90 | return board[rank-1]![file-1]!; 91 | } 92 | 93 | SquarePosition? findFrom(String piece) { 94 | if (last == null) { 95 | return null; 96 | } 97 | 98 | for (var rank in board.entries) { 99 | for (var file in rank.value.entries) { 100 | if (file.value.piece == "" && last!.board[rank.key]![file.key]!.piece == piece) { 101 | return SquarePosition(rank.key, file.key); 102 | } 103 | } 104 | } 105 | return null; 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /lib/models/drop_indicator_args.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class DropIndicatorArgs { 4 | final double size; 5 | final Color color; 6 | final BorderRadius radius; 7 | 8 | DropIndicatorArgs({required this.size, required this.color, radius}) : radius = radius ?? BorderRadius.circular(size); 9 | } -------------------------------------------------------------------------------- /lib/models/hint_map.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | typedef HintBuilder = Widget Function(double size); 4 | 5 | class HintMap { 6 | static int _lastId = 0; 7 | final String key; 8 | late int _id; 9 | Map> board = {}; 10 | 11 | int get id { 12 | return _id; 13 | } 14 | 15 | HintMap({ this.key = "" }) { 16 | _updateId(); 17 | for (var i = 0; i < 8; i++) { 18 | board[i] = {}; 19 | for (var j = 0; j < 8; j++) { 20 | board[i]![j] = null; 21 | } 22 | } 23 | } 24 | 25 | void _updateId() { 26 | _id = _lastId++; 27 | } 28 | 29 | HintMap set(int rank, int file, HintBuilder? widget) { 30 | board[rank-1]![file-1] = widget; 31 | return this; 32 | } 33 | 34 | HintBuilder? getHint(int rank, int file) { 35 | return board[rank-1]![file-1]; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /lib/models/piece_drop_event.dart: -------------------------------------------------------------------------------- 1 | import 'package:wp_chessboard/models/square_info.dart'; 2 | 3 | class PieceDropEvent { 4 | final SquareInfo from; 5 | final SquareInfo to; 6 | 7 | PieceDropEvent(this.from, this.to); 8 | } -------------------------------------------------------------------------------- /lib/models/piece_map.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | typedef PieceBuilder = Widget Function(double size); 4 | 5 | class PieceMap { 6 | final PieceBuilder K; 7 | final PieceBuilder Q; 8 | final PieceBuilder B; 9 | final PieceBuilder N; 10 | final PieceBuilder R; 11 | final PieceBuilder P; 12 | 13 | final PieceBuilder k; 14 | final PieceBuilder q; 15 | final PieceBuilder b; 16 | final PieceBuilder n; 17 | final PieceBuilder r; 18 | final PieceBuilder p; 19 | 20 | PieceMap({required this.K, required this.Q, required this.B, required this.N, required this.R, required this.P, required this.k, required this.q, required this.b, required this.n, required this.r, required this.p}); 21 | 22 | PieceBuilder get(String notation) { 23 | switch (notation) { 24 | case 'K': 25 | return K; 26 | case 'Q': 27 | return Q; 28 | case 'B': 29 | return B; 30 | case 'N': 31 | return N; 32 | case 'R': 33 | return R; 34 | case 'P': 35 | return P; 36 | case 'k': 37 | return k; 38 | case 'q': 39 | return q; 40 | case 'b': 41 | return b; 42 | case 'n': 43 | return n; 44 | case 'r': 45 | return r; 46 | case 'p': 47 | return p; 48 | default: 49 | throw Exception("Invalid piece notation: '" + notation + "'."); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /lib/models/square.dart: -------------------------------------------------------------------------------- 1 | class SquareLocation { 2 | final int rank; 3 | final int file; 4 | 5 | SquareLocation(this.rank, this.file); 6 | 7 | SquareLocation.fromString(String square) : 8 | rank = square.codeUnitAt(1) - "1".codeUnitAt(0) + 1, 9 | file = square.codeUnitAt(0) - "a".codeUnitAt(0) + 1; 10 | 11 | int get rankIndex { 12 | return rank - 1; 13 | } 14 | 15 | int get fileIndex { 16 | return file - 1; 17 | } 18 | } -------------------------------------------------------------------------------- /lib/models/square_info.dart: -------------------------------------------------------------------------------- 1 | class SquareInfo { 2 | final int index; 3 | final int file; 4 | final int rank; 5 | final double size; 6 | 7 | SquareInfo(this.index, this.size) : file = ((index % 8) + 1), rank = ((index / 8).floor() + 1); 8 | 9 | @override 10 | String toString() { 11 | return String.fromCharCode("a".codeUnitAt(0) + (file - 1)) + rank.toString(); 12 | } 13 | } -------------------------------------------------------------------------------- /lib/wp_chessboard.dart: -------------------------------------------------------------------------------- 1 | library wp_chessboard; 2 | 3 | export 'package:wp_chessboard/models/piece_map.dart'; 4 | export 'package:wp_chessboard/models/arrow_list.dart'; 5 | export 'package:wp_chessboard/models/arrow.dart'; 6 | export 'package:wp_chessboard/models/square_info.dart'; 7 | export 'package:wp_chessboard/models/piece_drop_event.dart'; 8 | export 'package:wp_chessboard/models/board_orientation.dart'; 9 | export 'package:wp_chessboard/models/hint_map.dart'; 10 | export 'package:wp_chessboard/models/hint_map.dart'; 11 | export 'package:wp_chessboard/models/drop_indicator_args.dart'; 12 | export 'package:wp_chessboard/models/square.dart'; 13 | export 'package:wp_chessboard/components/hints/move_hint.dart'; 14 | 15 | import 'package:flutter/material.dart'; 16 | import 'package:wp_chessboard/components/arrows.dart'; 17 | import 'package:wp_chessboard/components/drop_targets.dart'; 18 | import 'package:wp_chessboard/components/hints.dart'; 19 | import 'package:wp_chessboard/components/pieces.dart'; 20 | import 'package:wp_chessboard/components/squares.dart'; 21 | import 'package:wp_chessboard/models/arrow.dart'; 22 | import 'package:wp_chessboard/models/arrow_list.dart'; 23 | import 'package:wp_chessboard/models/board_orientation.dart'; 24 | import 'package:wp_chessboard/models/chess_state.dart'; 25 | import 'package:wp_chessboard/models/drop_indicator_args.dart'; 26 | import 'package:wp_chessboard/models/hint_map.dart'; 27 | import 'package:wp_chessboard/models/piece_drop_event.dart'; 28 | import 'package:wp_chessboard/models/piece_map.dart'; 29 | import 'package:wp_chessboard/models/square_info.dart'; 30 | 31 | class WPChessboard extends StatefulWidget { 32 | final double size; 33 | final Widget Function(SquareInfo) squareBuilder; 34 | final PieceMap pieceMap; 35 | final BoardOrientation orientation; 36 | final WPChessboardController controller; 37 | final void Function(SquareInfo square, String piece)? onPieceTap; 38 | final void Function(SquareInfo square, String piece)? onPieceStartDrag; 39 | final void Function(SquareInfo square)? onEmptyFieldTap; 40 | final void Function(PieceDropEvent)? onPieceDrop; 41 | final bool ghostOnDrag; 42 | final bool turnTopPlayerPieces; 43 | final DropIndicatorArgs? dropIndicator; 44 | 45 | 46 | const WPChessboard({Key? key, required this.size, required this.squareBuilder, required this.pieceMap, required this.controller, this.onPieceTap, this.onPieceDrop, this.onEmptyFieldTap, this.onPieceStartDrag, this.orientation = BoardOrientation.white, this.ghostOnDrag = false, this.dropIndicator, this.turnTopPlayerPieces = false}) : super(key: key); 47 | 48 | @override 49 | State createState() => _WPChessboardState(); 50 | } 51 | 52 | class _WPChessboardState extends State { 53 | ChessState state = ChessState(""); 54 | HintMap hints = HintMap(); 55 | ArrowList arrows = ArrowList([]); 56 | 57 | @override 58 | void initState() { 59 | state = widget.controller.state; 60 | widget.controller.addListener(_controllerListener); 61 | super.initState(); 62 | } 63 | 64 | @override 65 | void dispose() { 66 | super.dispose(); 67 | widget.controller.removeListener(_controllerListener); 68 | } 69 | 70 | void _controllerListener() { 71 | if (state.fen != widget.controller.state.fen) { 72 | onUpdateState(widget.controller.state); 73 | } 74 | if (hints.id != widget.controller.hints.id) { 75 | onUpdateHints(widget.controller.hints); 76 | } 77 | if (arrows.id != widget.controller.arrows.id) { 78 | onUpdateArrows(widget.controller.arrows); 79 | } 80 | } 81 | 82 | void onUpdateState(ChessState newState) { 83 | setState(() { 84 | state = newState; 85 | }); 86 | } 87 | 88 | void onUpdateHints(HintMap newHints) { 89 | setState(() { 90 | hints = newHints; 91 | }); 92 | } 93 | 94 | void onUpdateArrows(ArrowList newArrows) { 95 | setState(() { 96 | arrows = newArrows; 97 | }); 98 | } 99 | 100 | @override 101 | Widget build(BuildContext context) { 102 | return Container( 103 | color: Colors.black, 104 | width: widget.size, 105 | height: widget.size, 106 | child: RotatedBox( 107 | quarterTurns: (widget.orientation == BoardOrientation.black) ? 2 : 0, 108 | child: Stack( 109 | children: [ 110 | Squares( 111 | key: Key("squares_" + widget.size.toString() + "_" + state.fen), 112 | size: widget.size, 113 | squareBuilder: widget.squareBuilder, 114 | ), 115 | 116 | Positioned.fill( 117 | child: Pieces( 118 | key: Key("pieces_" + widget.size.toString() + "_" + state.fen), 119 | size: widget.size, 120 | orientation: widget.orientation, 121 | turnTopPlayerPieces: widget.turnTopPlayerPieces, 122 | pieceMap: widget.pieceMap, 123 | state: state, 124 | onPieceTap: widget.onPieceTap, 125 | onPieceStartDrag: widget.onPieceStartDrag, 126 | disableDrag: widget.onPieceDrop == null, 127 | ghostOnDrag: widget.ghostOnDrag, 128 | onEmptyFieldTap: widget.onEmptyFieldTap, 129 | animated: widget.controller.shouldAnimate 130 | ), 131 | ), 132 | 133 | Positioned.fill( 134 | child: Hints( 135 | key: Key(hints.id.toString()), 136 | size: widget.size, 137 | hints: hints, 138 | ), 139 | ), 140 | 141 | Positioned.fill( 142 | child: Arrows( 143 | size: widget.size, 144 | arrows: arrows.value, 145 | ), 146 | ), 147 | 148 | Positioned.fill( 149 | child: DropTargets( 150 | size: widget.size, 151 | onPieceDrop: widget.onPieceDrop, 152 | dropIndicator: widget.dropIndicator, 153 | ), 154 | ), 155 | ], 156 | ), 157 | ) 158 | ); 159 | } 160 | } 161 | 162 | class WPChessboardController extends ChangeNotifier { 163 | ChessState state = ChessState(""); 164 | HintMap hints = HintMap(); 165 | ArrowList arrows = ArrowList([]); 166 | bool shouldAnimate = true; 167 | 168 | WPChessboardController({ initialFen = "" }) { 169 | state = ChessState(initialFen); 170 | } 171 | 172 | void setFen(String value, { bool resetHints = true, bool newGame = false, bool animation = true }) { 173 | shouldAnimate = animation; 174 | 175 | if (newGame) { 176 | state = ChessState(value, last: null); 177 | } else { 178 | state = ChessState(value, last: state); 179 | } 180 | 181 | if (resetHints) { 182 | hints = HintMap(); 183 | } 184 | 185 | notifyListeners(); 186 | } 187 | 188 | void setHints(HintMap value) { 189 | hints = value; 190 | notifyListeners(); 191 | } 192 | 193 | void setArrows(List value) { 194 | arrows = ArrowList(value); 195 | notifyListeners(); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: wp_chessboard 2 | description: A very customizable Chessboard with awesomeness already onboard. 3 | version: 0.0.4 4 | repository: https://github.com/mono424/wp_chessboard 5 | 6 | environment: 7 | sdk: ">=2.16.1 <3.0.0" 8 | flutter: ">=1.17.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | flutter_lints: ^1.0.0 18 | 19 | # For information on the generic Dart part of this file, see the 20 | # following page: https://dart.dev/tools/pub/pubspec 21 | 22 | # The following section is specific to Flutter. 23 | flutter: 24 | 25 | # To add assets to your package, add an assets section, like this: 26 | # assets: 27 | # - images/a_dot_burr.jpeg 28 | # - images/a_dot_ham.jpeg 29 | # 30 | # For details regarding assets in packages, see 31 | # https://flutter.dev/assets-and-images/#from-packages 32 | # 33 | # An image asset can refer to one or more resolution-specific "variants", see 34 | # https://flutter.dev/assets-and-images/#resolution-aware. 35 | 36 | # To add custom fonts to your package, add a fonts section here, 37 | # in this "flutter" section. Each entry in this list should have a 38 | # "family" key with the font family name, and a "fonts" key with a 39 | # list giving the asset and other descriptors for the font. For 40 | # example: 41 | # fonts: 42 | # - family: Schyler 43 | # fonts: 44 | # - asset: fonts/Schyler-Regular.ttf 45 | # - asset: fonts/Schyler-Italic.ttf 46 | # style: italic 47 | # - family: Trajan Pro 48 | # fonts: 49 | # - asset: fonts/TrajanPro.ttf 50 | # - asset: fonts/TrajanPro_Bold.ttf 51 | # weight: 700 52 | # 53 | # For details regarding fonts in packages, see 54 | # https://flutter.dev/custom-fonts/#from-packages 55 | -------------------------------------------------------------------------------- /react_example/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # production 12 | build 13 | public/flutter 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /react_example/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /react_example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /react_example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | React App 17 | 18 | 19 | 20 |
21 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /react_example/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import WPChessboard from './wp_chessboard/wp_chessboard'; 3 | 4 | const sampleGame = [ 5 | "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 6 | "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1", 7 | "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1", 8 | "rnbqkbnr/ppp1pppp/8/3P4/8/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1", 9 | "rnb1kbnr/ppp1pppp/8/3q4/8/8/PPPP1PPP/RNBQKBNR w KQkq - 0 1", 10 | "rnb1kbnr/ppp1pppp/8/3q4/8/2N5/PPPP1PPP/R1BQKBNR w KQkq - 0 1", 11 | "rnb1kbnr/ppp1pppp/8/q7/8/2N5/PPPP1PPP/R1BQKBNR w KQkq - 0 1", 12 | "rnb1kbnr/ppp1pppp/8/q7/3P4/2N5/PPP2PPP/R1BQKBNR w KQkq - 0 1", 13 | "rnb1kbnr/pp2pppp/2p5/q7/3P4/2N5/PPP2PPP/R1BQKBNR w KQkq - 0 1", 14 | ]; 15 | 16 | function App() { 17 | const [currentFen, setCurrentFen] = useState(sampleGame[0]); 18 | 19 | const didLoad = () => { 20 | console.log('WPChessboard loaded'); 21 | } 22 | 23 | const play = async () => { 24 | for (const fen of sampleGame) { 25 | setCurrentFen(fen); 26 | await new Promise((resolve) => setTimeout(resolve, 1000)); 27 | } 28 | } 29 | 30 | return ( 31 |
32 | 39 | 40 |
41 | ); 42 | } 43 | 44 | export default App; 45 | -------------------------------------------------------------------------------- /react_example/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /react_example/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById('root')); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /react_example/src/wp_chessboard/wp_chessboard.jsx: -------------------------------------------------------------------------------- 1 | /* global _flutter */ 2 | 3 | import React, { useRef, useEffect, useState } from 'react'; 4 | 5 | function WPChessboard({ src, assetBase, didLoad, size, fen }) { 6 | const ref = useRef(null); 7 | const [state, setState] = useState(null); 8 | 9 | useEffect(() => { 10 | if (!ref.current || state) return; 11 | _flutter.loader.loadEntrypoint({ 12 | entrypointUrl: src, 13 | onEntrypointLoaded: async (engineInitializer) => { 14 | console.log(ref.current); 15 | let appRunner = await engineInitializer.initializeEngine({ 16 | hostElement: ref.current, 17 | assetBase: assetBase, 18 | }); 19 | await appRunner.runApp(); 20 | } 21 | }); 22 | 23 | ref.current.addEventListener("flutter-initialized", (event) => { 24 | let state = event.detail; 25 | didLoad(); 26 | setState(state); 27 | }, { 28 | once: true, 29 | }); 30 | }, [src, assetBase, didLoad, state]); 31 | 32 | useEffect(() => { 33 | if (!state) return; 34 | state.setSize(size); 35 | }, [size, state]); 36 | 37 | useEffect(() => { 38 | if (!state) return; 39 | state.setFen(fen); 40 | }, [fen, state]); 41 | 42 | 43 | return ( 44 |
45 | ); 46 | } 47 | 48 | export default WPChessboard; 49 | -------------------------------------------------------------------------------- /web_example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Symbolication related 36 | app.*.symbols 37 | 38 | # Obfuscation related 39 | app.*.map.json 40 | 41 | # Android Studio will place build artifacts here 42 | /android/app/debug 43 | /android/app/profile 44 | /android/app/release 45 | -------------------------------------------------------------------------------- /web_example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: 099b3f4bf1581796fac3848d3381dbf2f29edbea 8 | channel: beta 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 099b3f4bf1581796fac3848d3381dbf2f29edbea 17 | base_revision: 099b3f4bf1581796fac3848d3381dbf2f29edbea 18 | 19 | # User provided section 20 | 21 | # List of Local paths (relative to this file) that should be 22 | # ignored by the migrate tool. 23 | # 24 | # Files that are not part of the templates will be ignored by default. 25 | unmanaged_files: 26 | - 'lib/main.dart' 27 | - 'ios/Runner.xcodeproj/project.pbxproj' 28 | -------------------------------------------------------------------------------- /web_example/README.md: -------------------------------------------------------------------------------- 1 | # web_example 2 | 3 | A new Flutter project. 4 | -------------------------------------------------------------------------------- /web_example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | -------------------------------------------------------------------------------- /web_example/build.sh: -------------------------------------------------------------------------------- 1 | flutter build web 2 | rm -rf ../react_example/public/flutter 3 | mkdir ../react_example/public/flutter 4 | cp -r build/web/* ../react_example/public/flutter -------------------------------------------------------------------------------- /web_example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:chess_vectors_flutter/chess_vectors_flutter.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:wp_chessboard/wp_chessboard.dart'; 4 | import 'src/js_interop.dart'; 5 | 6 | void main() { 7 | runApp(const MyApp()); 8 | } 9 | 10 | extension HexColor on Color { 11 | static Color fromHex(String hexString) { 12 | final buffer = StringBuffer(); 13 | if (hexString.length == 6 || hexString.length == 7) buffer.write('ff'); 14 | buffer.write(hexString.replaceFirst('#', '')); 15 | return Color(int.parse(buffer.toString(), radix: 16)); 16 | } 17 | 18 | String toHex({bool leadingHashSign = true}) => '${leadingHashSign ? '#' : ''}' 19 | '${alpha.toRadixString(16).padLeft(2, '0')}' 20 | '${red.toRadixString(16).padLeft(2, '0')}' 21 | '${green.toRadixString(16).padLeft(2, '0')}' 22 | '${blue.toRadixString(16).padLeft(2, '0')}'; 23 | } 24 | 25 | Widget Function(SquareInfo) createSquareBuilder(Color light, Color dark) { 26 | return (SquareInfo info) { 27 | Color fieldColor = (info.index + info.rank) % 2 == 0 ? light : dark; 28 | Color overlayColor = Colors.transparent; 29 | 30 | // if (lastMove != null ) { 31 | // if (lastMove!.first.first == info.rank && lastMove!.first.last == info.file) { 32 | // overlayColor = Colors.blueAccent.shade400.withOpacity(0.4); 33 | // } else if (lastMove!.last.first == info.rank && lastMove!.last.last == info.file) { 34 | // overlayColor = Colors.blueAccent.shade400.withOpacity(0.87); 35 | // } 36 | // } 37 | 38 | return Container( 39 | color: fieldColor, 40 | width: info.size, 41 | height: info.size, 42 | child: AnimatedContainer( 43 | color: overlayColor, 44 | width: info.size, 45 | height: info.size, 46 | duration: const Duration(milliseconds: 200), 47 | ) 48 | ); 49 | }; 50 | } 51 | 52 | class MyApp extends StatefulWidget { 53 | 54 | const MyApp({Key? key}) : super(key: key); 55 | 56 | @override 57 | State createState() => _MyAppState(); 58 | } 59 | 60 | class _MyAppState extends State { 61 | late final StateManager _state; 62 | final ValueNotifier _fen = ValueNotifier(''); 63 | final ValueNotifier _lightColor = ValueNotifier(Colors.grey.shade200.toHex()); 64 | final ValueNotifier _darkColor = ValueNotifier(Colors.grey.shade600.toHex()); 65 | final ValueNotifier _size= ValueNotifier(400); 66 | final ValueNotifier _orientation= ValueNotifier(false); 67 | final controller = WPChessboardController(); 68 | 69 | @override 70 | void initState() { 71 | super.initState(); 72 | _state = StateManager( 73 | fen: _fen, 74 | size: _size, 75 | lightColor: _lightColor, 76 | darkColor: _darkColor, 77 | orientation: _orientation, 78 | ); 79 | final export = createDartExport(_state); 80 | broadcastAppEvent('flutter-initialized', export); 81 | listenToState(); 82 | } 83 | 84 | void listenToState() { 85 | _fen.addListener(() { 86 | update(_fen.value); 87 | }); 88 | } 89 | 90 | void onPieceStartDrag(SquareInfo square, String piece) { 91 | 92 | } 93 | 94 | void onPieceTap(SquareInfo square, String piece) { 95 | 96 | } 97 | 98 | void showHintFields(SquareInfo square, String piece) { 99 | 100 | } 101 | 102 | void onEmptyFieldTap(SquareInfo square) { 103 | 104 | } 105 | 106 | void onPieceDrop(PieceDropEvent event) { 107 | 108 | } 109 | 110 | void update(String fen, {bool animated = true}) { 111 | controller.setFen(fen, animation: animated); 112 | } 113 | 114 | void addArrows() { 115 | controller.setArrows([ 116 | Arrow( 117 | from: SquareLocation.fromString("b1"), 118 | to: SquareLocation.fromString("c3"), 119 | ), 120 | Arrow( 121 | from: SquareLocation.fromString("g1"), 122 | to: SquareLocation.fromString("f3"), 123 | color: Colors.red 124 | ) 125 | ]); 126 | } 127 | 128 | void removeArrows() { 129 | controller.setArrows([]); 130 | } 131 | 132 | BoardOrientation orienatation = BoardOrientation.white; 133 | void toggleArrows() { 134 | setState(() { 135 | if (orienatation == BoardOrientation.white) { 136 | orienatation = BoardOrientation.black; 137 | } else { 138 | orienatation = BoardOrientation.white; 139 | } 140 | }); 141 | } 142 | 143 | @override 144 | Widget build(BuildContext context) { 145 | return MaterialApp( 146 | builder: (context, child) => AnimatedBuilder( 147 | animation: Listenable.merge([_size, _lightColor, _darkColor, _orientation]), 148 | builder: (context, _) => WPChessboard( 149 | size: _size.value, 150 | orientation: _orientation.value ? BoardOrientation.black : BoardOrientation.white, 151 | squareBuilder: createSquareBuilder( 152 | HexColor.fromHex(_lightColor.value), 153 | HexColor.fromHex(_darkColor.value) 154 | ), 155 | controller: controller, 156 | // Dont pass any onPieceDrop handler to disable drag and drop 157 | // onPieceDrop: onPieceDrop, 158 | // onPieceTap: onPieceTap, 159 | // onPieceStartDrag: onPieceStartDrag, 160 | // onEmptyFieldTap: onEmptyFieldTap, 161 | turnTopPlayerPieces: false, 162 | ghostOnDrag: true, 163 | // dropIndicator: DropIndicatorArgs( 164 | // size: value / 2, 165 | // color: Colors.lightBlue.withOpacity(0.24) 166 | // ), 167 | pieceMap: PieceMap( 168 | K: (size) => WhiteKing(size: size), 169 | Q: (size) => WhiteQueen(size: size), 170 | B: (size) => WhiteBishop(size: size), 171 | N: (size) => WhiteKnight(size: size), 172 | R: (size) => WhiteRook(size: size), 173 | P: (size) => WhitePawn(size: size), 174 | k: (size) => BlackKing(size: size), 175 | q: (size) => BlackQueen(size: size), 176 | b: (size) => BlackBishop(size: size), 177 | n: (size) => BlackKnight(size: size), 178 | r: (size) => BlackRook(size: size), 179 | p: (size) => BlackPawn(size: size), 180 | ), 181 | ), 182 | ), 183 | ); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /web_example/lib/src/js_interop.dart: -------------------------------------------------------------------------------- 1 | library js_interop; 2 | 3 | export 'js_interop/state_manager.dart'; 4 | export 'js_interop/helper.dart' show broadcastAppEvent; 5 | export 'package:js/js_util.dart' show createDartExport; -------------------------------------------------------------------------------- /web_example/lib/src/js_interop/dom.dart: -------------------------------------------------------------------------------- 1 | import 'dart:js_interop'; 2 | import 'package:js/js.dart'; 3 | import 'package:js/js_util.dart' as js_util; 4 | 5 | /// Source: https://github.com/flutter/samples/tree/main/web_embedding/ng-flutter/flutter/lib/src/js_interop/dom.dart 6 | 7 | /// This is a little bit of JS-interop code so this Flutter app can dispatch 8 | /// a custom JS event (to be deprecated by package:web) 9 | 10 | @JS('CustomEvent') 11 | @staticInterop 12 | class DomCustomEvent { 13 | external factory DomCustomEvent.withType(JSString type); 14 | external factory DomCustomEvent.withOptions(JSString type, JSAny options); 15 | factory DomCustomEvent._(String type, [Object? options]) { 16 | if (options != null) { 17 | return DomCustomEvent.withOptions( 18 | type.toJS, js_util.jsify(options) as JSAny); 19 | } 20 | return DomCustomEvent.withType(type.toJS); 21 | } 22 | } 23 | 24 | dispatchCustomEvent(DomElement target, String type, Object data) { 25 | final DomCustomEvent event = DomCustomEvent._(type, { 26 | 'bubbles': true, 27 | 'composed': true, 28 | 'detail': data, 29 | }); 30 | 31 | target.dispatchEvent(event); 32 | } 33 | 34 | @JS() 35 | @staticInterop 36 | class DomEventTarget {} 37 | 38 | extension DomEventTargetExtension on DomEventTarget { 39 | @JS('dispatchEvent') 40 | external JSBoolean _dispatchEvent(DomCustomEvent event); 41 | bool dispatchEvent(DomCustomEvent event) => _dispatchEvent(event).toDart; 42 | } 43 | 44 | @JS() 45 | @staticInterop 46 | class DomElement extends DomEventTarget {} 47 | 48 | extension DomElementExtension on DomElement { 49 | @JS('querySelector') 50 | external DomElement? _querySelector(JSString selectors); 51 | DomElement? querySelector(String selectors) => _querySelector(selectors.toJS); 52 | } 53 | 54 | @JS() 55 | @staticInterop 56 | class DomDocument extends DomElement {} 57 | 58 | @JS() 59 | @staticInterop 60 | external DomDocument get document; -------------------------------------------------------------------------------- /web_example/lib/src/js_interop/helper.dart: -------------------------------------------------------------------------------- 1 | import 'dom.dart' as dom; 2 | 3 | /// Source: https://github.com/flutter/samples/tree/main/web_embedding/ng-flutter/flutter/lib/src/js_interop/helper.dart 4 | 5 | /// Locates the root of the flutter app (for now, the first element that has 6 | /// a flt-renderer tag), and dispatches a JS event named [name] with [data]. 7 | void broadcastAppEvent(String name, Object data) { 8 | final dom.DomElement? root = dom.document.querySelector('[flt-renderer]'); 9 | assert(root != null, 'Flutter root element cannot be found!'); 10 | 11 | dom.dispatchCustomEvent(root!, name, data); 12 | } -------------------------------------------------------------------------------- /web_example/lib/src/js_interop/state_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:js/js.dart'; 3 | 4 | @JSExport() 5 | class StateManager { 6 | StateManager({ 7 | required ValueNotifier fen, 8 | required ValueNotifier size, 9 | required ValueNotifier lightColor, 10 | required ValueNotifier darkColor, 11 | required ValueNotifier orientation, 12 | }) : _fen = fen, _size = size, _lightColor = lightColor, _darkColor = darkColor, _orientation = orientation; 13 | 14 | final ValueNotifier _fen; 15 | final ValueNotifier _size; 16 | final ValueNotifier _lightColor; 17 | final ValueNotifier _darkColor; 18 | final ValueNotifier _orientation; 19 | 20 | String getFen() { 21 | return _fen.value; 22 | } 23 | 24 | void setFen(String value) { 25 | _fen.value = value; 26 | } 27 | 28 | bool getOrientation() { 29 | return _orientation.value; 30 | } 31 | 32 | void setOrientation(bool value) { 33 | _orientation.value = value; 34 | } 35 | 36 | double getSize() { 37 | return _size.value; 38 | } 39 | 40 | void setSize(double value) { 41 | _size.value = value; 42 | } 43 | 44 | String getLightColor() { 45 | return _lightColor.value; 46 | } 47 | 48 | void setLightColor(String value) { 49 | _lightColor.value = value; 50 | } 51 | 52 | String getDarkColor() { 53 | return _darkColor.value; 54 | } 55 | 56 | void setDarkColor(String value) { 57 | _darkColor.value = value; 58 | } 59 | 60 | void onFenChanged(VoidCallback f) { 61 | _fen.addListener(f); 62 | } 63 | } -------------------------------------------------------------------------------- /web_example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | chess_vectors_flutter: 29 | dependency: "direct main" 30 | description: 31 | name: chess_vectors_flutter 32 | sha256: "988ff9ec3fa00174f0c0bbe0d50ca776803d9c8fff84d326876ee8a2e11dce31" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.0.18" 36 | clock: 37 | dependency: transitive 38 | description: 39 | name: clock 40 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.1.1" 44 | collection: 45 | dependency: transitive 46 | description: 47 | name: collection 48 | sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.17.1" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.1" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c 70 | url: "https://pub.dev" 71 | source: hosted 72 | version: "2.0.1" 73 | flutter_test: 74 | dependency: "direct dev" 75 | description: flutter 76 | source: sdk 77 | version: "0.0.0" 78 | js: 79 | dependency: "direct main" 80 | description: 81 | name: js 82 | sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "0.6.7" 86 | lints: 87 | dependency: transitive 88 | description: 89 | name: lints 90 | sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "2.0.1" 94 | matcher: 95 | dependency: transitive 96 | description: 97 | name: matcher 98 | sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "0.12.15" 102 | material_color_utilities: 103 | dependency: transitive 104 | description: 105 | name: material_color_utilities 106 | sha256: "586678f20e112219ed0f73215f01bcdf1d769824ba2ebae45ad918a9bfde9bdb" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "0.3.0" 110 | meta: 111 | dependency: transitive 112 | description: 113 | name: meta 114 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "1.9.1" 118 | path: 119 | dependency: transitive 120 | description: 121 | name: path 122 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "1.8.3" 126 | sky_engine: 127 | dependency: transitive 128 | description: flutter 129 | source: sdk 130 | version: "0.0.99" 131 | source_span: 132 | dependency: transitive 133 | description: 134 | name: source_span 135 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "1.10.0" 139 | stack_trace: 140 | dependency: transitive 141 | description: 142 | name: stack_trace 143 | sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "1.11.0" 147 | stream_channel: 148 | dependency: transitive 149 | description: 150 | name: stream_channel 151 | sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "2.1.1" 155 | string_scanner: 156 | dependency: transitive 157 | description: 158 | name: string_scanner 159 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.2.0" 163 | term_glyph: 164 | dependency: transitive 165 | description: 166 | name: term_glyph 167 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "1.2.1" 171 | test_api: 172 | dependency: transitive 173 | description: 174 | name: test_api 175 | sha256: daadc9baabec998b062c9091525aa95786508b1c48e9c30f1f891b8bf6ff2e64 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "0.5.2" 179 | tuple: 180 | dependency: transitive 181 | description: 182 | name: tuple 183 | sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "2.0.1" 187 | vector_math: 188 | dependency: transitive 189 | description: 190 | name: vector_math 191 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "2.1.4" 195 | wp_chessboard: 196 | dependency: "direct main" 197 | description: 198 | path: ".." 199 | relative: true 200 | source: path 201 | version: "0.0.3" 202 | sdks: 203 | dart: ">=3.0.0-0 <4.0.0" 204 | flutter: ">=1.17.0" 205 | -------------------------------------------------------------------------------- /web_example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: web_example 2 | description: A new Flutter project. 3 | publish_to: 'none' 4 | version: 0.1.0 5 | 6 | environment: 7 | sdk: '>=2.19.0-444.6.beta <3.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | wp_chessboard: 13 | path: "../" 14 | js: ^0.6.7 15 | chess_vectors_flutter: ^1.0.18 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | flutter_lints: ^2.0.0 21 | 22 | flutter: 23 | uses-material-design: true 24 | -------------------------------------------------------------------------------- /web_example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:web_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /web_example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono424/wp_chessboard/07597ca81d647d5a07dfb550daa96707977afc64/web_example/web/favicon.png -------------------------------------------------------------------------------- /web_example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | wp_chessboard 27 | 28 | 32 | 33 | 34 | 35 | 36 | 58 | 59 | --------------------------------------------------------------------------------