├── .flutter-plugins ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── adhara_markdown.iml ├── android ├── app │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── flutter │ │ └── plugins │ │ └── GeneratedPluginRegistrant.java └── local.properties ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── 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.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── flutter_export_environment.sh │ ├── Podfile │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.yaml └── test │ └── widget_test.dart ├── lib ├── adhara_markdown.dart ├── mdbean.dart ├── mdeditor.dart ├── mdviewer.dart └── utils.dart ├── pubspec.lock ├── pubspec.yaml └── test └── adhara_markdown_test.dart /.flutter-plugins: -------------------------------------------------------------------------------- 1 | url_launcher=/Users/rohit/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-4.2.0/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | ios/.generated/ 9 | ios/Flutter/Generated.xcconfig 10 | ios/Runner/GeneratedPluginRegistrant.* 11 | 12 | .idea/ 13 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.2.0] - 26 Mar, 2020 2 | 3 | * Upgrade project to support new flutter releases (by [sbu-WBT(https://github.com/sbu-WBT)) 4 | 5 | ## [0.1.2] - 5th April, 2019 6 | 7 | * Fix for optional parameter [PR3](https://github.com/infitio/flutter_markdown/pull/3) 8 | 9 | ## [0.1.1] - 23rd October, 2019 10 | 11 | * Upgrade dependencies 12 | 13 | 14 | ## [0.1.0] - 08th Feb, 2019 15 | 16 | * Minimalistic, highly customizable, regexp based markdown editor and viewer by adhara 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Rohit R. Abbadi 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # adhara_markdown 2 | 3 | Minimalistic, highly customizable markdown editor and viewer by adhara 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Dart 8 | [package](https://flutter.io/developing-packages/), 9 | a library module containing code that can be shared easily across 10 | multiple Flutter or Dart projects. 11 | 12 | For help getting started with Flutter, view our 13 | [online documentation](https://flutter.io/docs), which offers tutorials, 14 | samples, guidance on mobile development, and a full API reference. 15 | -------------------------------------------------------------------------------- /adhara_markdown.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java: -------------------------------------------------------------------------------- 1 | package io.flutter.plugins; 2 | 3 | import io.flutter.plugin.common.PluginRegistry; 4 | import io.flutter.plugins.urllauncher.UrlLauncherPlugin; 5 | 6 | /** 7 | * Generated file. Do not edit. 8 | */ 9 | public final class GeneratedPluginRegistrant { 10 | public static void registerWith(PluginRegistry registry) { 11 | if (alreadyRegisteredWith(registry)) { 12 | return; 13 | } 14 | UrlLauncherPlugin.registerWith(registry.registrarFor("io.flutter.plugins.urllauncher.UrlLauncherPlugin")); 15 | } 16 | 17 | private static boolean alreadyRegisteredWith(PluginRegistry registry) { 18 | final String key = GeneratedPluginRegistrant.class.getCanonicalName(); 19 | if (registry.hasPlugin(key)) { 20 | return true; 21 | } 22 | registry.registrarFor(key); 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android/local.properties: -------------------------------------------------------------------------------- 1 | sdk.dir=/Users/rohit/Library/Android/sdk 2 | flutter.sdk=/Users/rohit/flutter 3 | flutter.versionName=0.0.1 -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 30 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.example.example" 37 | minSdkVersion 16 38 | targetSdkVersion 30 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 34 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:4.1.2' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/rohit/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/rohit/workspace/opensource/adhara_markdown/example" 5 | export "FLUTTER_TARGET=lib/main.dart" 6 | export "FLUTTER_BUILD_DIR=build" 7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios" 8 | export "FLUTTER_FRAMEWORK_DIR=/Users/rohit/flutter/bin/cache/artifacts/engine/ios" 9 | export "FLUTTER_BUILD_NAME=0.0.1" 10 | export "FLUTTER_BUILD_NUMBER=0.0.1" 11 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Using a CDN with CocoaPods 1.7.2 or later can save a lot of time on pod installation, but it's experimental rather than the default. 2 | # source 'https://cdn.cocoapods.org/' 3 | 4 | # Uncomment this line to define a global platform for your project 5 | # platform :ios, '9.0' 6 | 7 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 8 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 9 | 10 | project 'Runner', { 11 | 'Debug' => :debug, 12 | 'Profile' => :release, 13 | 'Release' => :release, 14 | } 15 | 16 | def parse_KV_file(file, separator='=') 17 | file_abs_path = File.expand_path(file) 18 | if !File.exists? file_abs_path 19 | return []; 20 | end 21 | pods_ary = [] 22 | skip_line_start_symbols = ["#", "/"] 23 | File.foreach(file_abs_path) { |line| 24 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 25 | plugin = line.split(pattern=separator) 26 | if plugin.length == 2 27 | podname = plugin[0].strip() 28 | path = plugin[1].strip() 29 | podpath = File.expand_path("#{path}", file_abs_path) 30 | pods_ary.push({:name => podname, :path => podpath}); 31 | else 32 | puts "Invalid plugin specification: #{line}" 33 | end 34 | } 35 | return pods_ary 36 | end 37 | 38 | target 'Runner' do 39 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 40 | # referring to absolute paths on developers' machines. 41 | system('rm -rf .symlinks') 42 | system('mkdir -p .symlinks/plugins') 43 | 44 | # Flutter Pods 45 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 46 | if generated_xcode_build_settings.empty? 47 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." 48 | end 49 | generated_xcode_build_settings.map { |p| 50 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 51 | symlink = File.join('.symlinks', 'flutter') 52 | File.symlink(File.dirname(p[:path]), symlink) 53 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 54 | end 55 | } 56 | 57 | # Plugin Pods 58 | plugin_pods = parse_KV_file('../.flutter-plugins') 59 | plugin_pods.map { |p| 60 | symlink = File.join('.symlinks', 'plugins', p[:name]) 61 | File.symlink(p[:path], symlink) 62 | pod p[:name], :path => File.join(symlink, 'ios') 63 | } 64 | end 65 | 66 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. 67 | install! 'cocoapods', :disable_input_output_paths => true 68 | 69 | post_install do |installer| 70 | installer.pods_project.targets.each do |target| 71 | target.build_configurations.each do |config| 72 | config.build_settings['ENABLE_BITCODE'] = 'NO' 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /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 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 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 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 19 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 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 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 44 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 45 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 46 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 47 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 50 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; 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 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 66 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 9740EEB11CF90186004384FC /* Flutter */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 77 | 3B80C3931E831B6300D905FE /* App.framework */, 78 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 79 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 80 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 81 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 82 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 83 | ); 84 | name = Flutter; 85 | sourceTree = ""; 86 | }; 87 | 97C146E51CF9000F007C117D = { 88 | isa = PBXGroup; 89 | children = ( 90 | 9740EEB11CF90186004384FC /* Flutter */, 91 | 97C146F01CF9000F007C117D /* Runner */, 92 | 97C146EF1CF9000F007C117D /* Products */, 93 | CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | 97C146EF1CF9000F007C117D /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 97C146EE1CF9000F007C117D /* Runner.app */, 101 | ); 102 | name = Products; 103 | sourceTree = ""; 104 | }; 105 | 97C146F01CF9000F007C117D /* Runner */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 109 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 110 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 111 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 112 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 113 | 97C147021CF9000F007C117D /* Info.plist */, 114 | 97C146F11CF9000F007C117D /* Supporting Files */, 115 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 116 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 117 | ); 118 | path = Runner; 119 | sourceTree = ""; 120 | }; 121 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 97C146F21CF9000F007C117D /* main.m */, 125 | ); 126 | name = "Supporting Files"; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | 97C146ED1CF9000F007C117D /* Runner */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 135 | buildPhases = ( 136 | 9740EEB61CF901F6004384FC /* Run Script */, 137 | 97C146EA1CF9000F007C117D /* Sources */, 138 | 97C146EB1CF9000F007C117D /* Frameworks */, 139 | 97C146EC1CF9000F007C117D /* Resources */, 140 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 142 | ); 143 | buildRules = ( 144 | ); 145 | dependencies = ( 146 | ); 147 | name = Runner; 148 | productName = Runner; 149 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 150 | productType = "com.apple.product-type.application"; 151 | }; 152 | /* End PBXNativeTarget section */ 153 | 154 | /* Begin PBXProject section */ 155 | 97C146E61CF9000F007C117D /* Project object */ = { 156 | isa = PBXProject; 157 | attributes = { 158 | LastUpgradeCheck = 0910; 159 | ORGANIZATIONNAME = "The Chromium Authors"; 160 | TargetAttributes = { 161 | 97C146ED1CF9000F007C117D = { 162 | CreatedOnToolsVersion = 7.3.1; 163 | }; 164 | }; 165 | }; 166 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 167 | compatibilityVersion = "Xcode 3.2"; 168 | developmentRegion = English; 169 | hasScannedForEncodings = 0; 170 | knownRegions = ( 171 | en, 172 | Base, 173 | ); 174 | mainGroup = 97C146E51CF9000F007C117D; 175 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 176 | projectDirPath = ""; 177 | projectRoot = ""; 178 | targets = ( 179 | 97C146ED1CF9000F007C117D /* Runner */, 180 | ); 181 | }; 182 | /* End PBXProject section */ 183 | 184 | /* Begin PBXResourcesBuildPhase section */ 185 | 97C146EC1CF9000F007C117D /* Resources */ = { 186 | isa = PBXResourcesBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 190 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 191 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 192 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 193 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 194 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXResourcesBuildPhase section */ 199 | 200 | /* Begin PBXShellScriptBuildPhase section */ 201 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 202 | isa = PBXShellScriptBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | ); 206 | inputPaths = ( 207 | ); 208 | name = "Thin Binary"; 209 | outputPaths = ( 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | shellPath = /bin/sh; 213 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 214 | }; 215 | 9740EEB61CF901F6004384FC /* Run Script */ = { 216 | isa = PBXShellScriptBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | ); 220 | inputPaths = ( 221 | ); 222 | name = "Run Script"; 223 | outputPaths = ( 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | shellPath = /bin/sh; 227 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 228 | }; 229 | /* End PBXShellScriptBuildPhase section */ 230 | 231 | /* Begin PBXSourcesBuildPhase section */ 232 | 97C146EA1CF9000F007C117D /* Sources */ = { 233 | isa = PBXSourcesBuildPhase; 234 | buildActionMask = 2147483647; 235 | files = ( 236 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 237 | 97C146F31CF9000F007C117D /* main.m in Sources */, 238 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | }; 242 | /* End PBXSourcesBuildPhase section */ 243 | 244 | /* Begin PBXVariantGroup section */ 245 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | 97C146FB1CF9000F007C117D /* Base */, 249 | ); 250 | name = Main.storyboard; 251 | sourceTree = ""; 252 | }; 253 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 254 | isa = PBXVariantGroup; 255 | children = ( 256 | 97C147001CF9000F007C117D /* Base */, 257 | ); 258 | name = LaunchScreen.storyboard; 259 | sourceTree = ""; 260 | }; 261 | /* End PBXVariantGroup section */ 262 | 263 | /* Begin XCBuildConfiguration section */ 264 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 265 | isa = XCBuildConfiguration; 266 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 267 | buildSettings = { 268 | ALWAYS_SEARCH_USER_PATHS = NO; 269 | CLANG_ANALYZER_NONNULL = YES; 270 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 271 | CLANG_CXX_LIBRARY = "libc++"; 272 | CLANG_ENABLE_MODULES = YES; 273 | CLANG_ENABLE_OBJC_ARC = YES; 274 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 275 | CLANG_WARN_BOOL_CONVERSION = YES; 276 | CLANG_WARN_COMMA = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 279 | CLANG_WARN_EMPTY_BODY = YES; 280 | CLANG_WARN_ENUM_CONVERSION = YES; 281 | CLANG_WARN_INFINITE_RECURSION = YES; 282 | CLANG_WARN_INT_CONVERSION = YES; 283 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 284 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 285 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 286 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 287 | CLANG_WARN_STRICT_PROTOTYPES = YES; 288 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 289 | CLANG_WARN_UNREACHABLE_CODE = YES; 290 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 291 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 292 | COPY_PHASE_STRIP = NO; 293 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 294 | ENABLE_NS_ASSERTIONS = NO; 295 | ENABLE_STRICT_OBJC_MSGSEND = YES; 296 | GCC_C_LANGUAGE_STANDARD = gnu99; 297 | GCC_NO_COMMON_BLOCKS = YES; 298 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 299 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 300 | GCC_WARN_UNDECLARED_SELECTOR = YES; 301 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 302 | GCC_WARN_UNUSED_FUNCTION = YES; 303 | GCC_WARN_UNUSED_VARIABLE = YES; 304 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 305 | MTL_ENABLE_DEBUG_INFO = NO; 306 | SDKROOT = iphoneos; 307 | TARGETED_DEVICE_FAMILY = "1,2"; 308 | VALIDATE_PRODUCT = YES; 309 | }; 310 | name = Profile; 311 | }; 312 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 313 | isa = XCBuildConfiguration; 314 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 315 | buildSettings = { 316 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 317 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 318 | DEVELOPMENT_TEAM = S8QB4VV633; 319 | ENABLE_BITCODE = NO; 320 | FRAMEWORK_SEARCH_PATHS = ( 321 | "$(inherited)", 322 | "$(PROJECT_DIR)/Flutter", 323 | ); 324 | INFOPLIST_FILE = Runner/Info.plist; 325 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 326 | LIBRARY_SEARCH_PATHS = ( 327 | "$(inherited)", 328 | "$(PROJECT_DIR)/Flutter", 329 | ); 330 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 331 | PRODUCT_NAME = "$(TARGET_NAME)"; 332 | VERSIONING_SYSTEM = "apple-generic"; 333 | }; 334 | name = Profile; 335 | }; 336 | 97C147031CF9000F007C117D /* Debug */ = { 337 | isa = XCBuildConfiguration; 338 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 339 | buildSettings = { 340 | ALWAYS_SEARCH_USER_PATHS = NO; 341 | CLANG_ANALYZER_NONNULL = YES; 342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 343 | CLANG_CXX_LIBRARY = "libc++"; 344 | CLANG_ENABLE_MODULES = YES; 345 | CLANG_ENABLE_OBJC_ARC = YES; 346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 347 | CLANG_WARN_BOOL_CONVERSION = YES; 348 | CLANG_WARN_COMMA = YES; 349 | CLANG_WARN_CONSTANT_CONVERSION = YES; 350 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 351 | CLANG_WARN_EMPTY_BODY = YES; 352 | CLANG_WARN_ENUM_CONVERSION = YES; 353 | CLANG_WARN_INFINITE_RECURSION = YES; 354 | CLANG_WARN_INT_CONVERSION = YES; 355 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 356 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 357 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 358 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 359 | CLANG_WARN_STRICT_PROTOTYPES = YES; 360 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 361 | CLANG_WARN_UNREACHABLE_CODE = YES; 362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 363 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 364 | COPY_PHASE_STRIP = NO; 365 | DEBUG_INFORMATION_FORMAT = dwarf; 366 | ENABLE_STRICT_OBJC_MSGSEND = YES; 367 | ENABLE_TESTABILITY = YES; 368 | GCC_C_LANGUAGE_STANDARD = gnu99; 369 | GCC_DYNAMIC_NO_PIC = NO; 370 | GCC_NO_COMMON_BLOCKS = YES; 371 | GCC_OPTIMIZATION_LEVEL = 0; 372 | GCC_PREPROCESSOR_DEFINITIONS = ( 373 | "DEBUG=1", 374 | "$(inherited)", 375 | ); 376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 378 | GCC_WARN_UNDECLARED_SELECTOR = YES; 379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 380 | GCC_WARN_UNUSED_FUNCTION = YES; 381 | GCC_WARN_UNUSED_VARIABLE = YES; 382 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 383 | MTL_ENABLE_DEBUG_INFO = YES; 384 | ONLY_ACTIVE_ARCH = YES; 385 | SDKROOT = iphoneos; 386 | TARGETED_DEVICE_FAMILY = "1,2"; 387 | }; 388 | name = Debug; 389 | }; 390 | 97C147041CF9000F007C117D /* Release */ = { 391 | isa = XCBuildConfiguration; 392 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 393 | buildSettings = { 394 | ALWAYS_SEARCH_USER_PATHS = NO; 395 | CLANG_ANALYZER_NONNULL = YES; 396 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 397 | CLANG_CXX_LIBRARY = "libc++"; 398 | CLANG_ENABLE_MODULES = YES; 399 | CLANG_ENABLE_OBJC_ARC = YES; 400 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 401 | CLANG_WARN_BOOL_CONVERSION = YES; 402 | CLANG_WARN_COMMA = YES; 403 | CLANG_WARN_CONSTANT_CONVERSION = YES; 404 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 405 | CLANG_WARN_EMPTY_BODY = YES; 406 | CLANG_WARN_ENUM_CONVERSION = YES; 407 | CLANG_WARN_INFINITE_RECURSION = YES; 408 | CLANG_WARN_INT_CONVERSION = YES; 409 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 412 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 413 | CLANG_WARN_STRICT_PROTOTYPES = YES; 414 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 415 | CLANG_WARN_UNREACHABLE_CODE = YES; 416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 417 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 418 | COPY_PHASE_STRIP = NO; 419 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 420 | ENABLE_NS_ASSERTIONS = NO; 421 | ENABLE_STRICT_OBJC_MSGSEND = YES; 422 | GCC_C_LANGUAGE_STANDARD = gnu99; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 425 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 426 | GCC_WARN_UNDECLARED_SELECTOR = YES; 427 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 428 | GCC_WARN_UNUSED_FUNCTION = YES; 429 | GCC_WARN_UNUSED_VARIABLE = YES; 430 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 431 | MTL_ENABLE_DEBUG_INFO = NO; 432 | SDKROOT = iphoneos; 433 | TARGETED_DEVICE_FAMILY = "1,2"; 434 | VALIDATE_PRODUCT = YES; 435 | }; 436 | name = Release; 437 | }; 438 | 97C147061CF9000F007C117D /* Debug */ = { 439 | isa = XCBuildConfiguration; 440 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 441 | buildSettings = { 442 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 443 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 444 | ENABLE_BITCODE = NO; 445 | FRAMEWORK_SEARCH_PATHS = ( 446 | "$(inherited)", 447 | "$(PROJECT_DIR)/Flutter", 448 | ); 449 | INFOPLIST_FILE = Runner/Info.plist; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 451 | LIBRARY_SEARCH_PATHS = ( 452 | "$(inherited)", 453 | "$(PROJECT_DIR)/Flutter", 454 | ); 455 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 456 | PRODUCT_NAME = "$(TARGET_NAME)"; 457 | VERSIONING_SYSTEM = "apple-generic"; 458 | }; 459 | name = Debug; 460 | }; 461 | 97C147071CF9000F007C117D /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 464 | buildSettings = { 465 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 466 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 467 | ENABLE_BITCODE = NO; 468 | FRAMEWORK_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "$(PROJECT_DIR)/Flutter", 471 | ); 472 | INFOPLIST_FILE = Runner/Info.plist; 473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 474 | LIBRARY_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "$(PROJECT_DIR)/Flutter", 477 | ); 478 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | VERSIONING_SYSTEM = "apple-generic"; 481 | }; 482 | name = Release; 483 | }; 484 | /* End XCBuildConfiguration section */ 485 | 486 | /* Begin XCConfigurationList section */ 487 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 488 | isa = XCConfigurationList; 489 | buildConfigurations = ( 490 | 97C147031CF9000F007C117D /* Debug */, 491 | 97C147041CF9000F007C117D /* Release */, 492 | 249021D3217E4FDB00AE95B9 /* Profile */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 498 | isa = XCConfigurationList; 499 | buildConfigurations = ( 500 | 97C147061CF9000F007C117D /* Debug */, 501 | 97C147071CF9000F007C117D /* Release */, 502 | 249021D4217E4FDB00AE95B9 /* Profile */, 503 | ); 504 | defaultConfigurationIsVisible = 0; 505 | defaultConfigurationName = Release; 506 | }; 507 | /* End XCConfigurationList section */ 508 | }; 509 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 510 | } 511 | -------------------------------------------------------------------------------- /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 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/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/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infitio/flutter_markdown/28a93bf4f4d85d54850d5b4ce8d269e09b636d49/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | 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 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:adhara_markdown/adhara_markdown.dart'; 3 | 4 | main() => runApp(App()); 5 | 6 | List storyPieces = [ 7 | "There were once *two brothers* who lived on the *edge of a forest*." 8 | " The elder brother was very _mean_ to his younger brother and _ate up all the food and took all his good clothes_." 9 | " One day, the elder brother went into the forest to find some `firewood` to `sell in the market`." 10 | " As he went around chopping the branches of a tree after tree, he came upon a `magical tree`." 11 | " The tree said to him, 'Oh kind sir, please do not cut my branches. If you spare me, I will give you my golden apples'." 12 | " The elder brother agreed but was ~disappointed~ with the number apples the tree gave him. Greed overcame him, and he threatened to cut the entire trunk if the tree didn’t give him more apples. The magical tree instead showered upon the elder brother hundreds upon hundreds of tiny needles. The elder brother lay on the ground crying in pain as the sun began to lower down the horizon.", 13 | "*The younger brother grew worried and went in search of his elder brother.*" 14 | " He found him with hundreds of needles on his skin." 15 | " He rushed to his brother and removed each needle with painstaking love." 16 | " After he finished, the elder brother apologised for treating him badly and promised to be better." 17 | " The tree saw the change in the elder brother’s heart and gave them all the golden apples they could ever need." 18 | ]; 19 | 20 | class App extends StatelessWidget { 21 | @override 22 | Widget build(BuildContext context) { 23 | return MaterialApp( 24 | debugShowCheckedModeBanner: false, 25 | home: HomePage(), 26 | theme: new ThemeData( 27 | primaryColor: Colors.blue, backgroundColor: Colors.white), 28 | color: Colors.blue); 29 | } 30 | } 31 | 32 | class HomePage extends StatefulWidget { 33 | @override 34 | State createState() => HomePageState(); 35 | } 36 | 37 | class HomePageState extends State { 38 | int editingPiece = -1; 39 | MarkdownEditorController controller; 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return Scaffold( 44 | appBar: AppBar( 45 | title: Text("MD Viewer & Editor"), 46 | actions: [ 47 | IconButton( 48 | icon: Icon( 49 | Icons.info, 50 | color: Colors.white, 51 | ), 52 | onPressed: () { 53 | showAboutDialog( 54 | context: context, 55 | applicationName: "Adhara MD Editor", 56 | children: [ 57 | Text( 58 | "How to use", 59 | style: TextStyle( 60 | fontWeight: FontWeight.bold, fontSize: 18.0), 61 | ), 62 | Text("Tap on the paragraphs to change to edit mode."), 63 | Text("edit and click on update FAB") 64 | ]); 65 | // showDialog( 66 | // context: context, 67 | // builder: (BuildContext context){ 68 | // return Text("ad"); 69 | // } 70 | // ); 71 | }) 72 | ], 73 | ), 74 | floatingActionButton: (editingPiece == -1) 75 | ? null 76 | : FloatingActionButton( 77 | child: Icon(Icons.check), 78 | onPressed: () { 79 | setState(() { 80 | storyPieces[editingPiece] = controller.text; 81 | editingPiece = -1; 82 | }); 83 | }, 84 | ), 85 | body: Container( 86 | padding: EdgeInsets.all(12.0), 87 | child: ListView( 88 | children: [ 89 | _buildStory(storyPieces[0], 0), 90 | SizedBox(height: 8.0), 91 | _buildStory(storyPieces[1], 1) 92 | ], 93 | ), 94 | ), 95 | ); 96 | } 97 | 98 | get textStyle => TextStyle(fontSize: 18.0, color: Colors.black); 99 | get highlightedTextStyle => 100 | TextStyle(fontSize: 18.0, color: Colors.lightBlue); 101 | 102 | _buildStory(String storyPiece, int pieceIndex) { 103 | if (editingPiece == pieceIndex) { 104 | return _buildStoryEditor(storyPiece, pieceIndex); 105 | } 106 | return GestureDetector( 107 | child: MarkdownViewer( 108 | content: storyPiece, 109 | textStyle: textStyle, 110 | formatTypes: [ 111 | MarkdownTokenTypes.bold, 112 | MarkdownTokenTypes.italic, 113 | MarkdownTokenTypes.strikeThrough, 114 | MarkdownTokenTypes.code 115 | ], 116 | ), 117 | onTap: () { 118 | setState(() { 119 | editingPiece = pieceIndex; 120 | }); 121 | }, 122 | ); 123 | } 124 | 125 | _buildStoryEditor(String storyPiece, pieceIndex) { 126 | controller = MarkdownEditorController(); 127 | return Container( 128 | child: Column( 129 | children: [ 130 | MarkdownEditor( 131 | value: storyPiece, 132 | textStyle: TextStyle(fontSize: 18.0, color: Colors.black), 133 | controller: controller, 134 | tokenConfigs: [ 135 | MarkdownTokenConfig.mention(textStyle: highlightedTextStyle), 136 | MarkdownTokenConfig.link(textStyle: highlightedTextStyle), 137 | MarkdownTokenConfig.hashTag(textStyle: highlightedTextStyle), 138 | ], 139 | ), 140 | ], 141 | ), 142 | ); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: adhara_markdown_example 2 | description: Minimalistic, highly customizable, regexp based markdown editor and viewer by adhara - Example 3 | version: 0.0.1 4 | author: 5 | homepage: 6 | 7 | publish_to: 'none' 8 | 9 | environment: 10 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 11 | 12 | dependencies: 13 | flutter: 14 | sdk: flutter 15 | adhara_markdown: 16 | path: ../ 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | 22 | flutter: 23 | uses-material-design: true 24 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | //// This is a basic Flutter widget test. 2 | //// 3 | //// To perform an interaction with a widget in your test, use the WidgetTester 4 | //// utility that Flutter provides. For example, you can send tap and scroll 5 | //// gestures. You can also use WidgetTester to find child widgets in the widget 6 | //// tree, read text, and verify that the values of widget properties are correct. 7 | // 8 | //import 'package:flutter/material.dart'; 9 | //import 'package:flutter_test/flutter_test.dart'; 10 | // 11 | //import 'package:example/main.dart'; 12 | // 13 | //void main() { 14 | // testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // // Build our app and trigger a frame. 16 | // await tester.pumpWidget(MyApp()); 17 | // 18 | // // Verify that our counter starts at 0. 19 | // expect(find.text('0'), findsOneWidget); 20 | // expect(find.text('1'), findsNothing); 21 | // 22 | // // Tap the '+' icon and trigger a frame. 23 | // await tester.tap(find.byIcon(Icons.add)); 24 | // await tester.pump(); 25 | // 26 | // // Verify that our counter has incremented. 27 | // expect(find.text('0'), findsNothing); 28 | // expect(find.text('1'), findsOneWidget); 29 | // }); 30 | //} 31 | -------------------------------------------------------------------------------- /lib/adhara_markdown.dart: -------------------------------------------------------------------------------- 1 | library adhara_markdown; 2 | 3 | export 'package:adhara_markdown/mdbean.dart'; 4 | export 'package:adhara_markdown/mdeditor.dart'; 5 | export 'package:adhara_markdown/mdviewer.dart'; 6 | export 'package:adhara_markdown/utils.dart'; 7 | -------------------------------------------------------------------------------- /lib/mdbean.dart: -------------------------------------------------------------------------------- 1 | class MarkDownBean { 2 | String content; 3 | MarkdownMeta meta; 4 | } 5 | 6 | class MarkdownMeta { 7 | List collection; 8 | 9 | MarkdownMeta(this.collection) { 10 | if (collection == null) { 11 | collection = []; 12 | } else { 13 | collection.sort((SelectionInfo selection1, SelectionInfo selection2) => 14 | selection1.startIndex.compareTo(selection2.startIndex)); 15 | } 16 | } 17 | 18 | SelectionInfo selectionMeta(int user) => collection[user]; 19 | 20 | add(int user, SelectionInfo meta) { 21 | collection[user] = meta; 22 | } 23 | 24 | remove(int user) { 25 | collection.remove(user); 26 | } 27 | } 28 | 29 | class SelectionInfo { 30 | int startIndex; 31 | int endIndex; 32 | dynamic data; 33 | 34 | SelectionInfo(this.startIndex, this.endIndex, this.data); 35 | 36 | void updateIndex(int newStartIndex) { 37 | this.endIndex += newStartIndex - this.startIndex; 38 | this.startIndex = newStartIndex; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/mdeditor.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:adhara_markdown/mdbean.dart'; 3 | import 'package:adhara_markdown/mdviewer.dart'; 4 | import 'package:adhara_markdown/utils.dart'; 5 | 6 | class MarkdownEditor extends StatefulWidget { 7 | final String value; 8 | final String hint; 9 | final bool autoFocus; 10 | final OnSavedCallback onSaved; 11 | final List tokenConfigs; 12 | final TextStyle textStyle; 13 | final TextStyle highlightedTextStyle; 14 | final MarkDownBean bean; 15 | final MarkdownEditorController controller; 16 | final InputDecoration decoration; 17 | final FormFieldSetter onChange; 18 | final BoxConstraints suggestionsConstraints; 19 | final Offset suggestionsOffset; 20 | 21 | MarkdownEditor( 22 | {Key key, 23 | this.value, 24 | this.hint, 25 | this.autoFocus, 26 | this.onSaved, 27 | this.onChange, 28 | this.controller, 29 | this.tokenConfigs, 30 | this.textStyle, 31 | this.highlightedTextStyle, 32 | this.decoration, 33 | this.suggestionsConstraints, 34 | this.suggestionsOffset: Offset.zero, 35 | MarkDownBean bean}) 36 | : bean = bean ?? MarkDownBean(), 37 | super(key: key); 38 | 39 | @override 40 | _MarkdownEditorState createState() => _MarkdownEditorState(); 41 | } 42 | 43 | class _MarkdownEditorState extends State 44 | with WidgetsBindingObserver { 45 | TextEditingController textEditingController; 46 | int currentContentLength; 47 | Match match; 48 | List suggestions = []; 49 | MarkdownTokenConfig tokenConfig; 50 | 51 | TextStyle baseTextStyle = TextStyle( 52 | color: const Color(0xff273d52), 53 | fontWeight: FontWeight.w400, 54 | fontFamily: "SFProText", 55 | fontStyle: FontStyle.normal, 56 | fontSize: 14.0, 57 | ); 58 | 59 | GlobalKey _editorKey = GlobalKey(); 60 | OverlayState overlayState; 61 | 62 | @override 63 | void initState() { 64 | super.initState(); 65 | textEditingController = TextEditingController(text: widget.value); 66 | WidgetsBinding.instance.addObserver(this); 67 | widget.controller?._state = 68 | this; //must be called after setting textEditingController 69 | currentContentLength = textEditingController.text.length; 70 | overlayState = Overlay.of(context); 71 | textEditingController.addListener(_listenTextInput); 72 | } 73 | 74 | InputDecoration get _decoration => 75 | widget.decoration ?? 76 | InputDecoration( 77 | contentPadding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), 78 | hintText: widget.hint, 79 | hintStyle: baseTextStyle.copyWith(color: const Color(0x80273d52)), 80 | border: InputBorder.none, 81 | ); 82 | 83 | @override 84 | Widget build(BuildContext context) { 85 | final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context); 86 | TextStyle effectiveTextStyle = widget.textStyle; 87 | if (widget.textStyle == null || widget.textStyle.inherit) 88 | effectiveTextStyle = defaultTextStyle.style.merge(widget.textStyle); 89 | double topOffset = _decoration.labelStyle?.fontSize ?? 0.0; 90 | if (_decoration.hintStyle != null) { 91 | topOffset += _decoration.hintStyle.fontSize - effectiveTextStyle.fontSize; 92 | } 93 | /*if(_decoration.contentPadding!=null){ 94 | topOffset += _decoration.contentPadding.vertical/2; 95 | }*/ 96 | return Stack( 97 | key: _editorKey, 98 | children: [ 99 | //highlighted rich text 100 | Container( 101 | padding: 102 | _decoration.contentPadding?.add(EdgeInsets.only(top: topOffset)), 103 | child: MarkdownViewer( 104 | content: textEditingController.text, 105 | collapsible: false, 106 | textStyle: effectiveTextStyle, 107 | highlightedTextStyle: widget.highlightedTextStyle, 108 | tokenConfigs: widget.tokenConfigs, 109 | /*formatTypes: [ 110 | MarkdownTokenTypes.link, 111 | MarkdownTokenTypes.mention, 112 | MarkdownTokenTypes.hashTag 113 | ]*/ 114 | ), 115 | ), 116 | //Text input box 117 | TextFormField( 118 | controller: textEditingController, 119 | autofocus: widget.autoFocus ?? true, 120 | keyboardType: TextInputType.multiline, 121 | maxLines: null, 122 | style: effectiveTextStyle.copyWith(color: Colors.transparent), 123 | // style: effectiveTextStyle.copyWith(color: Colors.grey.withOpacity(0.1)), 124 | decoration: _decoration, 125 | onSaved: widget.onSaved), 126 | ], 127 | ); 128 | } 129 | 130 | @override 131 | void didChangeMetrics() { 132 | _listenTextInput(); 133 | } 134 | 135 | _listenTextInput() async { 136 | setState(() { 137 | suggestions = []; 138 | match = null; 139 | }); 140 | if (textEditingController != null) { 141 | if (textEditingController.text.length < 1) { 142 | suggestions = []; 143 | for (MarkdownTokenConfig _tokenConfig in widget.tokenConfigs) { 144 | _tokenConfig.meta?.collection = []; 145 | } 146 | } else { 147 | int indexNow = textEditingController.selection.baseOffset - 1; 148 | if (indexNow < 0) return; 149 | for (MarkdownTokenConfig _tokenConfig in widget.tokenConfigs) { 150 | if (_tokenConfig.hintRegExp != null) { 151 | for (Match m in _tokenConfig.hintRegExp 152 | .allMatches(textEditingController.text)) { 153 | if (m.start < indexNow + 1 && m.end >= indexNow + 1) { 154 | if (_tokenConfig.suggestions != null) { 155 | suggestions = await _tokenConfig.suggestions( 156 | textEditingController.text 157 | .substring(m.start, indexNow + 1)); 158 | } else { 159 | suggestions = []; 160 | } 161 | match = m; 162 | tokenConfig = _tokenConfig; 163 | break; 164 | } 165 | } 166 | if (match != null) break; 167 | } 168 | } 169 | // postMeta index update 170 | int textLength = textEditingController.text.length; 171 | if (currentContentLength != textEditingController.text.length) { 172 | for (MarkdownTokenConfig _tokenConfig in widget.tokenConfigs) { 173 | if (_tokenConfig.meta != null) { 174 | _tokenConfig.meta.collection.forEach((SelectionInfo info) { 175 | if (textLength > currentContentLength) { 176 | if (info.startIndex <= 177 | indexNow - (textLength - currentContentLength) && 178 | indexNow - (textLength - currentContentLength) < 179 | info.endIndex) { 180 | _tokenConfig.meta.collection = _tokenConfig.meta.collection 181 | .where((selectionInfo) => selectionInfo != info) 182 | .toList(); 183 | } else if (info.startIndex > 184 | indexNow - (textLength - currentContentLength)) { 185 | info.updateIndex( 186 | info.startIndex + (textLength - currentContentLength)); 187 | } 188 | } else { 189 | if (info.startIndex - 1 <= indexNow && 190 | indexNow < info.endIndex) { 191 | _tokenConfig.meta.collection = _tokenConfig.meta.collection 192 | .where((selectionInfo) => selectionInfo != info) 193 | .toList(); 194 | } else if (info.startIndex - 1 > indexNow) { 195 | info.updateIndex( 196 | info.startIndex - (currentContentLength - textLength)); 197 | } 198 | } 199 | }); 200 | } 201 | } 202 | } 203 | } 204 | currentContentLength = textEditingController.text.length; 205 | setState(() {}); 206 | } 207 | showSuggestions(context); 208 | if (widget.onChange != null) { 209 | widget.onChange(textEditingController.text); 210 | } 211 | } 212 | 213 | OverlayEntry overlaySuggestions; 214 | showSuggestions(BuildContext context) async { 215 | clearSuggestions(); 216 | if (suggestions.length == 0) return; 217 | final RenderBox renderBoxRed = _editorKey.currentContext.findRenderObject(); 218 | final editorSize = renderBoxRed.size; 219 | final editorPosition = renderBoxRed.localToGlobal(Offset.zero); 220 | double keyboardHeight = MediaQuery.of(context).viewInsets.bottom; 221 | double visibleHeight = MediaQuery.of(context).size.height - keyboardHeight; 222 | Offset suggestionOffset = widget.suggestionsOffset ?? Offset.zero; 223 | double top = editorPosition.dy + editorSize.height + suggestionOffset.dy; 224 | double bottom; 225 | if (top > visibleHeight / 2) { 226 | top = null; 227 | bottom = keyboardHeight + editorSize.height + suggestionOffset.dy; 228 | } 229 | print( 230 | "top $top bottom $bottom editorPosition.dy ${editorPosition.dy} visibleHeight $visibleHeight"); 231 | overlaySuggestions = OverlayEntry( 232 | builder: (context) => Positioned( 233 | top: top, 234 | bottom: bottom, 235 | left: suggestionOffset.dx, 236 | child: _buildSuggestions(context), 237 | )); 238 | overlayState.insert(overlaySuggestions); 239 | } 240 | 241 | clearSuggestions() { 242 | overlaySuggestions?.remove(); 243 | overlaySuggestions = null; 244 | } 245 | 246 | Widget _buildSuggestions(BuildContext context) { 247 | if (suggestions.isNotEmpty) { 248 | return Material( 249 | child: ConstrainedBox( 250 | constraints: widget.suggestionsConstraints ?? 251 | BoxConstraints( 252 | maxWidth: MediaQuery.of(context).size.width, 253 | maxHeight: 400.0), 254 | child: Container( 255 | decoration: BoxDecoration( 256 | color: Colors.transparent, 257 | border: Border.all(color: const Color(0x32273d52)), 258 | borderRadius: BorderRadius.circular(4.0)), 259 | child: _buildSuggestionsList(), 260 | ))); 261 | } 262 | return Container(); 263 | } 264 | 265 | ListView _buildSuggestionsList() { 266 | return ListView( 267 | padding: EdgeInsets.zero, 268 | shrinkWrap: true, 269 | children: suggestions.map((TokenSuggestion suggestion) { 270 | return InkWell(child: Builder(builder: (BuildContext context) { 271 | return suggestion.display; 272 | }), onTap: () { 273 | int indexNow = textEditingController.selection.baseOffset; 274 | int indexAt = match.start; 275 | String addToInput = suggestion.onInsert(); 276 | int offSet = indexAt + 1; 277 | textEditingController.text = 278 | textEditingController.text.substring(0, indexAt) + 279 | addToInput + 280 | textEditingController.text.substring(indexNow); 281 | offSet = offSet + addToInput.length; 282 | textEditingController.selection = TextSelection( 283 | baseOffset: textEditingController.selection.baseOffset + offSet, 284 | extentOffset: 285 | textEditingController.selection.extentOffset + offSet); 286 | if (tokenConfig.meta != null) { 287 | tokenConfig.meta.collection.add(SelectionInfo( 288 | indexAt, indexAt + addToInput.length - 1, suggestion.data)); 289 | } 290 | setState(() {}); 291 | }); 292 | }).toList(), 293 | ); 294 | } 295 | 296 | triggerSave() { 297 | if (widget.onSaved != null) { 298 | widget.onSaved(textEditingController.text); 299 | } 300 | } 301 | 302 | @override 303 | void dispose() { 304 | textEditingController.dispose(); 305 | WidgetsBinding.instance.removeObserver(this); 306 | clearSuggestions(); 307 | super.dispose(); 308 | } 309 | } 310 | 311 | class MarkdownEditorController { 312 | _MarkdownEditorState __state; 313 | List listeners = []; 314 | 315 | set _state(_MarkdownEditorState state) { 316 | __state = state; 317 | updateListeners(); 318 | } 319 | 320 | _MarkdownEditorState get _state => __state; 321 | 322 | TextEditingController get controller => _state?.textEditingController; 323 | String get text => _state?.textEditingController?.text; 324 | 325 | triggerSave() { 326 | _state?.triggerSave(); 327 | } 328 | 329 | updateListeners() { 330 | if (controller == null) return; 331 | for (VoidCallback listener in listeners) { 332 | controller.addListener(listener); 333 | } 334 | listeners = []; 335 | } 336 | 337 | addListener(VoidCallback listener) { 338 | listeners.add(listener); 339 | updateListeners(); 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /lib/mdviewer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:adhara_markdown/mdbean.dart'; 3 | import 'package:adhara_markdown/utils.dart'; 4 | 5 | class MarkdownViewer extends StatelessWidget { 6 | final String content; 7 | final int loggedInUser; 8 | final TextStyle textStyle; 9 | final TextStyle highlightedTextStyle; 10 | final TextStyle fadedStyle; 11 | final List formatTypes; 12 | final bool collapsible; 13 | final List tokenConfigs; 14 | final int collapseLimit; 15 | 16 | MarkdownViewer( 17 | {Key key, 18 | this.content: "", 19 | this.loggedInUser, 20 | this.textStyle: const TextStyle(color: Colors.black), 21 | this.highlightedTextStyle: const TextStyle(color: Colors.indigo), 22 | this.formatTypes, 23 | this.collapsible: false, 24 | this.collapseLimit: 240, 25 | this.tokenConfigs, 26 | this.fadedStyle: const TextStyle(color: Colors.grey, fontSize: 12.0)}) 27 | : super(key: key); 28 | 29 | get _textSpanConfigs => 30 | tokenConfigs ?? 31 | [ 32 | MarkdownTokenConfig.mention(textStyle: highlightedTextStyle), 33 | MarkdownTokenConfig.link(textStyle: highlightedTextStyle), 34 | MarkdownTokenConfig.hashTag(textStyle: highlightedTextStyle), 35 | MarkdownTokenConfig.bold(textStyle: textStyle), 36 | MarkdownTokenConfig.italic(textStyle: textStyle), 37 | MarkdownTokenConfig.strikeThrough(textStyle: textStyle), 38 | MarkdownTokenConfig.code(textStyle: textStyle), 39 | ]; 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | int len = 0; 44 | List richTextChildren = []; 45 | bool showReadMore = false; 46 | for (MarkdownToken span in _convertPostToTextSpans(context, content)) { 47 | if (!collapsible || len < collapseLimit) { 48 | richTextChildren.add(span.getSpan()); 49 | } else { 50 | showReadMore = true; 51 | } 52 | len += span.text.length; 53 | } 54 | if (showReadMore) { 55 | richTextChildren.add(MarkdownToken( 56 | config: MarkdownTokenConfig( 57 | type: null, regExp: null, textStyle: textStyle), 58 | text: "...") 59 | .getSpan()); 60 | richTextChildren.add(TextSpan( 61 | text: "Read more", 62 | style: fadedStyle.copyWith( 63 | color: fadedStyle.color.withOpacity(0.6), 64 | decoration: TextDecoration.underline, 65 | height: 1.3), 66 | recognizer: null, 67 | )); 68 | } 69 | 70 | return RichText( 71 | text: new TextSpan( 72 | children: richTextChildren, 73 | ), 74 | ); 75 | } 76 | 77 | _convertPostToTextSpans(BuildContext context, String content) { 78 | List contentSpans = [content]; 79 | for (MarkdownTokenConfig spanConfig in _textSpanConfigs) { 80 | if (formatTypes == null || formatTypes.indexOf(spanConfig.type) != -1) { 81 | if (spanConfig.meta != null) { 82 | contentSpans = splitUserTokens(contentSpans, spanConfig); 83 | } else { 84 | contentSpans = splitTokensByRegex(contentSpans, spanConfig); 85 | } 86 | } 87 | } 88 | return contentSpans.map((postSpan) { 89 | if (postSpan is String) { 90 | return MarkdownToken( 91 | config: MarkdownTokenConfig( 92 | type: null, regExp: null, textStyle: textStyle), 93 | text: postSpan); 94 | } else { 95 | return postSpan; 96 | } 97 | }).toList(); 98 | } 99 | 100 | splitUserTokens(List strings, MarkdownTokenConfig userSpanConfig) { 101 | List returnTexts = []; 102 | for (var text in strings) { 103 | if (text is String) { 104 | int startIndex = 0; 105 | if (userSpanConfig.meta != null) { 106 | userSpanConfig.meta.collection.forEach((SelectionInfo info) { 107 | returnTexts.add(text.substring(startIndex, info.startIndex)); 108 | returnTexts.add( 109 | MarkdownToken( 110 | config: userSpanConfig, 111 | selectionInfo: info, 112 | text: text.substring(info.startIndex, info.endIndex + 1), 113 | ), 114 | ); 115 | startIndex = info.endIndex + 1; 116 | }); 117 | } 118 | returnTexts.add(text.substring(startIndex, text.length)); 119 | } 120 | } 121 | return returnTexts; 122 | } 123 | 124 | splitTokensByRegex(List strings, MarkdownTokenConfig spanConfig) { 125 | List returnTexts = []; 126 | for (var text in strings) { 127 | if (text is String) { 128 | Iterable matches = spanConfig.regExp.allMatches(text); 129 | int startIndex = 0; 130 | for (Match m in matches) { 131 | returnTexts.add(text.substring(startIndex, m.start)); 132 | String matchedText = text.substring(m.start, m.end); 133 | returnTexts.add(MarkdownToken( 134 | config: spanConfig, 135 | text: (spanConfig.postProcess != null) 136 | ? spanConfig.postProcess(matchedText) 137 | : matchedText, 138 | )); 139 | startIndex = m.end; 140 | } 141 | returnTexts.add(text.substring(startIndex, text.length)); 142 | } else { 143 | returnTexts.add(text); 144 | } 145 | } 146 | return returnTexts; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:url_launcher/url_launcher.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:adhara_markdown/mdbean.dart'; 5 | 6 | typedef String StringCallbackFn(String span); 7 | typedef void AdharaRichTextSpanTapCallback(MarkdownToken richTextSpan); 8 | typedef Future> AdharaRichTextSuggestionCallback( 9 | String hint); 10 | typedef String OnSuggestionInsert(); 11 | typedef void OnSavedCallback(String content); 12 | 13 | enum MarkdownTokenTypes { 14 | link, 15 | mention, 16 | hashTag, 17 | bold, 18 | italic, 19 | strikeThrough, 20 | code 21 | } 22 | 23 | void urlOpener(MarkdownToken span) async { 24 | if (await canLaunch(span.text)) { 25 | await launch(span.text); 26 | } else { 27 | throw 'Could not launch ${span.text}'; 28 | } 29 | } 30 | 31 | String stripFirstAndLast(String text) => text.substring(1, text.length - 1); 32 | 33 | String _baseCharacters = r'a-zA-Z0-9\/?.",!:<>' + r"'"; 34 | 35 | class MarkdownTokenConfig { 36 | final MarkdownTokenTypes type; 37 | final RegExp regExp; 38 | final RegExp hintRegExp; 39 | final TextStyle textStyle; 40 | final StringCallbackFn postProcess; 41 | final MarkdownMeta meta; 42 | final AdharaRichTextSpanTapCallback onTap; 43 | final AdharaRichTextSuggestionCallback suggestions; 44 | 45 | MarkdownTokenConfig( 46 | {@required this.type, 47 | @required this.textStyle, 48 | this.regExp, 49 | this.hintRegExp, 50 | this.postProcess, 51 | this.meta, 52 | this.onTap, 53 | this.suggestions}); 54 | 55 | MarkdownTokenConfig.mention( 56 | {this.textStyle, 57 | this.postProcess, 58 | this.meta, 59 | this.onTap, 60 | this.suggestions}) 61 | : type = MarkdownTokenTypes.mention, 62 | regExp = RegExp(r'@[0-9a-zA-Z.\s]+'), 63 | hintRegExp = RegExp(r"@[0-9a-zA-Z.\s]*"); 64 | 65 | MarkdownTokenConfig.link({this.textStyle, this.postProcess}) 66 | : type = MarkdownTokenTypes.link, 67 | regExp = RegExp(r'((http[s]{0,1}:\/\/)[a-zA-Z0-9\.%\/?:&,\-_#="]*)'), 68 | hintRegExp = null, 69 | meta = null, 70 | suggestions = null, 71 | onTap = urlOpener; 72 | 73 | MarkdownTokenConfig.hashTag( 74 | {this.textStyle, this.suggestions, this.postProcess, this.onTap}) 75 | : type = MarkdownTokenTypes.hashTag, 76 | regExp = RegExp(r'#[' + _baseCharacters + ']+'), 77 | hintRegExp = RegExp(r'#[' + _baseCharacters + '\-]*'), 78 | meta = null; 79 | 80 | MarkdownTokenConfig.bold({TextStyle textStyle, StringCallbackFn postProcess}) 81 | : type = MarkdownTokenTypes.bold, 82 | regExp = RegExp(r'\*[' + _baseCharacters + r'_~`\-\s]*\*'), 83 | hintRegExp = null, 84 | textStyle = textStyle.copyWith(fontWeight: FontWeight.bold), 85 | postProcess = postProcess ?? stripFirstAndLast, 86 | meta = null, 87 | suggestions = null, 88 | onTap = null; 89 | 90 | MarkdownTokenConfig.italic( 91 | {TextStyle textStyle, StringCallbackFn postProcess}) 92 | : type = MarkdownTokenTypes.italic, 93 | regExp = RegExp(r'_[' + _baseCharacters + r'~`\-\*\s]*_'), 94 | hintRegExp = null, 95 | textStyle = textStyle.copyWith(fontStyle: FontStyle.italic), 96 | postProcess = postProcess ?? stripFirstAndLast, 97 | meta = null, 98 | suggestions = null, 99 | onTap = null; 100 | 101 | MarkdownTokenConfig.strikeThrough( 102 | {TextStyle textStyle, StringCallbackFn postProcess}) 103 | : type = MarkdownTokenTypes.strikeThrough, 104 | regExp = RegExp(r'~[' + _baseCharacters + r'_`\-\*\s]*~'), 105 | hintRegExp = null, 106 | textStyle = textStyle.copyWith(decoration: TextDecoration.lineThrough), 107 | postProcess = postProcess ?? stripFirstAndLast, 108 | meta = null, 109 | suggestions = null, 110 | onTap = null; 111 | 112 | MarkdownTokenConfig.code({TextStyle textStyle, StringCallbackFn postProcess}) 113 | : type = MarkdownTokenTypes.code, 114 | regExp = RegExp(r'`[' + _baseCharacters + r'~_\-\*\s]*`'), 115 | hintRegExp = null, 116 | textStyle = textStyle.copyWith(fontFamily: "Monospace"), 117 | postProcess = postProcess ?? stripFirstAndLast, 118 | meta = null, 119 | suggestions = null, 120 | onTap = null; 121 | } 122 | 123 | class MarkdownToken { 124 | final MarkdownTokenConfig config; 125 | final SelectionInfo selectionInfo; 126 | final String text; 127 | 128 | MarkdownToken( 129 | {@required this.text, @required this.config, this.selectionInfo}); 130 | 131 | TextSpan getSpan() { 132 | return TextSpan( 133 | text: text, 134 | style: config.textStyle, 135 | recognizer: (this.config.onTap != null) 136 | ? (TapGestureRecognizer() 137 | ..onTap = () { 138 | this.config.onTap(this); 139 | }) 140 | : null, 141 | ); 142 | } 143 | } 144 | 145 | class TokenSuggestion { 146 | Widget display; 147 | dynamic data; 148 | OnSuggestionInsert onInsert; 149 | 150 | TokenSuggestion({this.display, this.data, this.onInsert}); 151 | } 152 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.5.0" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.2.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_test: 59 | dependency: "direct dev" 60 | description: flutter 61 | source: sdk 62 | version: "0.0.0" 63 | flutter_web_plugins: 64 | dependency: transitive 65 | description: flutter 66 | source: sdk 67 | version: "0.0.0" 68 | js: 69 | dependency: transitive 70 | description: 71 | name: js 72 | url: "https://pub.dartlang.org" 73 | source: hosted 74 | version: "0.6.3" 75 | matcher: 76 | dependency: transitive 77 | description: 78 | name: matcher 79 | url: "https://pub.dartlang.org" 80 | source: hosted 81 | version: "0.12.10" 82 | meta: 83 | dependency: transitive 84 | description: 85 | name: meta 86 | url: "https://pub.dartlang.org" 87 | source: hosted 88 | version: "1.3.0" 89 | path: 90 | dependency: transitive 91 | description: 92 | name: path 93 | url: "https://pub.dartlang.org" 94 | source: hosted 95 | version: "1.8.0" 96 | plugin_platform_interface: 97 | dependency: transitive 98 | description: 99 | name: plugin_platform_interface 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "2.0.0" 103 | sky_engine: 104 | dependency: transitive 105 | description: flutter 106 | source: sdk 107 | version: "0.0.99" 108 | source_span: 109 | dependency: transitive 110 | description: 111 | name: source_span 112 | url: "https://pub.dartlang.org" 113 | source: hosted 114 | version: "1.8.0" 115 | stack_trace: 116 | dependency: transitive 117 | description: 118 | name: stack_trace 119 | url: "https://pub.dartlang.org" 120 | source: hosted 121 | version: "1.10.0" 122 | stream_channel: 123 | dependency: transitive 124 | description: 125 | name: stream_channel 126 | url: "https://pub.dartlang.org" 127 | source: hosted 128 | version: "2.1.0" 129 | string_scanner: 130 | dependency: transitive 131 | description: 132 | name: string_scanner 133 | url: "https://pub.dartlang.org" 134 | source: hosted 135 | version: "1.1.0" 136 | term_glyph: 137 | dependency: transitive 138 | description: 139 | name: term_glyph 140 | url: "https://pub.dartlang.org" 141 | source: hosted 142 | version: "1.2.0" 143 | test_api: 144 | dependency: transitive 145 | description: 146 | name: test_api 147 | url: "https://pub.dartlang.org" 148 | source: hosted 149 | version: "0.2.19" 150 | typed_data: 151 | dependency: transitive 152 | description: 153 | name: typed_data 154 | url: "https://pub.dartlang.org" 155 | source: hosted 156 | version: "1.3.0" 157 | url_launcher: 158 | dependency: "direct main" 159 | description: 160 | name: url_launcher 161 | url: "https://pub.dartlang.org" 162 | source: hosted 163 | version: "6.0.3" 164 | url_launcher_linux: 165 | dependency: transitive 166 | description: 167 | name: url_launcher_linux 168 | url: "https://pub.dartlang.org" 169 | source: hosted 170 | version: "2.0.0" 171 | url_launcher_macos: 172 | dependency: transitive 173 | description: 174 | name: url_launcher_macos 175 | url: "https://pub.dartlang.org" 176 | source: hosted 177 | version: "2.0.0" 178 | url_launcher_platform_interface: 179 | dependency: transitive 180 | description: 181 | name: url_launcher_platform_interface 182 | url: "https://pub.dartlang.org" 183 | source: hosted 184 | version: "2.0.2" 185 | url_launcher_web: 186 | dependency: transitive 187 | description: 188 | name: url_launcher_web 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "2.0.0" 192 | url_launcher_windows: 193 | dependency: transitive 194 | description: 195 | name: url_launcher_windows 196 | url: "https://pub.dartlang.org" 197 | source: hosted 198 | version: "2.0.0" 199 | vector_math: 200 | dependency: transitive 201 | description: 202 | name: vector_math 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "2.1.0" 206 | sdks: 207 | dart: ">=2.12.0-259.9.beta <3.0.0" 208 | flutter: ">=1.22.0" 209 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: adhara_markdown 2 | description: Minimalistic, highly customizable, regexp based markdown editor and viewer by adhara 3 | version: 0.2.0 4 | homepage: https://github.com/infitio/flutter_markdown 5 | 6 | environment: 7 | sdk: ">=2.2.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | url_launcher: ^6.0.2 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | # For information on the generic Dart part of this file, see the 19 | # following page: https://www.dartlang.org/tools/pub/pubspec 20 | 21 | # The following section is specific to Flutter. 22 | flutter: 23 | 24 | # To add assets to your package, add an assets section, like this: 25 | # assets: 26 | # - images/a_dot_burr.jpeg 27 | # - images/a_dot_ham.jpeg 28 | # 29 | # For details regarding assets in packages, see 30 | # https://flutter.io/assets-and-images/#from-packages 31 | # 32 | # An image asset can refer to one or more resolution-specific "variants", see 33 | # https://flutter.io/assets-and-images/#resolution-aware. 34 | 35 | # To add custom fonts to your package, add a fonts section here, 36 | # in this "flutter" section. Each entry in this list should have a 37 | # "family" key with the font family name, and a "fonts" key with a 38 | # list giving the asset and other descriptors for the font. For 39 | # example: 40 | # fonts: 41 | # - family: Schyler 42 | # fonts: 43 | # - asset: fonts/Schyler-Regular.ttf 44 | # - asset: fonts/Schyler-Italic.ttf 45 | # style: italic 46 | # - family: Trajan Pro 47 | # fonts: 48 | # - asset: fonts/TrajanPro.ttf 49 | # - asset: fonts/TrajanPro_Bold.ttf 50 | # weight: 700 51 | # 52 | # For details regarding fonts in packages, see 53 | # https://flutter.io/custom-fonts/#from-packages 54 | -------------------------------------------------------------------------------- /test/adhara_markdown_test.dart: -------------------------------------------------------------------------------- 1 | /* 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | import 'package:adhara_markdown/adhara_markdown.dart'; 5 | 6 | void main() { 7 | test('adds one to input values', () { 8 | */ 9 | /*final calculator = Calculator(); 10 | expect(calculator.addOne(2), 3); 11 | expect(calculator.addOne(-7), -6); 12 | expect(calculator.addOne(0), 1); 13 | expect(() => calculator.addOne(null), throwsNoSuchMethodError);*/ /* 14 | 15 | }); 16 | } 17 | */ 18 | --------------------------------------------------------------------------------