Compare commits

..

No commits in common. "master" and "v0.0.5" have entirely different histories.

39 changed files with 678 additions and 717 deletions

6
.flutter-plugins Normal file
View file

@ -0,0 +1,6 @@
# This is a generated file; do not edit or check into version control.
flutter_plugin_android_lifecycle=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\flutter_plugin_android_lifecycle-2.0.7\\
image_picker=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker-0.8.5+3\\
image_picker_android=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker_android-0.8.5+2\\
image_picker_for_web=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker_for_web-2.1.8\\
image_picker_ios=C:\\src\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\image_picker_ios-0.8.5+6\\

View file

@ -0,0 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"image_picker_ios","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_ios-0.8.5+6\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_plugin_android_lifecycle-2.0.7\\\\","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_android-0.8.5+2\\\\","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"image_picker_for_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\image_picker_for_web-2.1.8\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]}],"date_created":"2022-09-05 15:20:35.995199","version":"3.3.0"}

View file

@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "pub"
directory: "/"
schedule:
interval: "daily"

View file

@ -1,14 +0,0 @@
name: Iconica Standard Component CI Workflow
# Workflow Caller version: 2.0.0
on:
pull_request:
workflow_dispatch:
jobs:
call-global-iconica-workflow:
uses: Iconica-Development/.github/.github/workflows/component-ci.yml@master
secrets: inherit
permissions: write-all
with:
subfolder: "." # add optional subfolder to run workflow in

View file

@ -1,14 +0,0 @@
name: Iconica Standard Component Documentation Workflow
# Workflow Caller version: 1.0.0
on:
release:
types: [published]
workflow_dispatch:
jobs:
call-iconica-component-documentation-workflow:
uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master
secrets: inherit
permissions: write-all

6
.gitignore vendored
View file

@ -29,9 +29,3 @@ migrate_working_dir/
.packages
build/
coverage/
/.flutter-plugins
/.flutter-plugins-dependencies
# FVM Version Cache
.fvm/
.fvmrc

View file

@ -9,42 +9,9 @@
## 0.0.3 - September 6th 2022
- More customization options for the Image Picker Dialog added:
- Font
- Text color
- Icon color
- Close Button background color
- Close Button text color
- Close Button text size
## 1.0.0 - September 26th 2022
- Icons can be changed by Widgets instead of IconData.
## 1.0.2 - Oktober 21st 2022
- ImagePickerService can be correctly injected into the widget.
## 1.0.4 - April 4th 2023
- Make camera option optional
## 1.0.5 - February 7th 2024
- Added CI and linter
## 2.0.0 - February 22nd 2024
- Simplified the ImagePickerTheme
# 3.0.0 - February 22nd 2024
- Removed customButton from ImagePicker.
# 4.0.0
* Added title options to theme.
* updated iconica_analysis dependency.
* Updated default theme.
# 4.1.0
* Added support for handling errors when calling `pickImage`.
- Font
- Text color
- Icon color
- Close Button background color
- Close Button text color
- Close Button text size

View file

@ -1,9 +0,0 @@
Copyright (c) 2022 Iconica, All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,19 +1,17 @@
[![pub package](https://img.shields.io/pub/v/flutter_introduction_widget.svg)](https://github.com/Iconica-Development) [![Build status](https://img.shields.io/github/workflow/status/Iconica-Development/flutter_introduction_widget/CI)](https://github.com/Iconica-Development/flutter_image_picker/actions/new) [![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://github.com/tenhobi/effective_dart)
# Flutter Image Picker
Flutter Image Picker is a package you can use to implement an Image Picker in your Flutter app.
Image Picker that can be used to pick an image from storage or make a picture with your camera. This package is built with Flutter and is customizable with icons, descriptions and sizes.
![Gif](example/gif/ImagePickerGif.gif)
![Image Picker GIF](flutter_image_picker.gif)
## Features
Figma Design that defines this component (only accessible for Iconica developers): https://www.figma.com/file/4WkjwynOz5wFeFBRqTHPeP/Iconica-Design-System?type=design&node-id=357%3A3354&mode=design&t=XulkAJNPQ32ARxWh-1
Figma clickable prototype that demonstrates this component (only accessible for Iconica developers): https://www.figma.com/proto/4WkjwynOz5wFeFBRqTHPeP/Iconica-Design-System?type=design&node-id=340-611&viewport=188%2C-512%2C0.05&t=XulkAJNPQ32ARxWh-0&scaling=min-zoom&starting-point-node-id=516%3A2544&show-proto-sidebar=1
With the Flutter Image Picker you can select an existing picture from the gallery of your device or make a picture with the camera to use in your app. This package is made for Android, iOS and Windows.
## Setup
To use this package, add `flutter_image_picker` as a dependency in your pubspec.yaml file.
To use this package, add `flutter_image_picker` as a [dependency in your pubspec.yaml file](https://flutter.dev/docs/development/platform-integration/platform-channels).
## How to use
## How To Use
See the [Example Code](example/lib/main.dart) for an example on how to use this package.
@ -21,38 +19,39 @@ You can add an optional `ImagePickerTheme()` to the `ImagePicker()` to change th
An example on how to add a parameter to the `ImagePickerTheme()` is: `ImagePickerTheme(imagePickerTheme: const ImagePickerTheme(title: "Image Picker"))`.
As a whole you get `ImagePicker(ImagePickerTheme(imagePickerTheme: const ImagePickerTheme(title: "Image Picker")))`
| Parameter | Explaination |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| font | The font that is being used in the Image Picker Dialog. |
| title | The title displayed at the top of the Image Picker Dialog. |
| titleTextSize | The font size of the title mentioned above. |
| titleColor | The color of the title text. |
| titleBackgroundColor | The color of the title background. |
| titleAlignment | The alignment of the title text. |
| textColor | The color of the text that is displayed in the Image Picker Dialog. |
| iconColor | The color of the icons that are displayed in the Image Picker Dialog. |
| iconSize | The size of the icons that are visible in the Image Picker Dialog. |
| iconTextSize | The font size of the text underneath the icon buttons. |
| spaceBetweenIcons | The size of the space between the two icons in the Image Picker Dialog. |
| makePhotoIcon | The widget that is displayed for the 'Make Photo' functionality of the Image Picker Dialog. |
| makePhotoText | The text that is displayed underneath the 'Make Photo' icon. |
| selectImageIcon | The widget that is displayed for the 'Select Image From Gallery' functionality of the Image Picker Dialog. |
| selectImageText | The text that is displayed underneath the 'Select Image From Gallery' icon. |
| closeButtonText | The text that is shown on the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonTextSize | The size of the text that is being displayed on the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonTextColor | The color of the text that is being displayed on the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonWidth | The width of the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonHeight | The height of the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonBackgroundColor | The background color of the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| Parameter | Explaination |
|-------------------|----------------|
| font | The font that is being used in the Image Picker Dialog. |
| title | The title displayed at the top of the Image Picker Dialog. |
| titleTextSize | The font size of the title mentioned above. |
| titleColor | The color of the title text. |
| titleBackgroundColor | The color of the title background. |
| titleAlignment | The alignment of the title text. |
| textColor | The color of the text that is displayed in the Image Picker Dialog. |
| iconColor | The color of the icons that are displayed in the Image Picker Dialog. |
| iconSize | The size of the icons that are visible in the Image Picker Dialog. |
| iconTextSize | The font size of the text underneath the icon buttons. |
| spaceBetweenIcons | The size of the space between the two icons in the Image Picker Dialog. |
| makePhotoIcon | The icon that is displayed for the 'Make Photo' functionality of the Image Picker Dialog. |
| makePhotoText | The text that is displayed underneath the 'Make Photo' icon. |
| selectImageIcon | The icon that is displayed for the 'Select Image From Gallery' functionality of the Image Picker Dialog. |
| selectImageText | The text that is displayed underneath the 'Select Image From Gallery' icon. |
| closeButtonText | The text that is shown on the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonTextSize | The size of the text that is being displayed on the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonTextColor | The color of the text that is being displayed on the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonWidth | The width of the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonHeight | The height of the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
| closeButtonBackgroundColor | The background color of the 'Close Dialog' button at the bottom of the Image Picker Dialog. |
## Issues
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_image_picker) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_image_picker/pulls) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
## Want to contribute
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_image_picker/pulls).
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](URL TO PULL REQUEST TAB IN REPO).
## Author
This `flutter_image_picker` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>
This `flutter-image-picker` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>

View file

@ -1,9 +1,4 @@
include: package:flutter_iconica_analysis/analysis_options.yaml
include: package:flutter_lints/flutter.yaml
# Possible to overwrite the rules from the package
analyzer:
exclude:
linter:
rules:
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

1
example/.gitignore vendored
View file

@ -31,7 +31,6 @@ migrate_working_dir/
.pub-cache/
.pub/
/build/
pubspec.lock
# Web related
lib/generated_plugin_registrant.dart

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 MiB

View file

@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>9.0</string>
</dict>
</plist>

View file

@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View file

@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View file

@ -1,41 +0,0 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View file

@ -1,22 +0,0 @@
PODS:
- Flutter (1.0.0)
- image_picker_ios (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
COCOAPODS: 1.11.3

View file

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
0FC2B515B107F2CCC9400081 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD964E61DAEEAA6F72EFFC83 /* Pods_Runner.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
@ -32,7 +31,6 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
37C41588130A4A617D522A7C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@ -44,9 +42,6 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BD964E61DAEEAA6F72EFFC83 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C785D1BFD24C97C9AD880AAD /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
FB7137C291A1A4337E64A2C9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -54,24 +49,12 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0FC2B515B107F2CCC9400081 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
16A77C595AC779F26D312E25 /* Pods */ = {
isa = PBXGroup;
children = (
C785D1BFD24C97C9AD880AAD /* Pods-Runner.debug.xcconfig */,
37C41588130A4A617D522A7C /* Pods-Runner.release.xcconfig */,
FB7137C291A1A4337E64A2C9 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@ -89,8 +72,6 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
16A77C595AC779F26D312E25 /* Pods */,
A130C96F2C16654EE7E802F7 /* Frameworks */,
);
sourceTree = "<group>";
};
@ -117,14 +98,6 @@
path = Runner;
sourceTree = "<group>";
};
A130C96F2C16654EE7E802F7 /* Frameworks */ = {
isa = PBXGroup;
children = (
BD964E61DAEEAA6F72EFFC83 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -132,14 +105,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
47E642748A60D4513AE80A00 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
27ECA87BE0E31E65D21B232E /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -198,23 +169,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
27ECA87BE0E31E65D21B232E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -229,28 +183,6 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
47E642748A60D4513AE80A00 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -340,7 +272,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@ -417,7 +349,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -466,7 +398,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;

View file

@ -4,7 +4,4 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View file

@ -1,22 +1,36 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_image_picker/flutter_image_picker.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const ImagePickerExample());
final imageProvider =
StateNotifierProvider.autoDispose<ImageNotifier, Uint8List?>((ref) {
return ImageNotifier();
});
class ImageNotifier extends StateNotifier<Uint8List?> {
ImageNotifier() : super(null);
Uint8List? image;
void changeImage(Uint8List newImage) {
state = image = newImage;
}
void cleanImage() {
state = image = null;
}
}
class ImagePickerExample extends StatelessWidget {
const ImagePickerExample({
super.key,
});
void main() {
runApp(const ProviderScope(child: ImagePickerExample()));
}
class ImagePickerExample extends ConsumerWidget {
const ImagePickerExample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
title: 'Flutter Image Picker Example',
theme: ThemeData(
@ -28,11 +42,9 @@ class ImagePickerExample extends StatelessWidget {
}
}
class ImagePickerExampleHomePage extends StatefulWidget {
const ImagePickerExampleHomePage({
required this.title,
super.key,
});
class ImagePickerExampleHomePage extends ConsumerStatefulWidget {
const ImagePickerExampleHomePage({Key? key, required this.title})
: super(key: key);
final String title;
@ -42,26 +54,24 @@ class ImagePickerExampleHomePage extends StatefulWidget {
}
class ImagePickerExampleHomePageState
extends State<ImagePickerExampleHomePage> {
extends ConsumerState<ImagePickerExampleHomePage> {
final double whiteSpace = 20;
final double imageWidth = 300;
final String placeholder = 'assets/images/placeholder.png';
final String imageAlreadyDisplayedMessage =
'The selected image is already being displayed!';
Uint8List? uploadedImage;
@override
Widget build(BuildContext context) {
final imageWatcher = ref.watch(imageProvider);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(
onPressed: () {
setState(() {
uploadedImage = null;
});
ref.invalidate(imageProvider);
},
icon: const Icon(Icons.delete))
],
@ -71,8 +81,9 @@ class ImagePickerExampleHomePageState
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(children: [
if (uploadedImage == null) ...[
ProviderScope(
child: Column(children: [
if (imageWatcher == null) ...[
Image.asset(
placeholder,
width: imageWidth,
@ -80,12 +91,12 @@ class ImagePickerExampleHomePageState
)
] else ...[
Image.memory(
uploadedImage!,
imageWatcher,
width: imageWidth,
height: imageWidth,
)
]
]),
])),
SizedBox(height: whiteSpace),
const Text(
'Pick an image or make a photo!',
@ -116,18 +127,10 @@ class ImagePickerExampleHomePageState
Uint8List? imageInBytes = await showModalBottomSheet<Uint8List?>(
context: context,
backgroundColor: Colors.white,
builder: (BuildContext context) => ImagePicker(
onError: (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(error.message ?? "An error occurred")),
);
},
));
builder: (BuildContext context) => const ImagePicker());
if (imageInBytes != null) {
if (!listEquals(uploadedImage, imageInBytes)) {
setState(() {
uploadedImage = imageInBytes;
});
if (!listEquals(ref.read(imageProvider), imageInBytes)) {
ref.read(imageProvider.notifier).changeImage(imageInBytes);
} else {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(

View file

@ -6,10 +6,6 @@
#include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
}

View file

@ -3,7 +3,6 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View file

@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View file

@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View file

@ -5,8 +5,6 @@
import FlutterMacOS
import Foundation
import file_selector_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
}

View file

@ -1,40 +0,0 @@
platform :osx, '10.11'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

278
example/pubspec.lock Normal file
View file

@ -0,0 +1,278 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
cross_file:
dependency: transitive
description:
name: cross_file
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.3+1"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_image_picker:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.0.1"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.7"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0-dev.9"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: transitive
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.5"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
image_picker:
dependency: transitive
description:
name: image_picker
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.5+3"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.5+2"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.8"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.5+6"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.6.1"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
riverpod:
dependency: transitive
description:
name: riverpod
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0-dev.9"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
state_notifier:
dependency: transitive
description:
name: state_notifier
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.2+1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.12"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
sdks:
dart: ">=2.17.6 <3.0.0"
flutter: ">=3.0.0"

View file

@ -39,6 +39,8 @@ dependencies:
flutter_image_picker:
path: ../
flutter_riverpod: ^2.0.0-dev.9
dev_dependencies:
flutter_test:
sdk: flutter

View file

@ -6,9 +6,6 @@
#include "generated_plugin_registrant.h"
#include <file_selector_windows/file_selector_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
}

View file

@ -3,7 +3,6 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 MiB

View file

@ -1,10 +1,4 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
///
library flutter_image_picker;
export "src/models/image_picker_config.dart";
export "src/models/image_picker_theme.dart";
export "src/services/image_picker_service.dart";
export "src/ui/image_picker.dart";
export 'src/models/image_picker_theme.dart';
export 'src/ui/image_picker.dart';

View file

@ -1,23 +0,0 @@
class ImagePickerConfig {
/// The [ImagePickerConfig] is used to configure the [ImagePicker].
const ImagePickerConfig({
this.maxWidth,
this.maxHeight,
this.imageQuality,
this.cameraOption,
});
/// If specified, the image will be at most `maxWidth` wide and
/// `maxHeight` tall. Otherwise the image will be returned at it's
/// original width and height.
/// The `imageQuality` argument modifies the quality of the image, ranging
/// from 0-100 where 100 is the original/max quality. If `imageQuality` is null, the image with
/// the original quality will be returned. Compression is only supported
/// for certain image types such as JPEG and on Android PNG and WebP, too.
/// If compression is not supported for the image that is picked, a warning
/// message will be logged.
final double? maxWidth;
final double? maxHeight;
final int? imageQuality;
final bool? cameraOption;
}

View file

@ -1,58 +1,92 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import "package:flutter/material.dart";
import 'package:flutter/material.dart';
class ImagePickerTheme {
/// The [ImagePickerTheme] is used to style the [ImagePicker].
const ImagePickerTheme({
this.font = "Roboto",
this.title = "Upload Image",
this.titleTextSize = 20,
this.titleColor = Colors.black,
this.titleBackgroundColor = Colors.white,
this.titleAlignment = TextAlign.left,
this.textColor = Colors.black,
this.iconColor = Colors.black,
this.iconSize = 125,
this.iconTextSize = 15,
this.spaceBetweenIcons = 30,
this.makePhotoIcon,
this.makePhotoText = "TAKE PICTURE",
this.selectImageIcon,
this.selectImageText = "UPLOAD FILE",
this.iconTextStyle,
this.closeButtonBuilder,
this.title = "Do you want to upload a file or take a picture?",
this.titleStyle,
this.titleAlignment = TextAlign.center,
this.makePhotoIcon = Icons.camera_alt_rounded,
this.makePhotoText = "Take a Picture",
this.selectImageIcon = Icons.image,
this.selectImageText = "Select File",
this.closeButtonText = "Close",
this.closeButtonTextSize = 15,
this.closeButtonTextColor = Colors.white,
this.closeButtonWidth = 300,
this.closeButtonHeight = 40,
this.closeButtonBackgroundColor = Colors.black,
});
/// The font that's used in the Image Picker
final String font;
/// The title displayed at the top of the Image Picker Dialog.
final String title;
/// The font size of the title mentioned above.
final double titleTextSize;
/// The color of the title text.
final Color titleColor;
/// The color of the title background.
final Color titleBackgroundColor;
/// The alignment of the title text.
final TextAlign titleAlignment;
/// The color of the icons
final Color iconColor;
/// The color of the text in the Image Picker Dialog
final Color textColor;
/// The size of the icons that are visible in the Image Picker Dialog.
final double iconSize;
/// The font size of the text underneath the icon buttons.
final double iconTextSize;
/// The size of the space between the two icons in the Image Picker Dialog.
final double spaceBetweenIcons;
/// The icon that is displayed for the 'Make Photo' functionality of the
/// Image Picker Dialog.
final Widget? makePhotoIcon;
/// The icon that is displayed for the 'Make Photo' functionality of the Image Picker Dialog.
final IconData makePhotoIcon;
/// The text that is displayed underneath the 'Make Photo' icon.
final String makePhotoText;
/// The icon that is displayed for the 'Select Image From Gallery'
/// functionality of the Image Picker Dialog.
final Widget? selectImageIcon;
/// The icon that is displayed for the 'Select Image From Gallery' functionality of the Image Picker Dialog.
final IconData selectImageIcon;
/// The text that is displayed underneath the 'Select Image From Gallery'
/// icon.
/// The text that is displayed underneath the 'Select Image From Gallery' icon.
final String selectImageText;
final TextStyle? iconTextStyle;
/// The text that is shown on the 'Close Dialog' button at the bottom of the Image Picker Dialog.
final String closeButtonText;
final Widget Function(Function() onTap)? closeButtonBuilder;
/// The fontsize of the text of the close button of the Image Picker Dialog.
final double closeButtonTextSize;
final String title;
/// The color of the text of the close button of the Image Picker Dialog.
final Color closeButtonTextColor;
final TextStyle? titleStyle;
/// The width of the 'Close Dialog' button at the bottom of the Image Picker Dialog.
final double closeButtonWidth;
final TextAlign titleAlignment;
/// The height of the 'Close Dialog' button at the bottom of the Image Picker Dialog.
final double closeButtonHeight;
/// The color of the close button of the Image Picker Dialog.
final Color closeButtonBackgroundColor;
}

View file

@ -1,50 +1,21 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'dart:typed_data';
import "dart:typed_data";
import "package:flutter_image_picker/src/models/image_picker_config.dart";
import "package:image_picker/image_picker.dart";
import 'package:image_picker/image_picker.dart';
/// The Image Picker Service class is the functionality of the Image Picker
/// package which uses the Image Picker package to choose an image.
/// If you have your own implementation of the Image Picker you can add it to
/// the constructor when creating the class.
mixin ImagePickerService {
/// [pickImage] is the function that picks the image and returns it as a
/// [Uint8List].
/// The function requires [source], an [ImageSource]
Future<Uint8List?> pickImage(
ImageSource source, {
ImagePickerConfig? config,
});
}
/// The Image Picker Service class is the functionality of the Image Picker package which uses the Image Picker package to choose an image.
/// If you have your own implementation of the Image Picker you can add it to the constructor when creating the class.
class ImagePickerService {
ImagePickerService({this.imagePicker});
/// The ImagePickerServiceDefault is the default implementation of the
/// ImagePickerService.
/// It uses the Image Picker package to pick an image and returns it as a
/// [Uint8List].
class ImagePickerServiceDefault implements ImagePickerService {
ImagePickerServiceDefault({this.imagePicker});
/// It's possible to have your own implementation for the Image Picker if you
/// don't want to use the Image Picker Package.
/// It's possible to have your own implementation for the Image Picker if you don't want to use the Image Picker Package.
ImagePicker? imagePicker;
/// [pickImage] is the function that picks the image and returns it as a
/// [Uint8List].
/// The function requires [source], an [ImageSource] that's the method of how
/// the image needs to be picked, for example gallery or camera.
@override
Future<Uint8List?> pickImage(
ImageSource source, {
ImagePickerConfig? config,
}) async =>
await (await (imagePicker ?? ImagePicker()).pickImage(
source: source,
maxWidth: config?.maxWidth,
maxHeight: config?.maxHeight,
imageQuality: config?.imageQuality,
))
?.readAsBytes();
/// [pickImage] is the function that picks the image and returns it as a [Uint8List].
/// The function requires [source], an [ImageSource] that's the method of how the image needs to be picked, for example gallery or camera.
Future<Uint8List?> pickImage(ImageSource source) async {
var image =
await (await (imagePicker ?? ImagePicker()).pickImage(source: source))
?.readAsBytes();
return image;
}
}

View file

@ -1,166 +1,140 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
import 'package:flutter_image_picker/src/services/image_picker_service.dart';
import 'package:image_picker/image_picker.dart';
import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "package:flutter_image_picker/flutter_image_picker.dart";
import "package:image_picker/image_picker.dart";
import '../models/image_picker_theme.dart';
/// The Image Picker class generates the Image Picker Widget which can be
/// displayed in your application. If you call the class you can give it 4
/// optional variables:
/// The first one is the [ImagePickerTheme] which can be used to change the UI
/// of the widget.
/// The second one is the [ImagePickerConfig] which can be used to configure the
/// behaviour of the image picker.
/// The third one is your own implementation of the ImagePickerService. Which
/// can be used in testing for example.
/// The fourth one is a custom Button widget.
/// The Image Picker class generates the Image Picker Widget which can be displayed in your application. If you call the class you can give it 3 optional variables:
/// The first one is the [ImagePickerTheme] which can be used to change the UI of the widget.
/// The second one is your own implementation of the ImagePickerService. Which can be used in testing for example.
/// The third one is a custom Button widget.
class ImagePicker extends StatelessWidget {
const ImagePicker({
this.theme = const ImagePickerTheme(),
this.config = const ImagePickerConfig(),
this.service,
this.onError,
super.key,
});
const ImagePicker(
{Key? key,
this.imagePickerTheme = const ImagePickerTheme(),
this.imagePickerService,
this.customButton})
: super(key: key);
/// ImagePickerTheme can be used to change the UI of the Image Picker Widget to change the text/icons to your liking.
final ImagePickerTheme theme;
final ImagePickerTheme imagePickerTheme;
/// ImagePickerConfig can be used to define the size and quality for the
/// uploaded image.
final ImagePickerConfig config;
/// The Image Picker Dialog can have a custom button if you want to.
final StatelessWidget? customButton;
/// The ImagePickerService can be used if you want to use your own
/// implementation of the Image Service if you want to use it for testing or
/// add more features. If null the current implementation will be used.
final ImagePickerService? service;
final Function(PlatformException error)? onError;
/// The ImagePickerService can be used if you want to use your own implementation of the Image Service if you want to use it for testing or add more features. If null the current implementation will be used.
final ImagePickerService? imagePickerService;
@override
Widget build(BuildContext context) => SingleChildScrollView(
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
ListTile(
title: Text(
theme.title,
style:
theme.titleStyle ?? Theme.of(context).textTheme.titleMedium,
textAlign: theme.titleAlignment,
),
children: <Widget>[
ListTile(
tileColor: imagePickerTheme.titleBackgroundColor,
title: Text(
textAlign: imagePickerTheme.titleAlignment,
imagePickerTheme.title,
style: TextStyle(
fontFamily: imagePickerTheme.font,
fontSize: imagePickerTheme.titleTextSize,
color: imagePickerTheme.titleColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_generateIconButtonWithText(
context,
theme.selectImageIcon,
theme,
Icons.image,
ImageSource.gallery,
theme.selectImageText,
onError,
),
if (config.cameraOption ?? true) ...[
SizedBox(
width: theme.spaceBetweenIcons,
),
_generateIconButtonWithText(
context,
theme.makePhotoIcon,
theme,
Icons.camera_alt_rounded,
ImageSource.camera,
theme.makePhotoText,
onError,
),
],
],
),
),
const SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_generateIconButtonWithText(
context,
imagePickerTheme,
imagePickerTheme.selectImageIcon,
ImageSource.gallery,
imagePickerTheme.selectImageText),
SizedBox(
width: imagePickerTheme.spaceBetweenIcons,
),
if (theme.closeButtonBuilder != null) ...[
theme.closeButtonBuilder!.call(
() => Navigator.of(context).pop(),
),
] else ...[
const SizedBox(height: 30),
Center(
child: SizedBox(
width: 300,
height: 40,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black,
),
onPressed: () => Navigator.of(context).pop(),
child: const Text(
"Close",
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
),
),
),
const SizedBox(height: 30),
],
_generateIconButtonWithText(
context,
imagePickerTheme,
imagePickerTheme.makePhotoIcon,
ImageSource.camera,
imagePickerTheme.makePhotoText),
],
),
);
const SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: imagePickerTheme.closeButtonWidth,
height: imagePickerTheme.closeButtonHeight,
child: customButton ??
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor:
imagePickerTheme.closeButtonBackgroundColor),
onPressed: () => Navigator.of(context).pop(),
child: Text(imagePickerTheme.closeButtonText,
style: TextStyle(
fontFamily: imagePickerTheme.font,
fontSize: imagePickerTheme.closeButtonTextSize,
color: imagePickerTheme.closeButtonTextColor,
))),
)
],
),
const SizedBox(
height: (30),
),
],
));
}
/// The [_generateIconButtonWithText] function returns a column that includes
/// an [IconButton] and [Text].
/// The function requires the following parameters to be able to generate an
/// icon with text:
/// [context] The build context that is required to make the [pickImage]
/// function in [_imagePickerService] work.
/// [imagePickerTheme] The ImagePickerTheme that includes all default values
/// for the Image Picker Dialog.
/// [icon] The icon that needs to be displayed, requires an [IconData] as
///value to be used.
/// [imageSource] The type of [ImageSource] to be used to pick an image when
/// pressed on the icon.
/// The [_generateIconButtonWithText] function returns a column that includes an [IconButton] and [Text].
/// The function requires the following parameters to be able to generate an icon with text:
/// [context] The build context that is required to make the [pickImage] function in [_imagePickerService] work.
/// [imagePickerTheme] The ImagePickerTheme that includes all default values for the Image Picker Dialog.
/// [icon] The icon that needs to be displayed, requires an [IconData] as value to be used.
/// [imageSource] The type of [ImageSource] to be used to pick an image when pressed on the icon.
/// [bottomText] The text that's displayed underneath the icon.
Column _generateIconButtonWithText(
BuildContext context,
Widget? customIcon,
ImagePickerTheme imagePickerTheme,
IconData icon,
ImageSource imageSource,
String bottomText,
Function(PlatformException error)? onError,
) =>
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
InkWell(
key: Key(bottomText),
onTap: () async {
var navigator = Navigator.of(context);
Uint8List? image;
try {
image = await (service ?? ImagePickerServiceDefault())
.pickImage(imageSource, config: config);
} on PlatformException catch (e) {
debugPrint("image_picker_error: $e");
onError?.call(e);
}
navigator.pop(image);
},
child: customIcon ??
Icon(
icon,
size: imagePickerTheme.iconSize,
color: imagePickerTheme.iconColor,
),
),
Text(
bottomText,
style: theme.iconTextStyle,
),
],
);
BuildContext context,
ImagePickerTheme imagePickerTheme,
IconData icon,
ImageSource imageSource,
String bottomText) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
key: Key(bottomText),
icon: Icon(icon),
iconSize: imagePickerTheme.iconSize,
color: imagePickerTheme.iconColor,
onPressed: () async {
final navigator = Navigator.of(context);
var image = await (imagePickerService ?? ImagePickerService())
.pickImage(imageSource);
navigator.pop(image);
},
),
Text(
bottomText,
style: TextStyle(
fontFamily: imagePickerTheme.font,
fontSize: imagePickerTheme.iconTextSize,
color: imagePickerTheme.textColor),
),
const SizedBox(
height: 20,
),
],
);
}
}

View file

@ -1,24 +1,55 @@
name: flutter_image_picker
description: A Flutter Image Picking package.
version: 4.1.0
repository: https://github.com/Iconica-Development/flutter_image_picker
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
description: A new Flutter package project.
version: 0.0.1
homepage: https://github.com/Iconica-Development/flutter_image_picker
environment:
sdk: ">=3.0.0 <4.0.0"
sdk: ">=2.17.6 <3.0.0"
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
image_picker: ^1.1.2
image_picker: ^0.8.5+3
dev_dependencies:
flutter_test:
sdk: flutter
mocktail: ^1.0.3
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis
ref: 7.0.0
flutter_lints: ^2.0.0
mocktail: ^0.3.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# To add custom fonts to your package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages

View file

@ -1,39 +1,36 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'dart:typed_data';
import "dart:typed_data";
import "package:flutter/material.dart";
import "package:flutter_image_picker/flutter_image_picker.dart"
import 'package:flutter/material.dart';
import 'package:flutter_image_picker/flutter_image_picker.dart'
as iconica_image_picker;
import "package:flutter_test/flutter_test.dart";
import "package:image_picker/image_picker.dart" as image_picker;
import "package:mocktail/mocktail.dart";
import 'package:image_picker/image_picker.dart' as image_picker;
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import "mocks/image_picker_service_mock.dart";
import 'mocks/image_picker_service_mock.dart';
void main() {
var cameraImage = Uint8List(10);
var galleryImage = Uint8List(44);
Uint8List cameraImage = Uint8List(10);
Uint8List galleryImage = Uint8List(44);
testWidgets("Image Picker Shows With Normal Theme", (tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: iconica_image_picker.ImagePicker(),
),
),
);
testWidgets('Image Picker Shows With Normal Theme', (tester) async {
await tester.pumpWidget(const MaterialApp(
home: Material(child: iconica_image_picker.ImagePicker())));
var makePhotoIconFinder = find.byIcon(Icons.camera_alt_rounded);
var makePhotoTextFinder =
final titleFinder =
find.text(const iconica_image_picker.ImagePickerTheme().title);
final makePhotoIconFinder = find
.byIcon(const iconica_image_picker.ImagePickerTheme().makePhotoIcon);
final makePhotoTextFinder =
find.text(const iconica_image_picker.ImagePickerTheme().makePhotoText);
var selectImageIconFinder = find.byIcon(Icons.image);
var selectImageTextFinder = find
final selectImageIconFinder = find
.byIcon(const iconica_image_picker.ImagePickerTheme().selectImageIcon);
final selectImageTextFinder = find
.text(const iconica_image_picker.ImagePickerTheme().selectImageText);
var closebuttonTextFinder = find.text("Close");
final closebuttonTextFinder = find
.text(const iconica_image_picker.ImagePickerTheme().closeButtonText);
expect(titleFinder, findsOneWidget);
expect(makePhotoIconFinder, findsOneWidget);
expect(makePhotoTextFinder, findsOneWidget);
expect(selectImageIconFinder, findsOneWidget);
@ -42,26 +39,20 @@ void main() {
});
testWidgets(
"Image Picker Calls Function Correctly When ImageSource Is Gallery",
'Image Picker Calls Function Correctly When ImageSource Is Gallery',
(tester) async {
var serviceMock = ImagePickerServiceMock();
ImagePickerServiceMock serviceMock = ImagePickerServiceMock();
when(() => serviceMock.pickImage(image_picker.ImageSource.gallery))
.thenAnswer((_) => Future.value(galleryImage));
await tester.pumpWidget(
MaterialApp(
await tester.pumpWidget(MaterialApp(
home: Material(
child: iconica_image_picker.ImagePicker(
service: serviceMock,
),
),
),
);
child: iconica_image_picker.ImagePicker(
imagePickerService: serviceMock))));
var finder = find.byKey(
Key(const iconica_image_picker.ImagePickerTheme().selectImageText),
);
Finder finder = find.byKey(
Key(const iconica_image_picker.ImagePickerTheme().selectImageText));
await tester.tap(finder);
@ -70,26 +61,20 @@ void main() {
});
testWidgets(
"Image Picker Calls Function Correctly When ImageSource Is Camera",
'Image Picker Calls Function Correctly When ImageSource Is Camera',
(tester) async {
var serviceMock = ImagePickerServiceMock();
ImagePickerServiceMock serviceMock = ImagePickerServiceMock();
when(() => serviceMock.pickImage(image_picker.ImageSource.camera))
.thenAnswer((_) => Future.value(cameraImage));
await tester.pumpWidget(
MaterialApp(
await tester.pumpWidget(MaterialApp(
home: Material(
child: iconica_image_picker.ImagePicker(
service: serviceMock,
),
),
),
);
child: iconica_image_picker.ImagePicker(
imagePickerService: serviceMock))));
var finder = find.byKey(
Key(const iconica_image_picker.ImagePickerTheme().makePhotoText),
);
Finder finder = find.byKey(
Key(const iconica_image_picker.ImagePickerTheme().makePhotoText));
await tester.tap(finder);
@ -97,42 +82,33 @@ void main() {
.called(1);
});
testWidgets("Image Picker Shows With Custom Theme", (tester) async {
Widget makePhotoIcon = Container(
height: 125,
width: 125,
color: Colors.red,
);
var makePhotoText = "taaaake image";
Widget selectImageIcon = Container(
height: 125,
width: 125,
color: Colors.blue,
);
var selectImageText = "seleeeeect image";
var closeButtonText = "Close";
testWidgets('Image Picker Shows With Custom Theme', (tester) async {
String title = "title";
IconData makePhotoIcon = Icons.motorcycle;
String makePhotoText = "taaaake image";
IconData selectImageIcon = Icons.chevron_left;
String selectImageText = "seleeeeect image";
String closeButtonText = "Close Dialog!";
await tester.pumpWidget(
MaterialApp(
await tester.pumpWidget(MaterialApp(
home: Material(
child: iconica_image_picker.ImagePicker(
theme: iconica_image_picker.ImagePickerTheme(
makePhotoIcon: makePhotoIcon,
makePhotoText: makePhotoText,
selectImageIcon: selectImageIcon,
selectImageText: selectImageText,
),
),
),
),
);
child: iconica_image_picker.ImagePicker(
imagePickerTheme: iconica_image_picker.ImagePickerTheme(
title: title,
makePhotoIcon: makePhotoIcon,
makePhotoText: makePhotoText,
selectImageIcon: selectImageIcon,
selectImageText: selectImageText,
closeButtonText: closeButtonText)))));
var makePhotoIconFinder = find.byWidget(makePhotoIcon);
var makePhotoTextFinder = find.text(makePhotoText);
var selectImageIconFinder = find.byWidget(selectImageIcon);
var selectImageTextFinder = find.text(selectImageText);
var closebuttonTextFinder = find.text(closeButtonText);
final titleFinder = find.text(title);
final makePhotoIconFinder = find.byIcon(makePhotoIcon);
final makePhotoTextFinder = find.text(makePhotoText);
final selectImageIconFinder = find.byIcon(selectImageIcon);
final selectImageTextFinder = find.text(selectImageText);
final closebuttonTextFinder = find.text(closeButtonText);
expect(titleFinder, findsOneWidget);
expect(makePhotoIconFinder, findsOneWidget);
expect(makePhotoTextFinder, findsOneWidget);
expect(selectImageIconFinder, findsOneWidget);

View file

@ -1,8 +1,4 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import "package:flutter_image_picker/src/services/image_picker_service.dart";
import "package:mocktail/mocktail.dart";
import 'package:flutter_image_picker/src/services/image_picker_service.dart';
import 'package:mocktail/mocktail.dart';
class ImagePickerServiceMock extends Mock implements ImagePickerService {}