mirror of
https://github.com/Iconica-Development/flutter_image_picker.git
synced 2025-05-18 19:53:45 +02:00
Compare commits
35 commits
Author | SHA1 | Date | |
---|---|---|---|
|
d8e824191a | ||
|
a6f50c54d8 | ||
|
004f0067a4 | ||
|
204e375cb8 | ||
6221ed816f | |||
e208c5031c | |||
|
a80bf1fb87 | ||
|
b3aa961e92 | ||
|
9131a82501 | ||
|
c7114d56ca | ||
|
39f5e82a48 | ||
|
75f3aac3f2 | ||
|
27d8fcd609 | ||
|
f0bac29e7f | ||
|
fdc556c476 | ||
|
29f08a94ea | ||
|
7743745c37 | ||
|
1d0efbdbd0 | ||
|
9e3eaff8c2 | ||
|
455fc691a2 | ||
|
7bdce96cf5 | ||
|
829574e5f6 | ||
|
27a8217b86 | ||
|
a09204b580 | ||
|
14d74727da | ||
|
d77f4f2f7c | ||
|
e950920a7d | ||
|
6555f54c19 | ||
|
ce73f41903 | ||
|
aed0952376 | ||
|
20814755cc | ||
|
cc1c54027a | ||
|
44b0c92ea6 | ||
|
27e8c04142 | ||
437bf79385 |
31 changed files with 560 additions and 604 deletions
10
.github/dependabot.yaml
vendored
Normal file
10
.github/dependabot.yaml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "pub"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
14
.github/workflows/component-ci.yml
vendored
Normal file
14
.github/workflows/component-ci.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
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
|
14
.github/workflows/component-documentation.yml
vendored
Normal file
14
.github/workflows/component-documentation.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
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
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -31,3 +31,7 @@ build/
|
||||||
coverage/
|
coverage/
|
||||||
/.flutter-plugins
|
/.flutter-plugins
|
||||||
/.flutter-plugins-dependencies
|
/.flutter-plugins-dependencies
|
||||||
|
|
||||||
|
# FVM Version Cache
|
||||||
|
.fvm/
|
||||||
|
.fvmrc
|
||||||
|
|
26
CHANGELOG.md
26
CHANGELOG.md
|
@ -23,4 +23,28 @@
|
||||||
|
|
||||||
## 1.0.2 - Oktober 21st 2022
|
## 1.0.2 - Oktober 21st 2022
|
||||||
|
|
||||||
- ImagePickerService can be correctly injected into the widget.
|
- 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`.
|
||||||
|
|
9
LICENSE
Normal file
9
LICENSE
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
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.
|
21
README.md
21
README.md
|
@ -1,18 +1,19 @@
|
||||||
|
[](https://github.com/Iconica-Development) [](https://github.com/Iconica-Development/flutter_image_picker/actions/new) [](https://github.com/tenhobi/effective_dart)
|
||||||
|
|
||||||
# Flutter Image Picker
|
# 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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 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
|
## Setup
|
||||||
|
|
||||||
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).
|
To use this package, add `flutter_image_picker` as a dependency in your pubspec.yaml file.
|
||||||
|
|
||||||
## How To Use
|
## How to use
|
||||||
|
|
||||||
See the [Example Code](example/lib/main.dart) for an example on how to use this package.
|
See the [Example Code](example/lib/main.dart) for an example on how to use this package.
|
||||||
|
|
||||||
|
@ -46,12 +47,12 @@ As a whole you get `ImagePicker(ImagePickerTheme(imagePickerTheme: const ImagePi
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
## Want to contribute
|
## 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](https://github.com/Iconica-Development/flutter_image_picker/pulls).
|
||||||
|
|
||||||
## Author
|
## 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>
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_iconica_analysis/analysis_options.yaml
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
# Possible to overwrite the rules from the package
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
1
example/.gitignore
vendored
1
example/.gitignore
vendored
|
@ -31,6 +31,7 @@ migrate_working_dir/
|
||||||
.pub-cache/
|
.pub-cache/
|
||||||
.pub/
|
.pub/
|
||||||
/build/
|
/build/
|
||||||
|
pubspec.lock
|
||||||
|
|
||||||
# Web related
|
# Web related
|
||||||
lib/generated_plugin_registrant.dart
|
lib/generated_plugin_registrant.dart
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.8 MiB |
|
@ -21,6 +21,6 @@
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>9.0</string>
|
<string>11.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
22
example/ios/Podfile.lock
Normal file
22
example/ios/Podfile.lock
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
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
|
|
@ -7,6 +7,7 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
@ -42,6 +44,9 @@
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -49,12 +54,24 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
0FC2B515B107F2CCC9400081 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup 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 */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -72,6 +89,8 @@
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
16A77C595AC779F26D312E25 /* Pods */,
|
||||||
|
A130C96F2C16654EE7E802F7 /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
@ -98,6 +117,14 @@
|
||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
A130C96F2C16654EE7E802F7 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BD964E61DAEEAA6F72EFFC83 /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
@ -105,12 +132,14 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
47E642748A60D4513AE80A00 /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
27ECA87BE0E31E65D21B232E /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -169,6 +198,23 @@
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase 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 */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -183,6 +229,28 @@
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
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 */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -272,7 +340,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
@ -349,7 +417,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -398,7 +466,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
|
|
@ -4,4 +4,7 @@
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|
|
@ -1,36 +1,22 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_image_picker/flutter_image_picker.dart';
|
import 'package:flutter_image_picker/flutter_image_picker.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const ProviderScope(child: ImagePickerExample()));
|
runApp(const ImagePickerExample());
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImagePickerExample extends ConsumerWidget {
|
class ImagePickerExample extends StatelessWidget {
|
||||||
const ImagePickerExample({Key? key}) : super(key: key);
|
const ImagePickerExample({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Flutter Image Picker Example',
|
title: 'Flutter Image Picker Example',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
|
@ -42,9 +28,11 @@ class ImagePickerExample extends ConsumerWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImagePickerExampleHomePage extends ConsumerStatefulWidget {
|
class ImagePickerExampleHomePage extends StatefulWidget {
|
||||||
const ImagePickerExampleHomePage({Key? key, required this.title})
|
const ImagePickerExampleHomePage({
|
||||||
: super(key: key);
|
required this.title,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
|
@ -54,24 +42,26 @@ class ImagePickerExampleHomePage extends ConsumerStatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImagePickerExampleHomePageState
|
class ImagePickerExampleHomePageState
|
||||||
extends ConsumerState<ImagePickerExampleHomePage> {
|
extends State<ImagePickerExampleHomePage> {
|
||||||
final double whiteSpace = 20;
|
final double whiteSpace = 20;
|
||||||
final double imageWidth = 300;
|
final double imageWidth = 300;
|
||||||
final String placeholder = 'assets/images/placeholder.png';
|
final String placeholder = 'assets/images/placeholder.png';
|
||||||
final String imageAlreadyDisplayedMessage =
|
final String imageAlreadyDisplayedMessage =
|
||||||
'The selected image is already being displayed!';
|
'The selected image is already being displayed!';
|
||||||
|
|
||||||
|
Uint8List? uploadedImage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final imageWatcher = ref.watch(imageProvider);
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(widget.title),
|
title: Text(widget.title),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ref.invalidate(imageProvider);
|
setState(() {
|
||||||
|
uploadedImage = null;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.delete))
|
icon: const Icon(Icons.delete))
|
||||||
],
|
],
|
||||||
|
@ -81,9 +71,8 @@ class ImagePickerExampleHomePageState
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ProviderScope(
|
Column(children: [
|
||||||
child: Column(children: [
|
if (uploadedImage == null) ...[
|
||||||
if (imageWatcher == null) ...[
|
|
||||||
Image.asset(
|
Image.asset(
|
||||||
placeholder,
|
placeholder,
|
||||||
width: imageWidth,
|
width: imageWidth,
|
||||||
|
@ -91,12 +80,12 @@ class ImagePickerExampleHomePageState
|
||||||
)
|
)
|
||||||
] else ...[
|
] else ...[
|
||||||
Image.memory(
|
Image.memory(
|
||||||
imageWatcher,
|
uploadedImage!,
|
||||||
width: imageWidth,
|
width: imageWidth,
|
||||||
height: imageWidth,
|
height: imageWidth,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
])),
|
]),
|
||||||
SizedBox(height: whiteSpace),
|
SizedBox(height: whiteSpace),
|
||||||
const Text(
|
const Text(
|
||||||
'Pick an image or make a photo!',
|
'Pick an image or make a photo!',
|
||||||
|
@ -127,10 +116,18 @@ class ImagePickerExampleHomePageState
|
||||||
Uint8List? imageInBytes = await showModalBottomSheet<Uint8List?>(
|
Uint8List? imageInBytes = await showModalBottomSheet<Uint8List?>(
|
||||||
context: context,
|
context: context,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
builder: (BuildContext context) => const ImagePicker());
|
builder: (BuildContext context) => ImagePicker(
|
||||||
|
onError: (error) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text(error.message ?? "An error occurred")),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
));
|
||||||
if (imageInBytes != null) {
|
if (imageInBytes != null) {
|
||||||
if (!listEquals(ref.read(imageProvider), imageInBytes)) {
|
if (!listEquals(uploadedImage, imageInBytes)) {
|
||||||
ref.read(imageProvider.notifier).changeImage(imageInBytes);
|
setState(() {
|
||||||
|
uploadedImage = imageInBytes;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <file_selector_linux/file_selector_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
file_selector_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import file_selector_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,278 +0,0 @@
|
||||||
# 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: "1.0.3"
|
|
||||||
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"
|
|
|
@ -39,8 +39,6 @@ dependencies:
|
||||||
flutter_image_picker:
|
flutter_image_picker:
|
||||||
path: ../
|
path: ../
|
||||||
|
|
||||||
flutter_riverpod: ^2.0.0-dev.9
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
FileSelectorWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
file_selector_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|
BIN
flutter_image_picker.gif
Normal file
BIN
flutter_image_picker.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 MiB |
|
@ -1,5 +1,10 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
///
|
||||||
library flutter_image_picker;
|
library flutter_image_picker;
|
||||||
|
|
||||||
export 'src/services/image_picker_service.dart';
|
export "src/models/image_picker_config.dart";
|
||||||
export 'src/models/image_picker_theme.dart';
|
export "src/models/image_picker_theme.dart";
|
||||||
export 'src/ui/image_picker.dart';
|
export "src/services/image_picker_service.dart";
|
||||||
|
export "src/ui/image_picker.dart";
|
||||||
|
|
23
lib/src/models/image_picker_config.dart
Normal file
23
lib/src/models/image_picker_config.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
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;
|
||||||
|
}
|
|
@ -1,92 +1,58 @@
|
||||||
import 'package:flutter/material.dart';
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
|
||||||
class ImagePickerTheme {
|
class ImagePickerTheme {
|
||||||
/// The [ImagePickerTheme] is used to style the [ImagePicker].
|
/// The [ImagePickerTheme] is used to style the [ImagePicker].
|
||||||
|
|
||||||
const ImagePickerTheme({
|
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.iconColor = Colors.black,
|
||||||
this.iconSize = 125,
|
this.iconSize = 125,
|
||||||
this.iconTextSize = 15,
|
|
||||||
this.spaceBetweenIcons = 30,
|
this.spaceBetweenIcons = 30,
|
||||||
this.makePhotoIcon,
|
this.makePhotoIcon,
|
||||||
this.makePhotoText = "Take a Picture",
|
this.makePhotoText = "TAKE PICTURE",
|
||||||
this.selectImageIcon,
|
this.selectImageIcon,
|
||||||
this.selectImageText = "Select File",
|
this.selectImageText = "UPLOAD FILE",
|
||||||
this.closeButtonText = "Close",
|
this.iconTextStyle,
|
||||||
this.closeButtonTextSize = 15,
|
this.closeButtonBuilder,
|
||||||
this.closeButtonTextColor = Colors.white,
|
this.title = "Do you want to upload a file or take a picture?",
|
||||||
this.closeButtonWidth = 300,
|
this.titleStyle,
|
||||||
this.closeButtonHeight = 40,
|
this.titleAlignment = TextAlign.center,
|
||||||
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
|
/// The color of the icons
|
||||||
final Color iconColor;
|
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.
|
/// The size of the icons that are visible in the Image Picker Dialog.
|
||||||
final double iconSize;
|
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.
|
/// The size of the space between the two icons in the Image Picker Dialog.
|
||||||
final double spaceBetweenIcons;
|
final double spaceBetweenIcons;
|
||||||
|
|
||||||
/// The icon that is displayed for the 'Make Photo' functionality of the Image Picker Dialog.
|
/// The icon that is displayed for the 'Make Photo' functionality of the
|
||||||
|
/// Image Picker Dialog.
|
||||||
final Widget? makePhotoIcon;
|
final Widget? makePhotoIcon;
|
||||||
|
|
||||||
/// The text that is displayed underneath the 'Make Photo' icon.
|
/// The text that is displayed underneath the 'Make Photo' icon.
|
||||||
final String makePhotoText;
|
final String makePhotoText;
|
||||||
|
|
||||||
/// The icon that is displayed for the 'Select Image From Gallery' functionality of the Image Picker Dialog.
|
/// The icon that is displayed for the 'Select Image From Gallery'
|
||||||
|
/// functionality of the Image Picker Dialog.
|
||||||
final Widget? selectImageIcon;
|
final Widget? 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 String selectImageText;
|
||||||
|
|
||||||
/// The text that is shown on the 'Close Dialog' button at the bottom of the Image Picker Dialog.
|
final TextStyle? iconTextStyle;
|
||||||
final String closeButtonText;
|
|
||||||
|
|
||||||
/// The fontsize of the text of the close button of the Image Picker Dialog.
|
final Widget Function(Function() onTap)? closeButtonBuilder;
|
||||||
final double closeButtonTextSize;
|
|
||||||
|
|
||||||
/// The color of the text of the close button of the Image Picker Dialog.
|
final String title;
|
||||||
final Color closeButtonTextColor;
|
|
||||||
|
|
||||||
/// The width of the 'Close Dialog' button at the bottom of the Image Picker Dialog.
|
final TextStyle? titleStyle;
|
||||||
final double closeButtonWidth;
|
|
||||||
|
|
||||||
/// The height of the 'Close Dialog' button at the bottom of the Image Picker Dialog.
|
final TextAlign titleAlignment;
|
||||||
final double closeButtonHeight;
|
|
||||||
|
|
||||||
/// The color of the close button of the Image Picker Dialog.
|
|
||||||
final Color closeButtonBackgroundColor;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,50 @@
|
||||||
import 'dart:typed_data';
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:image_picker/image_picker.dart';
|
import "dart:typed_data";
|
||||||
|
import "package:flutter_image_picker/src/models/image_picker_config.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.
|
/// The Image Picker Service class is the functionality of the Image Picker
|
||||||
/// If you have your own implementation of the Image Picker you can add it to the constructor when creating the class.
|
/// package which uses the Image Picker package to choose an image.
|
||||||
abstract class ImagePickerService {
|
/// If you have your own implementation of the Image Picker you can add it to
|
||||||
/// [pickImage] is the function that picks the image and returns it as a [Uint8List].
|
/// 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]
|
/// The function requires [source], an [ImageSource]
|
||||||
Future<Uint8List?> pickImage(ImageSource source);
|
Future<Uint8List?> pickImage(
|
||||||
|
ImageSource source, {
|
||||||
|
ImagePickerConfig? config,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ImagePickerServiceDefault is the default implementation of the ImagePickerService.
|
/// The ImagePickerServiceDefault is the default implementation of the
|
||||||
/// It uses the Image Picker package to pick an image and returns it as a [Uint8List].
|
/// ImagePickerService.
|
||||||
|
/// It uses the Image Picker package to pick an image and returns it as a
|
||||||
|
/// [Uint8List].
|
||||||
class ImagePickerServiceDefault implements ImagePickerService {
|
class ImagePickerServiceDefault implements ImagePickerService {
|
||||||
ImagePickerServiceDefault({this.imagePicker});
|
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;
|
ImagePicker? imagePicker;
|
||||||
|
|
||||||
/// [pickImage] is the function that picks the image and returns it as a [Uint8List].
|
/// [pickImage] is the function that picks the image and returns it as a
|
||||||
/// The function requires [source], an [ImageSource] that's the method of how the image needs to be picked, for example gallery or camera.
|
/// [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
|
@override
|
||||||
Future<Uint8List?> pickImage(ImageSource source) async {
|
Future<Uint8List?> pickImage(
|
||||||
var image =
|
ImageSource source, {
|
||||||
await (await (imagePicker ?? ImagePicker()).pickImage(source: source))
|
ImagePickerConfig? config,
|
||||||
?.readAsBytes();
|
}) async =>
|
||||||
return image;
|
await (await (imagePicker ?? ImagePicker()).pickImage(
|
||||||
}
|
source: source,
|
||||||
|
maxWidth: config?.maxWidth,
|
||||||
|
maxHeight: config?.maxHeight,
|
||||||
|
imageQuality: config?.imageQuality,
|
||||||
|
))
|
||||||
|
?.readAsBytes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,147 +1,166 @@
|
||||||
import 'package:flutter/material.dart';
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
import 'package:flutter_image_picker/src/services/image_picker_service.dart';
|
//
|
||||||
import 'package:image_picker/image_picker.dart';
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import '../models/image_picker_theme.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";
|
||||||
|
|
||||||
/// 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 Image Picker class generates the Image Picker Widget which can be
|
||||||
/// The first one is the [ImagePickerTheme] which can be used to change the UI of the widget.
|
/// displayed in your application. If you call the class you can give it 4
|
||||||
/// The second one is your own implementation of the ImagePickerService. Which can be used in testing for example.
|
/// optional variables:
|
||||||
/// The third one is a custom Button widget.
|
/// 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.
|
||||||
class ImagePicker extends StatelessWidget {
|
class ImagePicker extends StatelessWidget {
|
||||||
const ImagePicker({
|
const ImagePicker({
|
||||||
this.imagePickerTheme = const ImagePickerTheme(),
|
this.theme = const ImagePickerTheme(),
|
||||||
this.imagePickerService,
|
this.config = const ImagePickerConfig(),
|
||||||
this.customButton,
|
this.service,
|
||||||
|
this.onError,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// ImagePickerTheme can be used to change the UI of the Image Picker Widget to change the text/icons to your liking.
|
/// ImagePickerTheme can be used to change the UI of the Image Picker Widget to change the text/icons to your liking.
|
||||||
final ImagePickerTheme imagePickerTheme;
|
final ImagePickerTheme theme;
|
||||||
|
|
||||||
/// The Image Picker Dialog can have a custom button if you want to.
|
/// ImagePickerConfig can be used to define the size and quality for the
|
||||||
final Widget? customButton;
|
/// uploaded image.
|
||||||
|
final ImagePickerConfig config;
|
||||||
|
|
||||||
/// 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.
|
/// The ImagePickerService can be used if you want to use your own
|
||||||
final ImagePickerService? imagePickerService;
|
/// 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;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => SingleChildScrollView(
|
||||||
return SingleChildScrollView(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
tileColor: imagePickerTheme.titleBackgroundColor,
|
title: Text(
|
||||||
title: Text(
|
theme.title,
|
||||||
textAlign: imagePickerTheme.titleAlignment,
|
style:
|
||||||
imagePickerTheme.title,
|
theme.titleStyle ?? Theme.of(context).textTheme.titleMedium,
|
||||||
style: TextStyle(
|
textAlign: theme.titleAlignment,
|
||||||
fontFamily: imagePickerTheme.font,
|
),
|
||||||
fontSize: imagePickerTheme.titleTextSize,
|
|
||||||
color: imagePickerTheme.titleColor,
|
|
||||||
),
|
),
|
||||||
),
|
Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
const SizedBox(
|
children: [
|
||||||
height: 20,
|
_generateIconButtonWithText(
|
||||||
),
|
context,
|
||||||
Row(
|
theme.selectImageIcon,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
theme,
|
||||||
children: [
|
Icons.image,
|
||||||
_generateIconButtonWithText(
|
ImageSource.gallery,
|
||||||
context,
|
theme.selectImageText,
|
||||||
imagePickerTheme.selectImageIcon,
|
onError,
|
||||||
imagePickerTheme,
|
),
|
||||||
Icons.image,
|
if (config.cameraOption ?? true) ...[
|
||||||
ImageSource.gallery,
|
SizedBox(
|
||||||
imagePickerTheme.selectImageText),
|
width: theme.spaceBetweenIcons,
|
||||||
SizedBox(
|
),
|
||||||
width: imagePickerTheme.spaceBetweenIcons,
|
_generateIconButtonWithText(
|
||||||
|
context,
|
||||||
|
theme.makePhotoIcon,
|
||||||
|
theme,
|
||||||
|
Icons.camera_alt_rounded,
|
||||||
|
ImageSource.camera,
|
||||||
|
theme.makePhotoText,
|
||||||
|
onError,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
_generateIconButtonWithText(
|
if (theme.closeButtonBuilder != null) ...[
|
||||||
context,
|
theme.closeButtonBuilder!.call(
|
||||||
imagePickerTheme.makePhotoIcon,
|
() => Navigator.of(context).pop(),
|
||||||
imagePickerTheme,
|
),
|
||||||
Icons.camera_alt_rounded,
|
] else ...[
|
||||||
ImageSource.camera,
|
const SizedBox(height: 30),
|
||||||
imagePickerTheme.makePhotoText),
|
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),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
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 [_generateIconButtonWithText] function returns a column that includes
|
||||||
/// The function requires the following parameters to be able to generate an icon with text:
|
/// an [IconButton] and [Text].
|
||||||
/// [context] The build context that is required to make the [pickImage] function in [_imagePickerService] work.
|
/// The function requires the following parameters to be able to generate an
|
||||||
/// [imagePickerTheme] The ImagePickerTheme that includes all default values for the Image Picker Dialog.
|
/// icon with text:
|
||||||
/// [icon] The icon that needs to be displayed, requires an [IconData] as value to be used.
|
/// [context] The build context that is required to make the [pickImage]
|
||||||
/// [imageSource] The type of [ImageSource] to be used to pick an image when pressed on the icon.
|
/// 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.
|
/// [bottomText] The text that's displayed underneath the icon.
|
||||||
Column _generateIconButtonWithText(
|
Column _generateIconButtonWithText(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
Widget? customIcon,
|
Widget? customIcon,
|
||||||
ImagePickerTheme imagePickerTheme,
|
ImagePickerTheme imagePickerTheme,
|
||||||
IconData icon,
|
IconData icon,
|
||||||
ImageSource imageSource,
|
ImageSource imageSource,
|
||||||
String bottomText) {
|
String bottomText,
|
||||||
return Column(
|
Function(PlatformException error)? onError,
|
||||||
mainAxisSize: MainAxisSize.min,
|
) =>
|
||||||
children: <Widget>[
|
Column(
|
||||||
InkWell(
|
mainAxisSize: MainAxisSize.min,
|
||||||
key: Key(bottomText),
|
children: <Widget>[
|
||||||
onTap: () async {
|
InkWell(
|
||||||
final navigator = Navigator.of(context);
|
key: Key(bottomText),
|
||||||
var image =
|
onTap: () async {
|
||||||
await (imagePickerService ?? ImagePickerServiceDefault())
|
var navigator = Navigator.of(context);
|
||||||
.pickImage(imageSource);
|
Uint8List? image;
|
||||||
navigator.pop(image);
|
try {
|
||||||
},
|
image = await (service ?? ImagePickerServiceDefault())
|
||||||
child: customIcon ??
|
.pickImage(imageSource, config: config);
|
||||||
Icon(
|
} on PlatformException catch (e) {
|
||||||
icon,
|
debugPrint("image_picker_error: $e");
|
||||||
size: imagePickerTheme.iconSize,
|
onError?.call(e);
|
||||||
color: imagePickerTheme.iconColor,
|
}
|
||||||
),
|
navigator.pop(image);
|
||||||
),
|
},
|
||||||
Text(
|
child: customIcon ??
|
||||||
bottomText,
|
Icon(
|
||||||
style: TextStyle(
|
icon,
|
||||||
fontFamily: imagePickerTheme.font,
|
size: imagePickerTheme.iconSize,
|
||||||
fontSize: imagePickerTheme.iconTextSize,
|
color: imagePickerTheme.iconColor,
|
||||||
color: imagePickerTheme.textColor),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
Text(
|
||||||
height: 20,
|
bottomText,
|
||||||
),
|
style: theme.iconTextStyle,
|
||||||
],
|
),
|
||||||
);
|
],
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
17
pubspec.yaml
17
pubspec.yaml
|
@ -1,21 +1,24 @@
|
||||||
name: flutter_image_picker
|
name: flutter_image_picker
|
||||||
description: A Flutter Image Picking package.
|
description: A Flutter Image Picking package.
|
||||||
version: 1.0.3
|
version: 4.1.0
|
||||||
repository: https://github.com/Iconica-Development/flutter_image_picker
|
repository: https://github.com/Iconica-Development/flutter_image_picker
|
||||||
|
|
||||||
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.6 <3.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
image_picker: ^0.8.5+3
|
image_picker: ^1.1.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
mocktail: ^1.0.3
|
||||||
mocktail: ^0.3.0
|
flutter_iconica_analysis:
|
||||||
|
git:
|
||||||
flutter:
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
ref: 7.0.0
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
import 'dart:typed_data';
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import "dart:typed_data";
|
||||||
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;
|
as iconica_image_picker;
|
||||||
import 'package:image_picker/image_picker.dart' as image_picker;
|
import "package:flutter_test/flutter_test.dart";
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import "package:image_picker/image_picker.dart" as image_picker;
|
||||||
import 'package:mocktail/mocktail.dart';
|
import "package:mocktail/mocktail.dart";
|
||||||
|
|
||||||
import 'mocks/image_picker_service_mock.dart';
|
import "mocks/image_picker_service_mock.dart";
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Uint8List cameraImage = Uint8List(10);
|
var cameraImage = Uint8List(10);
|
||||||
Uint8List galleryImage = Uint8List(44);
|
var galleryImage = Uint8List(44);
|
||||||
|
|
||||||
testWidgets('Image Picker Shows With Normal Theme', (tester) async {
|
testWidgets("Image Picker Shows With Normal Theme", (tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const MaterialApp(
|
const MaterialApp(
|
||||||
home: Material(
|
home: Material(
|
||||||
|
@ -22,18 +26,14 @@ void main() {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final titleFinder =
|
var makePhotoIconFinder = find.byIcon(Icons.camera_alt_rounded);
|
||||||
find.text(const iconica_image_picker.ImagePickerTheme().title);
|
var makePhotoTextFinder =
|
||||||
final makePhotoIconFinder = find.byIcon(Icons.camera_alt_rounded);
|
|
||||||
final makePhotoTextFinder =
|
|
||||||
find.text(const iconica_image_picker.ImagePickerTheme().makePhotoText);
|
find.text(const iconica_image_picker.ImagePickerTheme().makePhotoText);
|
||||||
final selectImageIconFinder = find.byIcon(Icons.image);
|
var selectImageIconFinder = find.byIcon(Icons.image);
|
||||||
final selectImageTextFinder = find
|
var selectImageTextFinder = find
|
||||||
.text(const iconica_image_picker.ImagePickerTheme().selectImageText);
|
.text(const iconica_image_picker.ImagePickerTheme().selectImageText);
|
||||||
final closebuttonTextFinder = find
|
var closebuttonTextFinder = find.text("Close");
|
||||||
.text(const iconica_image_picker.ImagePickerTheme().closeButtonText);
|
|
||||||
|
|
||||||
expect(titleFinder, findsOneWidget);
|
|
||||||
expect(makePhotoIconFinder, findsOneWidget);
|
expect(makePhotoIconFinder, findsOneWidget);
|
||||||
expect(makePhotoTextFinder, findsOneWidget);
|
expect(makePhotoTextFinder, findsOneWidget);
|
||||||
expect(selectImageIconFinder, findsOneWidget);
|
expect(selectImageIconFinder, findsOneWidget);
|
||||||
|
@ -42,20 +42,26 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'Image Picker Calls Function Correctly When ImageSource Is Gallery',
|
"Image Picker Calls Function Correctly When ImageSource Is Gallery",
|
||||||
(tester) async {
|
(tester) async {
|
||||||
ImagePickerServiceMock serviceMock = ImagePickerServiceMock();
|
var serviceMock = ImagePickerServiceMock();
|
||||||
|
|
||||||
when(() => serviceMock.pickImage(image_picker.ImageSource.gallery))
|
when(() => serviceMock.pickImage(image_picker.ImageSource.gallery))
|
||||||
.thenAnswer((_) => Future.value(galleryImage));
|
.thenAnswer((_) => Future.value(galleryImage));
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
home: Material(
|
home: Material(
|
||||||
child: iconica_image_picker.ImagePicker(
|
child: iconica_image_picker.ImagePicker(
|
||||||
imagePickerService: serviceMock))));
|
service: serviceMock,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Finder finder = find.byKey(
|
var finder = find.byKey(
|
||||||
Key(const iconica_image_picker.ImagePickerTheme().selectImageText));
|
Key(const iconica_image_picker.ImagePickerTheme().selectImageText),
|
||||||
|
);
|
||||||
|
|
||||||
await tester.tap(finder);
|
await tester.tap(finder);
|
||||||
|
|
||||||
|
@ -64,20 +70,26 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'Image Picker Calls Function Correctly When ImageSource Is Camera',
|
"Image Picker Calls Function Correctly When ImageSource Is Camera",
|
||||||
(tester) async {
|
(tester) async {
|
||||||
ImagePickerServiceMock serviceMock = ImagePickerServiceMock();
|
var serviceMock = ImagePickerServiceMock();
|
||||||
|
|
||||||
when(() => serviceMock.pickImage(image_picker.ImageSource.camera))
|
when(() => serviceMock.pickImage(image_picker.ImageSource.camera))
|
||||||
.thenAnswer((_) => Future.value(cameraImage));
|
.thenAnswer((_) => Future.value(cameraImage));
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
home: Material(
|
home: Material(
|
||||||
child: iconica_image_picker.ImagePicker(
|
child: iconica_image_picker.ImagePicker(
|
||||||
imagePickerService: serviceMock))));
|
service: serviceMock,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Finder finder = find.byKey(
|
var finder = find.byKey(
|
||||||
Key(const iconica_image_picker.ImagePickerTheme().makePhotoText));
|
Key(const iconica_image_picker.ImagePickerTheme().makePhotoText),
|
||||||
|
);
|
||||||
|
|
||||||
await tester.tap(finder);
|
await tester.tap(finder);
|
||||||
|
|
||||||
|
@ -85,41 +97,42 @@ void main() {
|
||||||
.called(1);
|
.called(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Image Picker Shows With Custom Theme', (tester) async {
|
testWidgets("Image Picker Shows With Custom Theme", (tester) async {
|
||||||
String title = "title";
|
|
||||||
Widget makePhotoIcon = Container(
|
Widget makePhotoIcon = Container(
|
||||||
height: 125,
|
height: 125,
|
||||||
width: 125,
|
width: 125,
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
);
|
);
|
||||||
String makePhotoText = "taaaake image";
|
var makePhotoText = "taaaake image";
|
||||||
Widget selectImageIcon = Container(
|
Widget selectImageIcon = Container(
|
||||||
height: 125,
|
height: 125,
|
||||||
width: 125,
|
width: 125,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
);
|
);
|
||||||
String selectImageText = "seleeeeect image";
|
var selectImageText = "seleeeeect image";
|
||||||
String closeButtonText = "Close Dialog!";
|
var closeButtonText = "Close";
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
home: Material(
|
home: Material(
|
||||||
child: iconica_image_picker.ImagePicker(
|
child: iconica_image_picker.ImagePicker(
|
||||||
imagePickerTheme: iconica_image_picker.ImagePickerTheme(
|
theme: iconica_image_picker.ImagePickerTheme(
|
||||||
title: title,
|
makePhotoIcon: makePhotoIcon,
|
||||||
makePhotoIcon: makePhotoIcon,
|
makePhotoText: makePhotoText,
|
||||||
makePhotoText: makePhotoText,
|
selectImageIcon: selectImageIcon,
|
||||||
selectImageIcon: selectImageIcon,
|
selectImageText: selectImageText,
|
||||||
selectImageText: selectImageText,
|
),
|
||||||
closeButtonText: closeButtonText)))));
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
final titleFinder = find.text(title);
|
var makePhotoIconFinder = find.byWidget(makePhotoIcon);
|
||||||
final makePhotoIconFinder = find.byWidget(makePhotoIcon);
|
var makePhotoTextFinder = find.text(makePhotoText);
|
||||||
final makePhotoTextFinder = find.text(makePhotoText);
|
var selectImageIconFinder = find.byWidget(selectImageIcon);
|
||||||
final selectImageIconFinder = find.byWidget(selectImageIcon);
|
var selectImageTextFinder = find.text(selectImageText);
|
||||||
final selectImageTextFinder = find.text(selectImageText);
|
var closebuttonTextFinder = find.text(closeButtonText);
|
||||||
final closebuttonTextFinder = find.text(closeButtonText);
|
|
||||||
|
|
||||||
expect(titleFinder, findsOneWidget);
|
|
||||||
expect(makePhotoIconFinder, findsOneWidget);
|
expect(makePhotoIconFinder, findsOneWidget);
|
||||||
expect(makePhotoTextFinder, findsOneWidget);
|
expect(makePhotoTextFinder, findsOneWidget);
|
||||||
expect(selectImageIconFinder, findsOneWidget);
|
expect(selectImageIconFinder, findsOneWidget);
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import 'package:flutter_image_picker/src/services/image_picker_service.dart';
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
import 'package:mocktail/mocktail.dart';
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import "package:flutter_image_picker/src/services/image_picker_service.dart";
|
||||||
|
import "package:mocktail/mocktail.dart";
|
||||||
|
|
||||||
class ImagePickerServiceMock extends Mock implements ImagePickerService {}
|
class ImagePickerServiceMock extends Mock implements ImagePickerService {}
|
||||||
|
|
Loading…
Reference in a new issue