├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── calendar.iml ├── data └── mock_data.json ├── example ├── .gitignore ├── README.md ├── android.iml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── yourcompany │ │ │ │ └── example │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ ├── 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 │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── example.iml ├── example_android.iml ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── 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.yaml └── test │ └── widget_test.dart ├── lib ├── calendar.dart ├── controllers.dart ├── src │ ├── actions.dart │ ├── calendar │ │ ├── calendar.dart │ │ ├── calendar_controller.dart │ │ ├── calendar_event_icon.dart │ │ ├── calendar_event_icon_row.dart │ │ ├── calendar_events_view.dart │ │ └── calendar_view.dart │ ├── data │ │ ├── data_controller.dart │ │ └── data_model.dart │ ├── day │ │ ├── day.dart │ │ └── day_header.dart │ ├── events │ │ ├── events_footer_view.dart │ │ ├── events_header_view.dart │ │ └── events_view.dart │ ├── month │ │ └── month.dart │ ├── stores.dart │ ├── types.dart │ └── week │ │ ├── week.dart │ │ └── week_header.dart └── utils.dart ├── mock-api.js ├── mock-data.js ├── package.json └── pubspec.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea/ 4 | .vscode/ 5 | .packages 6 | .pub/ 7 | build/ 8 | ios/.generated/ 9 | packages 10 | pubspec.lock 11 | node_modules/ 12 | test.dart 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.1] - TODO: Add release date. 2 | 3 | * TODO: Describe initial release. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # calendar 2 | 3 | A flutter widget to display a calendar with some events. 4 | 5 | flutter-calendar-calendar view 6 | flutter-calendar-event view 7 | flutter-calendar-funcational-demo 8 | 9 | ### Event Data Structure 10 | 11 | The structure of the data returned from the API (currently) is as follows: 12 | ``` 13 | { 14 | "id": int, 15 | "title": String, 16 | "url": String, 17 | "date_start": DateTime, 18 | "date_end": DateTime, 19 | "details": Object 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /calendar.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /data/mock_data.json: -------------------------------------------------------------------------------- 1 | [{"id":1,"title":"Event 1","url":"/events/1","date_start":"2016-12-25 12:00:00.000","date_end":"2016-12-25 13:00:00.000","details":"anything"},{"id":2,"title":"Event 2","url":"/events/2","date_start":"2016-12-25 12:00:00.000","date_end":"2016-12-25 13:00:00.000","details":"anything"},{"id":3,"title":"Event 3","url":"/events/3","date_start":"2016-12-25 12:00:00.000","date_end":"2016-12-25 13:00:00.000","details":"anything"},{"id":4,"title":"Event 4","url":"/events/4","date_start":"2016-12-25 12:00:00.000","date_end":"2016-12-25 13:00:00.000","details":"anything"},{"id":5,"title":"Event 5","url":"/events/5","date_start":"2016-12-25 12:00:00.000","date_end":"2016-12-25 13:00:00.000","details":"anything"},{"id":6,"title":"Event 6","url":"/events/6","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":7,"title":"Event 7","url":"/events/7","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":8,"title":"Event 8","url":"/events/8","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":9,"title":"Event 9","url":"/events/9","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":10,"title":"Event 10","url":"/events/10","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":11,"title":"Event 11","url":"/events/11","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":12,"title":"Event 12","url":"/events/12","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":13,"title":"Event 13","url":"/events/13","date_start":"2016-12-21 12:00:00.000","date_end":"2016-12-21 13:00:00.000","details":{"foo":"bar"}},{"id":14,"title":"Event 14","url":"/events/14","date_start":"2016-12-23 12:00:00.000","date_end":"2016-12-23 13:00:00.000","details":10},{"id":15,"title":"Event 15","url":"/events/15","date_start":"2016-12-23 12:00:00.000","date_end":"2016-12-23 13:00:00.000","details":10},{"id":16,"title":"Event 16","url":"/events/16","date_start":"2016-12-23 12:00:00.000","date_end":"2016-12-23 13:00:00.000","details":10}] -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .idea 4 | .packages 5 | .pub/ 6 | build/ 7 | ios/.generated/ 8 | packages 9 | pubspec.lock 10 | .flutter-plugins 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | Calendar Example 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](http://flutter.io/). 9 | -------------------------------------------------------------------------------- /example/android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | GeneratedPluginRegistrant.java 10 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withInputStream { stream -> 5 | localProperties.load(stream) 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 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | 17 | android { 18 | compileSdkVersion 25 19 | buildToolsVersion '25.0.3' 20 | 21 | lintOptions { 22 | disable 'InvalidPackage' 23 | } 24 | 25 | defaultConfig { 26 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 27 | applicationId "com.yourcompany.example" 28 | minSdkVersion 16 29 | targetSdkVersion 25 30 | versionCode 1 31 | versionName "1.0" 32 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 33 | } 34 | 35 | buildTypes { 36 | release { 37 | // TODO: Add your own signing config for the release build. 38 | // Signing with the debug keys for now, so `flutter run --release` works. 39 | signingConfig signingConfigs.debug 40 | } 41 | } 42 | } 43 | 44 | flutter { 45 | source '../..' 46 | } 47 | 48 | dependencies { 49 | androidTestCompile 'com.android.support:support-annotations:25.4.0' 50 | androidTestCompile 'com.android.support.test:runner:0.5' 51 | androidTestCompile 'com.android.support.test:rules:0.5' 52 | } 53 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/yourcompany/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.yourcompany.example; 2 | 3 | import android.os.Bundle; 4 | 5 | import io.flutter.app.FlutterActivity; 6 | import io.flutter.plugins.GeneratedPluginRegistrant; 7 | 8 | public class MainActivity extends FlutterActivity { 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | GeneratedPluginRegistrant.registerWith(this); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | maven { 5 | url "https://maven.google.com" 6 | } 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:2.3.3' 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | jcenter() 17 | maven { 18 | url "https://maven.google.com" 19 | } 20 | } 21 | } 22 | 23 | rootProject.buildDir = '../build' 24 | subprojects { 25 | project.buildDir = "${rootProject.buildDir}/${project.name}" 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 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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-3.3-all.zip 7 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withInputStream { stream -> plugins.load(stream) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /example/example_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | *.pbxuser 16 | *.mode1v3 17 | *.mode2v3 18 | *.perspectivev3 19 | 20 | !default.pbxuser 21 | !default.mode1v3 22 | !default.mode2v3 23 | !default.perspectivev3 24 | 25 | xcuserdata 26 | 27 | *.moved-aside 28 | 29 | *.pyc 30 | *sync/ 31 | Icon? 32 | .tags* 33 | 34 | /Flutter/app.flx 35 | /Flutter/app.zip 36 | /Flutter/App.framework 37 | /Flutter/Flutter.framework 38 | /Flutter/Generated.xcconfig 39 | /ServiceDefinitions.json 40 | 41 | Pods/ 42 | -------------------------------------------------------------------------------- /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 | UIRequiredDeviceCapabilities 24 | 25 | arm64 26 | 27 | MinimumOSVersion 28 | 8.0 29 | 30 | 31 | -------------------------------------------------------------------------------- /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 = 46; 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 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 18 | 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; 19 | 9740EEBB1CF902C7004384FC /* app.flx in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB71CF902C7004384FC /* app.flx */; }; 20 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 21 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 22 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXCopyFilesBuildPhase section */ 26 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 27 | isa = PBXCopyFilesBuildPhase; 28 | buildActionMask = 2147483647; 29 | dstPath = ""; 30 | dstSubfolderSpec = 10; 31 | files = ( 32 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 33 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 34 | ); 35 | name = "Embed Frameworks"; 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXCopyFilesBuildPhase section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 42 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 43 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 44 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 45 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 46 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 49 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 50 | 9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = ""; }; 51 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 52 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 65 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | /* End PBXFrameworksBuildPhase section */ 70 | 71 | /* Begin PBXGroup section */ 72 | 9740EEB11CF90186004384FC /* Flutter */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 9740EEB71CF902C7004384FC /* app.flx */, 76 | 3B80C3931E831B6300D905FE /* App.framework */, 77 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 78 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 79 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 80 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 81 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 82 | ); 83 | name = Flutter; 84 | sourceTree = ""; 85 | }; 86 | 97C146E51CF9000F007C117D = { 87 | isa = PBXGroup; 88 | children = ( 89 | 9740EEB11CF90186004384FC /* Flutter */, 90 | 97C146F01CF9000F007C117D /* Runner */, 91 | 97C146EF1CF9000F007C117D /* Products */, 92 | ); 93 | sourceTree = ""; 94 | }; 95 | 97C146EF1CF9000F007C117D /* Products */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 97C146EE1CF9000F007C117D /* Runner.app */, 99 | ); 100 | name = Products; 101 | sourceTree = ""; 102 | }; 103 | 97C146F01CF9000F007C117D /* Runner */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 107 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 108 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 109 | 97C147021CF9000F007C117D /* Info.plist */, 110 | 97C146F11CF9000F007C117D /* Supporting Files */, 111 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 112 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 113 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 114 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 115 | ); 116 | path = Runner; 117 | sourceTree = ""; 118 | }; 119 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | /* End PBXGroup section */ 127 | 128 | /* Begin PBXNativeTarget section */ 129 | 97C146ED1CF9000F007C117D /* Runner */ = { 130 | isa = PBXNativeTarget; 131 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 132 | buildPhases = ( 133 | 9740EEB61CF901F6004384FC /* Run Script */, 134 | 97C146EA1CF9000F007C117D /* Sources */, 135 | 97C146EB1CF9000F007C117D /* Frameworks */, 136 | 97C146EC1CF9000F007C117D /* Resources */, 137 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 138 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | ); 144 | name = Runner; 145 | productName = Runner; 146 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 147 | productType = "com.apple.product-type.application"; 148 | }; 149 | /* End PBXNativeTarget section */ 150 | 151 | /* Begin PBXProject section */ 152 | 97C146E61CF9000F007C117D /* Project object */ = { 153 | isa = PBXProject; 154 | attributes = { 155 | LastUpgradeCheck = 0830; 156 | ORGANIZATIONNAME = "The Chromium Authors"; 157 | TargetAttributes = { 158 | 97C146ED1CF9000F007C117D = { 159 | CreatedOnToolsVersion = 7.3.1; 160 | LastSwiftMigration = 0830; 161 | }; 162 | }; 163 | }; 164 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 165 | compatibilityVersion = "Xcode 3.2"; 166 | developmentRegion = English; 167 | hasScannedForEncodings = 0; 168 | knownRegions = ( 169 | en, 170 | Base, 171 | ); 172 | mainGroup = 97C146E51CF9000F007C117D; 173 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 174 | projectDirPath = ""; 175 | projectRoot = ""; 176 | targets = ( 177 | 97C146ED1CF9000F007C117D /* Runner */, 178 | ); 179 | }; 180 | /* End PBXProject section */ 181 | 182 | /* Begin PBXResourcesBuildPhase section */ 183 | 97C146EC1CF9000F007C117D /* Resources */ = { 184 | isa = PBXResourcesBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | 9740EEBB1CF902C7004384FC /* app.flx in Resources */, 188 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 189 | 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, 190 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 191 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 192 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 193 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXResourcesBuildPhase section */ 198 | 199 | /* Begin PBXShellScriptBuildPhase section */ 200 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 201 | isa = PBXShellScriptBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | ); 205 | inputPaths = ( 206 | ); 207 | name = "Thin Binary"; 208 | outputPaths = ( 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | shellPath = /bin/sh; 212 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 213 | }; 214 | 9740EEB61CF901F6004384FC /* Run Script */ = { 215 | isa = PBXShellScriptBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | ); 219 | inputPaths = ( 220 | ); 221 | name = "Run Script"; 222 | outputPaths = ( 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | shellPath = /bin/sh; 226 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 227 | }; 228 | /* End PBXShellScriptBuildPhase section */ 229 | 230 | /* Begin PBXSourcesBuildPhase section */ 231 | 97C146EA1CF9000F007C117D /* Sources */ = { 232 | isa = PBXSourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 236 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin PBXVariantGroup section */ 243 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 244 | isa = PBXVariantGroup; 245 | children = ( 246 | 97C146FB1CF9000F007C117D /* Base */, 247 | ); 248 | name = Main.storyboard; 249 | sourceTree = ""; 250 | }; 251 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 252 | isa = PBXVariantGroup; 253 | children = ( 254 | 97C147001CF9000F007C117D /* Base */, 255 | ); 256 | name = LaunchScreen.storyboard; 257 | sourceTree = ""; 258 | }; 259 | /* End PBXVariantGroup section */ 260 | 261 | /* Begin XCBuildConfiguration section */ 262 | 97C147031CF9000F007C117D /* Debug */ = { 263 | isa = XCBuildConfiguration; 264 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 265 | buildSettings = { 266 | ALWAYS_SEARCH_USER_PATHS = NO; 267 | CLANG_ANALYZER_NONNULL = YES; 268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 269 | CLANG_CXX_LIBRARY = "libc++"; 270 | CLANG_ENABLE_MODULES = YES; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_WARN_BOOL_CONVERSION = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 275 | CLANG_WARN_EMPTY_BODY = YES; 276 | CLANG_WARN_ENUM_CONVERSION = YES; 277 | CLANG_WARN_INFINITE_RECURSION = YES; 278 | CLANG_WARN_INT_CONVERSION = YES; 279 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 280 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = dwarf; 286 | ENABLE_STRICT_OBJC_MSGSEND = YES; 287 | ENABLE_TESTABILITY = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_DYNAMIC_NO_PIC = NO; 290 | GCC_NO_COMMON_BLOCKS = YES; 291 | GCC_OPTIMIZATION_LEVEL = 0; 292 | GCC_PREPROCESSOR_DEFINITIONS = ( 293 | "DEBUG=1", 294 | "$(inherited)", 295 | ); 296 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 297 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 298 | GCC_WARN_UNDECLARED_SELECTOR = YES; 299 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 300 | GCC_WARN_UNUSED_FUNCTION = YES; 301 | GCC_WARN_UNUSED_VARIABLE = YES; 302 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 303 | MTL_ENABLE_DEBUG_INFO = YES; 304 | ONLY_ACTIVE_ARCH = YES; 305 | SDKROOT = iphoneos; 306 | TARGETED_DEVICE_FAMILY = "1,2"; 307 | }; 308 | name = Debug; 309 | }; 310 | 97C147041CF9000F007C117D /* Release */ = { 311 | isa = XCBuildConfiguration; 312 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 313 | buildSettings = { 314 | ALWAYS_SEARCH_USER_PATHS = NO; 315 | CLANG_ANALYZER_NONNULL = YES; 316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 317 | CLANG_CXX_LIBRARY = "libc++"; 318 | CLANG_ENABLE_MODULES = YES; 319 | CLANG_ENABLE_OBJC_ARC = YES; 320 | CLANG_WARN_BOOL_CONVERSION = YES; 321 | CLANG_WARN_CONSTANT_CONVERSION = YES; 322 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 323 | CLANG_WARN_EMPTY_BODY = YES; 324 | CLANG_WARN_ENUM_CONVERSION = YES; 325 | CLANG_WARN_INFINITE_RECURSION = YES; 326 | CLANG_WARN_INT_CONVERSION = YES; 327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 328 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 332 | COPY_PHASE_STRIP = NO; 333 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 334 | ENABLE_NS_ASSERTIONS = NO; 335 | ENABLE_STRICT_OBJC_MSGSEND = YES; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_NO_COMMON_BLOCKS = YES; 338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 340 | GCC_WARN_UNDECLARED_SELECTOR = YES; 341 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 342 | GCC_WARN_UNUSED_FUNCTION = YES; 343 | GCC_WARN_UNUSED_VARIABLE = YES; 344 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 345 | MTL_ENABLE_DEBUG_INFO = NO; 346 | SDKROOT = iphoneos; 347 | TARGETED_DEVICE_FAMILY = "1,2"; 348 | VALIDATE_PRODUCT = YES; 349 | }; 350 | name = Release; 351 | }; 352 | 97C147061CF9000F007C117D /* Debug */ = { 353 | isa = XCBuildConfiguration; 354 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 355 | buildSettings = { 356 | ARCHS = arm64; 357 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 358 | CLANG_ENABLE_MODULES = YES; 359 | ENABLE_BITCODE = NO; 360 | FRAMEWORK_SEARCH_PATHS = ( 361 | "$(inherited)", 362 | "$(PROJECT_DIR)/Flutter", 363 | ); 364 | INFOPLIST_FILE = Runner/Info.plist; 365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 366 | LIBRARY_SEARCH_PATHS = ( 367 | "$(inherited)", 368 | "$(PROJECT_DIR)/Flutter", 369 | ); 370 | PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.example; 371 | PRODUCT_NAME = "$(TARGET_NAME)"; 372 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 373 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 374 | SWIFT_VERSION = 3.0; 375 | }; 376 | name = Debug; 377 | }; 378 | 97C147071CF9000F007C117D /* Release */ = { 379 | isa = XCBuildConfiguration; 380 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 381 | buildSettings = { 382 | ARCHS = arm64; 383 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 384 | CLANG_ENABLE_MODULES = YES; 385 | ENABLE_BITCODE = NO; 386 | FRAMEWORK_SEARCH_PATHS = ( 387 | "$(inherited)", 388 | "$(PROJECT_DIR)/Flutter", 389 | ); 390 | INFOPLIST_FILE = Runner/Info.plist; 391 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 392 | LIBRARY_SEARCH_PATHS = ( 393 | "$(inherited)", 394 | "$(PROJECT_DIR)/Flutter", 395 | ); 396 | PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.example; 397 | PRODUCT_NAME = "$(TARGET_NAME)"; 398 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 399 | SWIFT_VERSION = 3.0; 400 | }; 401 | name = Release; 402 | }; 403 | /* End XCBuildConfiguration section */ 404 | 405 | /* Begin XCConfigurationList section */ 406 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 407 | isa = XCConfigurationList; 408 | buildConfigurations = ( 409 | 97C147031CF9000F007C117D /* Debug */, 410 | 97C147041CF9000F007C117D /* Release */, 411 | ); 412 | defaultConfigurationIsVisible = 0; 413 | defaultConfigurationName = Release; 414 | }; 415 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 416 | isa = XCConfigurationList; 417 | buildConfigurations = ( 418 | 97C147061CF9000F007C117D /* Debug */, 419 | 97C147071CF9000F007C117D /* Release */, 420 | ); 421 | defaultConfigurationIsVisible = 0; 422 | defaultConfigurationName = Release; 423 | }; 424 | /* End XCConfigurationList section */ 425 | }; 426 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 427 | } 428 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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: [UIApplicationLaunchOptionsKey: 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 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemimik/flutter-calendar/525870a925797e4b77a6c939678206c44fef42b1/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 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | arm64 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | UIViewControllerBasedStatusBarAppearance 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/rendering.dart'; 3 | import 'package:http/http.dart'; 4 | import 'dart:convert'; 5 | import 'package:calendar/calendar.dart'; 6 | import 'package:calendar/controllers.dart'; 7 | import 'package:calendar/utils.dart'; 8 | 9 | Widget appBar = new AppBar(title: new Text('Calendar Example'), backgroundColor: Colors.blue[500]); 10 | ThemeData theme = new ThemeData(primarySwatch: Colors.blue); 11 | 12 | /// 13 | /// INFO(mperrotte): 14 | /// - Define the model class that will represent your data. 15 | /// - Extend the DataModel for functionality and type checking 16 | class Event extends DataModel { 17 | Event( 18 | Map data, 19 | ) : id = data['id'], 20 | title = data['title'], 21 | url = data['url'], 22 | start = DateTime.parse(data['date_start']), 23 | end = DateTime.parse(data['date_end']), 24 | details = data['details'], 25 | super( 26 | year: DateTime.parse(data['date_start']).year, 27 | month: DateTime.parse(data['date_start']).month, 28 | date: DateTime.parse(data['date_start']).day, 29 | ); 30 | 31 | final int id; 32 | final String title; 33 | final String url; 34 | final DateTime start; 35 | final DateTime end; 36 | final dynamic details; 37 | } 38 | 39 | EventsView renderEventsHandler(List events) { 40 | return new EventsView( 41 | itemBuilder: (BuildContext context, int index) { 42 | if (index >= events.length) { 43 | return null; 44 | } 45 | return new Dismissible( 46 | // key needs to be more unique 47 | key: new ValueKey((events[index] as Event).id), 48 | direction: DismissDirection.horizontal, 49 | onDismissed: (DismissDirection direction) { 50 | print(direction); 51 | removeEventAction(index); 52 | print('done removing'); 53 | }, 54 | onResize: () { 55 | print('resize'); 56 | }, 57 | background: new Container( 58 | decoration: new BoxDecoration( 59 | color: theme.primaryColor, 60 | ), 61 | child: new ListTile( 62 | leading: new Icon( 63 | Icons.input, 64 | color: Colors.white, 65 | size: 36.0, 66 | ), 67 | ), 68 | ), 69 | child: new Container( 70 | height: 75.0, 71 | decoration: new BoxDecoration( 72 | color: theme.canvasColor, 73 | border: new Border( 74 | bottom: new BorderSide(color: theme.dividerColor), 75 | ), 76 | ), 77 | child: new ListTile( 78 | title: new Text((events[index] as Event).title), 79 | subtitle: new Text((events[index] as Event).url), 80 | isThreeLine: true, 81 | ), 82 | ), 83 | ); 84 | }, 85 | ); 86 | } 87 | 88 | dynamic fetchDataHandler(String uri) async { 89 | print('fetching data...'); 90 | Response response = await get(uri); 91 | String json = response.body; 92 | if (json == null) { 93 | // NOTE(mperrotte): no body value from response; bail out; 94 | return null; 95 | } 96 | JsonDecoder decoder = new JsonDecoder(); 97 | try { 98 | dynamic payload = decoder.convert(json); 99 | return payload; 100 | } on ArgumentError { 101 | // NOTE(mperrotte): unable to decode json payload 102 | return null; 103 | } 104 | } 105 | 106 | List parseDataHandler(List payload) { 107 | List events = new List(); 108 | for (Map item in payload) { 109 | events.add(new Event(item)); 110 | } 111 | return events; 112 | } 113 | 114 | String getUriHandler() { 115 | return 'https://gist.githubusercontent.com/mikemimik/2da9df7ca94f0bdfd493bf70e53ec3b6/raw/f4e0fe43219b02091f4eec79ebd10e37185e213d/data-events.json'; 116 | } 117 | 118 | CalendarController calendarController = new CalendarController( 119 | renderEvents: renderEventsHandler, 120 | ); 121 | DataController dataController = new DataController( 122 | fetchData: fetchDataHandler, 123 | parseData: parseDataHandler, 124 | getUri: getUriHandler, 125 | ); 126 | 127 | void main() { 128 | debugPaintSizeEnabled = false; 129 | 130 | runApp( 131 | new MaterialApp( 132 | title: 'Calendar Example', 133 | theme: theme, 134 | home: new Scaffold( 135 | appBar: appBar, 136 | body: new Calendar( 137 | calendarController: calendarController, 138 | dataController: dataController, 139 | ), 140 | ), 141 | ), 142 | ); 143 | } 144 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: CalendarExample 2 | description: Calendar Example 3 | 4 | dependencies: 5 | flutter: 6 | sdk: flutter 7 | calendar: 8 | path: ../ 9 | http: '>=0.11.3+14' 10 | 11 | dev_dependencies: 12 | flutter_test: 13 | sdk: flutter 14 | 15 | 16 | # For information on the generic Dart part of this file, see the 17 | # following page: https://www.dartlang.org/tools/pub/pubspec 18 | 19 | # The following section is specific to Flutter. 20 | flutter: 21 | 22 | # The following line ensures that the Material Icons font is 23 | # included with your application, so that you can use the icons in 24 | # the Icons class. 25 | uses-material-design: true 26 | 27 | # To add assets to your application, add an assets section, like this: 28 | # assets: 29 | # - images/a_dot_burr.jpeg 30 | # - images/a_dot_ham.jpeg 31 | 32 | # An image asset can refer to one or more resolution-specific "variants", see 33 | # https://flutter.io/assets-and-images/. 34 | 35 | # For details regarding adding assets from package dependencies, see 36 | # https://flutter.io/assets-and-images/ 37 | 38 | # To add custom fonts to your application, add a fonts section here, 39 | # in this "flutter" section. Each entry in this list should have a 40 | # "family" key with the font family name, and a "fonts" key with a 41 | # list giving the asset and other descriptors for the font. For 42 | # example: 43 | # fonts: 44 | # - family: Schyler 45 | # fonts: 46 | # - asset: fonts/Schyler-Regular.ttf 47 | # - asset: fonts/Schyler-Italic.ttf 48 | # style: italic 49 | # - family: Trajan Pro 50 | # fonts: 51 | # - asset: fonts/TrajanPro.ttf 52 | # - asset: fonts/TrajanPro_Bold.ttf 53 | # weight: 700 54 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // // This is a basic Flutter widget test. 2 | // // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // // are correct. 6 | 7 | // import 'package:flutter/material.dart'; 8 | // import 'package:flutter_test/flutter_test.dart'; 9 | 10 | // import '../lib/main.dart'; 11 | 12 | // void main() { 13 | // testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // // Build our app and trigger a frame. 15 | // await tester.pumpWidget(new MyApp()); 16 | 17 | // // Verify that our counter starts at 0. 18 | // expect(find.text('0'), findsOneWidget); 19 | // expect(find.text('1'), findsNothing); 20 | 21 | // // Tap the '+' icon and trigger a frame. 22 | // await tester.tap(find.byIcon(Icons.add)); 23 | // await tester.pump(); 24 | 25 | // // Verify that our counter has incremented. 26 | // expect(find.text('0'), findsNothing); 27 | // expect(find.text('1'), findsOneWidget); 28 | // }); 29 | // } 30 | -------------------------------------------------------------------------------- /lib/calendar.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Calendar Exports 3 | /// 4 | /// The calendar library implements a [Calendar] component with a [CalendarController]. 5 | 6 | export 'src/calendar/calendar.dart'; 7 | export 'src/calendar/calendar_controller.dart'; 8 | 9 | export 'src/events/events_view.dart'; 10 | 11 | export 'src/data/data_model.dart'; 12 | -------------------------------------------------------------------------------- /lib/controllers.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Controller Exports 3 | /// 4 | export 'src/calendar/calendar_controller.dart'; 5 | export 'src/data/data_controller.dart'; 6 | -------------------------------------------------------------------------------- /lib/src/actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_flux/flutter_flux.dart'; 2 | 3 | import 'package:calendar/controllers.dart'; 4 | import 'package:calendar/src/types.dart'; 5 | 6 | final Action switchViewAction = new Action(); 7 | final Action> selectDateAction = new Action>(); 8 | final Action> fetchDataAction = new Action>(); 9 | final Action removeEventAction = new Action(); 10 | 11 | final Action setCalendarControllerAction = new Action(); 12 | final Action setDataControllerAction = new Action(); 13 | -------------------------------------------------------------------------------- /lib/src/calendar/calendar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_flux/flutter_flux.dart'; 4 | 5 | import 'package:calendar/src/calendar/calendar_view.dart'; 6 | import 'package:calendar/src/calendar/calendar_events_view.dart'; 7 | import 'package:calendar/utils.dart'; 8 | import 'package:calendar/controllers.dart'; 9 | 10 | // TODO(mperrotte): fetch data 11 | class Calendar extends StoreWatcher { 12 | Calendar({ 13 | Key key, 14 | DateTime initializeDate, 15 | @required this.calendarController, 16 | @required this.dataController, 17 | }) 18 | : year = (initializeDate == null) ? new DateTime.now().year : initializeDate.year, 19 | month = (initializeDate == null) ? new DateTime.now().month : initializeDate.month, 20 | date = (initializeDate == null) ? new DateTime.now().day : initializeDate.day, 21 | super(key: key); 22 | 23 | final int year; 24 | final int month; 25 | final int date; 26 | final CalendarController calendarController; 27 | final DataController dataController; 28 | 29 | @override 30 | void initStores(ListenToStore listenToStore) { 31 | listenToStore(calendarStoreToken); 32 | listenToStore(controllerStoreToken); 33 | 34 | // INFO(mperrotte): Fetch data after we've initialized the listeners 35 | String uri = dataController.getUri(); 36 | dynamic payload = dataController.fetchData(uri); 37 | fetchDataAction({ 38 | 'payload': payload, 39 | 'parseData': dataController.parseData, 40 | }); 41 | } 42 | 43 | @override 44 | Widget build(BuildContext context, Map stores) { 45 | final CalendarStore calendarStore = stores[calendarStoreToken]; 46 | Widget component; 47 | 48 | // INFO(mperrotte): put controllers into store 49 | setCalendarControllerAction(calendarController); 50 | setDataControllerAction(dataController); 51 | 52 | switch (calendarStore.currentView) { 53 | case RenderableView.calendar: 54 | component = new CalendarView( 55 | year: year, 56 | month: month, 57 | date: date, 58 | ); 59 | break; 60 | case RenderableView.events: 61 | component = new CalendarEventsView( 62 | year: calendarStore.selectedYear, 63 | month: calendarStore.selectedMonth, 64 | date: calendarStore.selectedDate, 65 | child: calendarController.renderEvents( 66 | calendarStore.eventsByDate[calendarStore.selectedDate], 67 | ), 68 | ); 69 | break; 70 | case RenderableView.event: 71 | break; 72 | } 73 | return new Material( 74 | child: component, 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/src/calendar/calendar_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | import 'package:calendar/src/types.dart'; 4 | 5 | abstract class BaseCalendarController { 6 | BaseCalendarController({ 7 | @required this.renderEvents, 8 | }); 9 | 10 | final RenderEventsCallback renderEvents; 11 | } 12 | 13 | class CalendarController extends BaseCalendarController { 14 | CalendarController({ 15 | @required renderEvents, 16 | }) 17 | : super( 18 | renderEvents: renderEvents, 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/calendar/calendar_event_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class CalendarViewEventIcon extends StatelessWidget { 5 | CalendarViewEventIcon({ 6 | @required this.backgroundColor, 7 | }); 8 | 9 | final Color backgroundColor; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return new Container( 14 | height: 5.0, 15 | width: 5.0, 16 | margin: const EdgeInsets.all(0.5), 17 | decoration: new BoxDecoration( 18 | color: backgroundColor, 19 | ), 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/calendar/calendar_event_icon_row.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:calendar/src/calendar/calendar_event_icon.dart'; 5 | 6 | class CalendarViewEventIconRow extends StatelessWidget { 7 | CalendarViewEventIconRow({ 8 | @required this.eventIcons, 9 | }); 10 | 11 | final List eventIcons; 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return new Row( 16 | children: eventIcons, 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/calendar/calendar_events_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:calendar/src/events/events_header_view.dart'; 4 | import 'package:calendar/src/events/events_footer_view.dart'; 5 | 6 | class CalendarEventsView extends StatelessWidget { 7 | CalendarEventsView({ 8 | @required this.year, 9 | @required this.month, 10 | @required this.date, 11 | @required this.child, 12 | }); 13 | 14 | final int year; 15 | final int month; 16 | final int date; 17 | final Widget child; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | ThemeData theme = Theme.of(context); 22 | 23 | return new Container( 24 | constraints: new BoxConstraints(), 25 | child: new Column( 26 | // crossAxisAlignment: CrossAxisAlignment.stretch, 27 | // mainAxisAlignment: MainAxisAlignment.spaceBetween, 28 | 29 | children: [ 30 | new EventsHeader(year, month, date), 31 | child, 32 | new EventsFooter(theme), 33 | ], 34 | ), 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/calendar/calendar_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:calendar/src/month/month.dart'; 5 | import 'package:calendar/controllers.dart'; 6 | import 'package:calendar/utils.dart'; 7 | 8 | class CalendarView extends StatelessWidget { 9 | CalendarView({ 10 | @required this.year, 11 | @required this.month, 12 | @required this.date, 13 | }); 14 | 15 | final int year; 16 | final int month; 17 | final int date; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return new Container( 22 | child: new Column( 23 | children: [ 24 | new CalendarViewHeader(monthName: MonthNames[month - 1]['long']), 25 | new Month( 26 | year: year, 27 | month: month, 28 | date: date, 29 | ), 30 | ], 31 | ), 32 | ); 33 | } 34 | } 35 | 36 | class CalendarViewHeader extends StatelessWidget { 37 | CalendarViewHeader({ 38 | @required this.monthName, 39 | }); 40 | 41 | final String monthName; 42 | @override 43 | Widget build(BuildContext context) { 44 | return new Container( 45 | height: 40.0, 46 | margin: const EdgeInsets.only(top: 5.0, bottom: 10.0), 47 | child: new Align( 48 | alignment: FractionalOffset.center, 49 | child: new Text(monthName), 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/data/data_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:calendar/src/types.dart'; 3 | 4 | class BaseDataController { 5 | BaseDataController({ 6 | @required this.fetchData, 7 | @required this.parseData, 8 | @required this.getUri, 9 | }); 10 | 11 | final FetchDataCallback fetchData; 12 | final ParseDataCallback parseData; 13 | final GetDataUriCallback getUri; 14 | } 15 | 16 | class DataController extends BaseDataController { 17 | DataController({ 18 | @required fetchData, 19 | @required parseData, 20 | @required getUri, 21 | }) 22 | : super( 23 | fetchData: fetchData, 24 | parseData: parseData, 25 | getUri: getUri, 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/data/data_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | abstract class DataModel { 4 | DataModel({ 5 | @required this.year, 6 | @required this.month, 7 | @required this.date, 8 | }); 9 | 10 | final int year; 11 | final int month; 12 | final int date; 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/day/day.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_flux/flutter_flux.dart'; 4 | 5 | import 'package:calendar/src/calendar/calendar_event_icon_row.dart'; 6 | import 'package:calendar/src/calendar/calendar_event_icon.dart'; 7 | import 'package:calendar/src/data/data_model.dart'; 8 | import 'package:calendar/utils.dart'; 9 | 10 | class Day extends StoreWatcher { 11 | Day({ 12 | @required this.year, 13 | @required this.month, 14 | @required this.date, 15 | List events, 16 | this.today: false, 17 | }) : textStyle = today ? new TextStyle(color: Colors.orange[500]) : new TextStyle(); 18 | 19 | final int year; 20 | final int month; 21 | final int date; 22 | final bool today; 23 | final TextStyle textStyle; 24 | 25 | // Functions 26 | List _generateEventIcons(int count) { 27 | List eventIcons = new List(); 28 | for (int i = 0; i < count; i++) { 29 | eventIcons.add( 30 | new CalendarViewEventIcon( 31 | backgroundColor: Colors.red[500], 32 | ), 33 | ); 34 | } 35 | return eventIcons; 36 | } 37 | 38 | List _generateEventIconRows(CalendarStore store) { 39 | List children = new List(); 40 | if (store.eventsByDate[date] != null && store.eventsByDate[date].length != 0) { 41 | num rows = store.eventsByDate[date].length / 4; 42 | num rowCount = rows.round(); 43 | num remainder = store.eventsByDate[date].length.remainder(4); 44 | for (int i = 0; i < rowCount; i++) { 45 | if (i == rowCount - 1) { 46 | int iconCount = (remainder == 0) ? 4 : remainder; 47 | children.add( 48 | new CalendarViewEventIconRow( 49 | eventIcons: _generateEventIcons(iconCount), 50 | ), 51 | ); 52 | } else { 53 | children.add( 54 | new CalendarViewEventIconRow( 55 | eventIcons: _generateEventIcons(4), 56 | ), 57 | ); 58 | } 59 | } 60 | } 61 | return children; 62 | } 63 | 64 | @override 65 | void initStores(ListenToStore listenToStore) { 66 | listenToStore(calendarStoreToken); 67 | } 68 | 69 | @override 70 | Widget build(BuildContext context, Map stores) { 71 | final CalendarStore calendarStore = stores[calendarStoreToken]; 72 | 73 | return new Flexible( 74 | child: new InkWell( 75 | onTap: () { 76 | Map currentDay = new Map.fromIterables( 77 | ['year', 'month', 'date'], 78 | [year, month, date], 79 | ); 80 | if (calendarStore.eventsByDate[date] != null && 81 | calendarStore.eventsByDate[date].length != 0) { 82 | selectDateAction(currentDay); 83 | switchViewAction(RenderableView.events); 84 | } 85 | }, 86 | child: new Container( 87 | height: 60.0, 88 | decoration: new BoxDecoration( 89 | border: new Border.all( 90 | color: Colors.black, 91 | width: 0.5, 92 | )), 93 | padding: const EdgeInsets.all(4.0), 94 | child: new Column( 95 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 96 | children: [ 97 | new Align( 98 | alignment: FractionalOffset.centerRight, 99 | child: new Container( 100 | child: new Text( 101 | date.toString(), 102 | style: textStyle, 103 | ), 104 | ), 105 | ), 106 | new Container( 107 | height: 25.0, 108 | child: new Column( 109 | mainAxisAlignment: MainAxisAlignment.end, 110 | children: _generateEventIconRows(calendarStore), 111 | ), 112 | ) 113 | ], 114 | ), 115 | ), 116 | ), 117 | ); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /lib/src/day/day_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_flux/flutter_flux.dart'; 4 | import 'day.dart'; 5 | 6 | class DayHeader extends Day { 7 | DayHeader({ 8 | @required this.day, 9 | }); 10 | 11 | final String day; 12 | 13 | @override 14 | Widget build(BuildContext context, Map stores) { 15 | return new Flexible( 16 | child: new Container( 17 | decoration: new BoxDecoration( 18 | border: new Border.all( 19 | color: Colors.black, 20 | width: 0.5, 21 | ), 22 | ), 23 | padding: const EdgeInsets.all(4.0), 24 | child: new Align( 25 | alignment: FractionalOffset.center, 26 | child: new Text(day), 27 | ), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/events/events_footer_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:calendar/src/types.dart'; 3 | import 'package:calendar/src/actions.dart'; 4 | 5 | class EventsFooter extends StatelessWidget { 6 | EventsFooter( 7 | this.theme, 8 | ); 9 | 10 | final ThemeData theme; 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return new Container( 15 | decoration: new BoxDecoration( 16 | color: theme.accentColor, 17 | ), 18 | child: new SizedBox( 19 | height: 48.0, 20 | child: new Row( 21 | children: [ 22 | new IconButton( 23 | iconSize: 36.0, 24 | icon: new Icon( 25 | Icons.chevron_left, 26 | size: 36.0, 27 | ), 28 | onPressed: () { 29 | switchViewAction(RenderableView.calendar); 30 | }, 31 | ) 32 | ], 33 | ), 34 | ), 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/events/events_header_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:calendar/src/types.dart'; 3 | 4 | class EventsHeader extends StatelessWidget { 5 | EventsHeader( 6 | this.year, 7 | this.month, 8 | this.date, 9 | ); 10 | 11 | final int year; 12 | final int month; 13 | final int date; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return new Center( 18 | child: new Container( 19 | constraints: new BoxConstraints(), 20 | margin: const EdgeInsets.only( 21 | top: 12.0, 22 | bottom: 12.0, 23 | ), 24 | child: new SizedBox( 25 | height: 15.0, 26 | child: new Text('Day: ' + MonthNames[month - 1]['long'] + ' $date, $year'), 27 | ), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/events/events_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_flux/flutter_flux.dart'; 4 | import 'package:calendar/src/stores.dart'; 5 | 6 | class EventsView extends StoreWatcher { 7 | EventsView({ 8 | @required this.itemBuilder, 9 | }); 10 | 11 | final IndexedWidgetBuilder itemBuilder; 12 | 13 | @override 14 | void initStores(ListenToStore listenToStore) { 15 | listenToStore(calendarStoreToken); 16 | } 17 | 18 | @override 19 | Widget build(BuildContext context, Map stores) { 20 | final CalendarStore calendarStore = stores[calendarStoreToken]; 21 | 22 | return new Container( 23 | height: 504.0, 24 | child: new ListView.builder( 25 | itemCount: calendarStore.eventsByDate[calendarStore.selectedDate].length, 26 | itemBuilder: itemBuilder, 27 | ), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/month/month.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_flux/flutter_flux.dart'; 4 | 5 | import 'package:calendar/src/week/week_header.dart'; 6 | import 'package:calendar/src/week/week.dart'; 7 | import 'package:calendar/src/day/day.dart'; 8 | import 'package:calendar/utils.dart'; 9 | 10 | class Month extends StoreWatcher { 11 | Month({ 12 | @required this.year, 13 | @required this.month, 14 | @required this.date, 15 | }); 16 | 17 | final int year; 18 | final int month; 19 | final int date; 20 | 21 | // Functions 22 | List _padMonthBeginning(DateTime firstDay) { 23 | List days = new List(); 24 | int firstWeekday = firstDay.weekday; 25 | DateTime lastDayPrevMonth = new DateTime(year, month, 0); 26 | DateTime prevMonth = new DateTime(year, month - 1); 27 | if (firstWeekday < 7) { 28 | // NOTE(mperrotte): ignore if sunday (no padding needed) 29 | for (int i = 0; i < firstWeekday; i++) { 30 | days.add(new Day( 31 | year: (month == 1) ? year - 1 : year, 32 | month: prevMonth.month, 33 | date: lastDayPrevMonth.day - i, 34 | today: false, 35 | )); 36 | } 37 | } 38 | return days; 39 | } 40 | 41 | List _padMonthEnding(DateTime lastDay) { 42 | List days = new List(); 43 | int lastWeekday = lastDay.weekday; 44 | DateTime firstDayNextMonth = new DateTime(year, month + 1, 1); 45 | DateTime nextMonth = new DateTime(year, month + 1); 46 | int remainingDays = ((6 - lastWeekday) == -1) ? 6 : (6 - lastWeekday); 47 | for (int i = 0; i < remainingDays; i++) { 48 | days.add(new Day( 49 | year: (month == 12) ? year + 1 : year, 50 | month: nextMonth.month, 51 | date: firstDayNextMonth.day + i, 52 | today: false, 53 | )); 54 | } 55 | return days; 56 | } 57 | 58 | List _generateMonthDays(DateTime firstDay, DateTime lastDay) { 59 | List days = []; 60 | for (int i = firstDay.day; i <= lastDay.day; i++) { 61 | if (i == date) { 62 | days.add(new Day(year: year, month: month, date: i, today: true)); 63 | } else { 64 | days.add(new Day(year: year, month: month, date: i, today: false)); 65 | } 66 | } 67 | // INFO(mperrotte): add padding to the beginnging of the month 68 | days.insertAll(0, _padMonthBeginning(firstDay)); 69 | // INFO(mperrotte): add padding to the ending of the month 70 | days.addAll(_padMonthEnding(lastDay)); 71 | return days; 72 | } 73 | 74 | List _generateMonthWeeks() { 75 | DateTime firstDay = new DateTime(year, month, 1); 76 | DateTime lastDay = new DateTime(year, month + 1, 0); 77 | List monthDays = _generateMonthDays(firstDay, lastDay); 78 | List weekList = new List(); 79 | for (int weeknum = 0; weeknum < (monthDays.length / 7); weeknum++) { 80 | List weekDays = new List(); 81 | // TODO(mperrotte): Look into using `List.sublist` here instead 82 | for (int weekday = (weeknum * 7); weekday < (weeknum * 7) + 7; weekday++) { 83 | weekDays.add(monthDays[weekday]); 84 | } 85 | weekList.add(new Week(days: weekDays)); 86 | } 87 | return weekList; 88 | } 89 | 90 | @override 91 | void initStores(ListenToStore listenToStore) { 92 | listenToStore(calendarStoreToken); 93 | } 94 | 95 | @override 96 | Widget build(BuildContext context, Map stores) { 97 | List monthWeeks = _generateMonthWeeks(); 98 | 99 | return new Expanded( 100 | child: new Container( 101 | margin: const EdgeInsets.all(8.0), 102 | child: new Column( 103 | children: [ 104 | [generateWeekHeader('short')], 105 | monthWeeks, 106 | ].expand((Iterable week) { 107 | return week; 108 | }).toList(), 109 | ), 110 | ), 111 | ); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /lib/src/stores.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_flux/flutter_flux.dart'; 2 | 3 | import 'package:calendar/src/data/data_model.dart'; 4 | import 'package:calendar/src/actions.dart'; 5 | import 'package:calendar/src/types.dart'; 6 | import 'package:calendar/controllers.dart'; 7 | 8 | Map> reduceEvents(List events) { 9 | Map> eventsByDate = new Map>(); 10 | return events.fold(eventsByDate, (prev, event) { 11 | if (prev.containsKey(event.date)) { 12 | prev[event.date].add(event); 13 | } else { 14 | prev[event.date] = new List(); 15 | prev[event.date].add(event); 16 | } 17 | return prev; 18 | }); 19 | } 20 | 21 | class CalendarStore extends Store { 22 | CalendarStore() { 23 | // NOTE(mperrotte): define action/reducers 24 | triggerOnAction(switchViewAction, (RenderableView view) { 25 | _currentView = view; 26 | }); 27 | triggerOnAction(selectDateAction, (Map currentDay) { 28 | _selectedDate = currentDay['date']; 29 | _selectedMonth = currentDay['month']; 30 | _selectedYear = currentDay['year']; 31 | }); 32 | triggerOnAction(removeEventAction, (int index) { 33 | _events.removeAt(index); 34 | _eventsByDate = reduceEvents(_events); 35 | }); 36 | 37 | _fetchDataReducer(Map funcs) async { 38 | dynamic payload = await funcs['payload']; 39 | List data = funcs['parseData'](payload); 40 | _events = data; 41 | _eventsByDate = reduceEvents(_events); 42 | trigger(); 43 | } 44 | 45 | fetchDataAction.listen(_fetchDataReducer); 46 | } 47 | 48 | // NOTE(mperrotte): define store properties 49 | RenderableView _currentView = RenderableView.calendar; 50 | int _selectedYear; 51 | int _selectedMonth; 52 | int _selectedDate; 53 | List _events = new List(); 54 | Map> _eventsByDate = new Map>(); 55 | 56 | // NOTE(mperrotte): define selectors 57 | RenderableView get currentView => _currentView; 58 | int get selectedYear => _selectedYear; 59 | int get selectedMonth => _selectedMonth; 60 | int get selectedDate => _selectedDate; 61 | List get events => _events; 62 | Map> get eventsByDate => _eventsByDate; 63 | Map get currentDay => { 64 | 'year': _selectedYear, 65 | 'month': _selectedMonth, 66 | 'date': _selectedDate, 67 | }; 68 | } 69 | 70 | class ControllerStore extends Store { 71 | ControllerStore() { 72 | // setCalendarControllerAction.listen((CalendarController controller) { 73 | // _calendarController = controller; 74 | // trigger(); 75 | // }); 76 | triggerOnAction(setCalendarControllerAction, (CalendarController controller) { 77 | _calendarController = controller; 78 | }); 79 | triggerOnAction(setDataControllerAction, (DataController controller) { 80 | _dataController = controller; 81 | }); 82 | } 83 | 84 | CalendarController _calendarController; 85 | DataController _dataController; 86 | 87 | // NOTE(mperrotte): created single selector with type interface 88 | getController(ControllerType controller) { 89 | switch (controller) { 90 | case ControllerType.calendar: 91 | return _calendarController; 92 | case ControllerType.data: 93 | return _dataController; 94 | } 95 | } 96 | } 97 | 98 | // NOTE(mperrotte): define store tokens 99 | final StoreToken calendarStoreToken = new StoreToken(new CalendarStore()); 100 | final StoreToken controllerStoreToken = new StoreToken(new ControllerStore()); 101 | -------------------------------------------------------------------------------- /lib/src/types.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter/widgets.dart'; 2 | import 'package:calendar/src/events/events_view.dart'; 3 | import 'package:calendar/src/data/data_model.dart'; 4 | 5 | const Map> MonthNames = const { 6 | 0: const {'short': 'Jan', 'long': 'January'}, 7 | 1: const {'short': 'Feb', 'long': 'February'}, 8 | 2: const {'short': 'Mar', 'long': 'March'}, 9 | 3: const {'short': 'Apr', 'long': 'April'}, 10 | 4: const {'short': 'May', 'long': 'May'}, 11 | 5: const {'short': 'June', 'long': 'June'}, 12 | 6: const {'short': 'July', 'long': 'July'}, 13 | 7: const {'short': 'Aug', 'long': 'August'}, 14 | 8: const {'short': 'Sep', 'long': 'September'}, 15 | 9: const {'short': 'Oct', 'long': 'October'}, 16 | 10: const {'short': 'Nov', 'long': 'November'}, 17 | 11: const {'short': 'Dec', 'long': 'December'} 18 | }; 19 | 20 | const Map> DayNames = const { 21 | 0: const {'short': 'Mon', 'long': 'Monday'}, 22 | 1: const {'short': 'Tue', 'long': 'Tuesday'}, 23 | 2: const {'short': 'Wed', 'long': 'Wednesday'}, 24 | 3: const {'short': 'Thur', 'long': 'Thursday'}, 25 | 4: const {'short': 'Fri', 'long': 'Friday'}, 26 | 5: const {'short': 'Sat', 'long': 'Saturday'}, 27 | 6: const {'short': 'Sun', 'long': 'Sunday'} 28 | }; 29 | 30 | enum RenderableView { 31 | calendar, 32 | events, 33 | event, 34 | } 35 | 36 | enum ControllerType { 37 | calendar, 38 | data, 39 | } 40 | 41 | typedef String DataCallback(); 42 | typedef EventsView RenderEventsCallback(List events); 43 | typedef dynamic FetchDataCallback(String uri); 44 | typedef String GetDataUriCallback(); 45 | typedef List ParseDataCallback(List payload); 46 | typedef List FilterEventsCallback(List events, Map currentDay); 47 | -------------------------------------------------------------------------------- /lib/src/week/week.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:calendar/src/day/day.dart'; 4 | 5 | class Week extends StatelessWidget { 6 | Week({ 7 | @required this.days, 8 | }); 9 | 10 | final List days; 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return new Row( 15 | children: days, 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/week/week_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:calendar/src/day/day_header.dart'; 5 | import 'package:calendar/utils.dart'; 6 | import 'week.dart'; 7 | 8 | class WeekHeader extends Week { 9 | WeekHeader({ 10 | @required this.days, 11 | }); 12 | 13 | final List days; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return new Row( 18 | children: days, 19 | ); 20 | } 21 | } 22 | 23 | WeekHeader generateWeekHeader(String nameFormat) { 24 | assert(nameFormat != null); 25 | List days = new List(); 26 | // INFO(mperrotte): add sunday first 27 | days.add(new DayHeader( 28 | day: DayNames[0][nameFormat], 29 | )); 30 | for (int i = 0; i < 6; i++) { 31 | days.add(new DayHeader( 32 | day: DayNames[i][nameFormat], 33 | )); 34 | } 35 | return new WeekHeader( 36 | days: days, 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /lib/utils.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Utility Exports 3 | /// 4 | export 'src/actions.dart'; 5 | export 'src/stores.dart'; 6 | export 'src/types.dart'; 7 | -------------------------------------------------------------------------------- /mock-api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const router = express.Router(); 5 | const data = require('./mock-data.js'); 6 | 7 | const PORT = 4000; 8 | 9 | router.route('/') 10 | .get((req, res, next) => { 11 | res.json(data); 12 | }); 13 | 14 | let app = express(); 15 | 16 | app.use('/events', router); 17 | 18 | app.listen(PORT, () => { 19 | console.log(`api listening on port ${PORT}...`); 20 | }); 21 | -------------------------------------------------------------------------------- /mock-data.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mockData = []; 4 | 5 | for (let i = 1; i <= 16; i++) { 6 | if (i <= 5) { 7 | mockData.push({ 8 | id: i, 9 | title: `Event ${i}`, 10 | url: `/events/${i}`, 11 | date_start: '2016-12-25 12:00:00.000', 12 | date_end: '2016-12-25 13:00:00.000', 13 | details: 'anything' 14 | }); 15 | } else if (i <= 13) { 16 | mockData.push({ 17 | id: i, 18 | title: `Event ${i}`, 19 | url: `/events/${i}`, 20 | date_start: '2016-12-21 12:00:00.000', 21 | date_end: '2016-12-21 13:00:00.000', 22 | details: { 23 | foo: 'bar' 24 | } 25 | }); 26 | } else { 27 | mockData.push({ 28 | id: i, 29 | title: `Event ${i}`, 30 | url: `/events/${i}`, 31 | date_start: '2016-12-23 12:00:00.000', 32 | date_end: '2016-12-23 13:00:00.000', 33 | details: 10 34 | }) 35 | } 36 | } 37 | 38 | module.exports = mockData; 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "calendar", 3 | "version": "0.0.1", 4 | "description": "A flutter widget to display a calendar with some events.", 5 | "main": "mock-api.js", 6 | "scripts": { 7 | "start": "node mock-api.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/mikemimik/flutter-calendar.git" 12 | }, 13 | "keywords": [], 14 | "author": "Michael Perrotte ", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/mikemimik/flutter-calendar/issues" 18 | }, 19 | "homepage": "https://github.com/mikemimik/flutter-calendar#readme", 20 | "dependencies": { 21 | "express": "^4.14.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: calendar 2 | description: Flutter Calendar Component 3 | version: 0.0.2 4 | author: Michael Perrotte 5 | homepage: 6 | 7 | environment: 8 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | flutter_flux: '>=4.0.1' 14 | http: '>=0.11.3+14' 15 | 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | 21 | flutter: 22 | --------------------------------------------------------------------------------