├── .flutter-plugins ├── .flutter-plugins-dependencies ├── .gitignore ├── .metadata ├── .pubignore ├── CHANGELOG.md ├── LICENSE ├── PRIVACY-AND-POLICY.MD ├── README.md ├── TERMS-AND-CONDITIONS.MD ├── analysis_options.yaml ├── assets ├── add.svg ├── check.svg ├── completed-mark.svg ├── cover.png ├── light-bulb.svg ├── uo-dark.svg ├── uo.svg ├── upvote-off.svg └── upvote-on.svg ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ ├── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h │ └── RunnerTests │ │ └── RunnerTests.swift ├── lib │ └── main.dart ├── pubspec.lock └── pubspec.yaml ├── lib ├── src │ ├── logic │ │ ├── l10n.dart │ │ ├── user_orient.dart │ │ └── user_orient_data.dart │ ├── models │ │ ├── endpoint.dart │ │ ├── feature.dart │ │ ├── label.dart │ │ ├── project.dart │ │ └── user.dart │ ├── utilities │ │ ├── build_context_extensions.dart │ │ ├── helper_functions.dart │ │ ├── navigation.dart │ │ └── restful_endpoints.dart │ ├── views │ │ ├── board_view.dart │ │ ├── form_view.dart │ │ └── sent_view.dart │ └── widgets │ │ ├── bottom_padding.dart │ │ ├── button.dart │ │ ├── feature_card.dart │ │ ├── image_fade.dart │ │ ├── styled_close_button.dart │ │ ├── styled_text_field.dart │ │ ├── tip_card.dart │ │ └── watermark.dart └── userorient_flutter.dart ├── pubspec.yaml └── test └── userorient_flutter_test.dart /.flutter-plugins: -------------------------------------------------------------------------------- 1 | # This is a generated file; do not edit or check into version control. 2 | path_provider_linux=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ 3 | path_provider_windows=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ 4 | shared_preferences=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences-2.5.2/ 5 | shared_preferences_android=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.6/ 6 | shared_preferences_foundation=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/ 7 | shared_preferences_linux=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/ 8 | shared_preferences_web=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/ 9 | shared_preferences_windows=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/ 10 | url_launcher=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher-6.3.1/ 11 | url_launcher_android=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.14/ 12 | url_launcher_ios=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.2/ 13 | url_launcher_linux=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/ 14 | url_launcher_macos=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2/ 15 | url_launcher_web=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.0/ 16 | url_launcher_windows=/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/ 17 | -------------------------------------------------------------------------------- /.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"shared_preferences_foundation","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_ios","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.2/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"shared_preferences_android","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.6/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_android","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.14/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"shared_preferences_foundation","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.4/","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"url_launcher_macos","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2/","native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false},{"name":"url_launcher_linux","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/","native_build":true,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false},{"name":"url_launcher_windows","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/","native_build":true,"dependencies":[],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3/","dependencies":[],"dev_dependency":false},{"name":"url_launcher_web","path":"/Users/kamranbekirov/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.0/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2025-06-02 02:09:54.178641","version":"3.32.0","swift_package_manager_enabled":{"ios":false,"macos":false}} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | build/ 30 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "300451adae589accbece3490f4396f10bdf15e6e" 8 | channel: "stable" 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /.pubignore: -------------------------------------------------------------------------------- 1 | assets/cover.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.0 2 | 3 | - Web support is here 🎉. The board now works on Flutter for Web apps. 4 | - Improved opening transitions on Android and iOS to be more consistent with native apps. 5 | 6 | ## 1.0.0 7 | 8 | - 1.0.0 is here 🎉. This means after a long time of internal testing and polishing, UserOrient is now ready for production. 9 | - Also, fixed overflow issue in the form view when the keyboard is open. 10 | - Restricted submitting empty form. 11 | 12 | ## 0.3.2 13 | 14 | - Fix issue where labels in Spanish were having null values, causing Text widget to throw an error. 15 | - Improve localization texts. 16 | 17 | ## 0.3.1 18 | 19 | - Localize tab labels. 20 | 21 | ## 0.3.0 22 | 23 | - Add support for dark mode. 24 | - Add "Roadmap" and "Implemented" tabs to better organize the features list. 25 | - Fix language issue where only English was supported (by mistake). 26 | 27 | ## 0.2.1 28 | 29 | - Make English the default language in case the language is not supported. 30 | - Refresh the features list when the board is re-opened. 31 | - Upgrade dependencies. 32 | 33 | ## 0.2.0 34 | 35 | - Fix pub.dev score issues and update documentation. 36 | 37 | ## 0.1.9 38 | 39 | - Update documentation. 40 | 41 | ## 0.1.8 42 | 43 | - Fix issue where all first letters of words in request message were being capitalized. 44 | 45 | ## 0.1.7 46 | 47 | - Update design of the board. 48 | 49 | ## 0.1.6 50 | 51 | - Display tags of the features. 52 | 53 | ## 0.1.5 54 | 55 | - Redesigned the board with minimalistic design. 56 | 57 | ## 0.1.4 58 | 59 | - Improve documentation. 60 | - Make `UserOrient.openBoard(...)` method a `Future`. 61 | 62 | ## 0.1.3 63 | 64 | - Add English language support. 65 | 66 | ## 0.1.2 67 | 68 | - Seems like the previous bug fix didn't work. Fixed it again. 69 | 70 | ## 0.1.1 71 | 72 | - Fixed a bug where multiple users were being created on the server. 73 | 74 | ## 0.1.0 75 | 76 | - Improved the board for better user experience. 77 | 78 | ## 0.0.9 79 | 80 | - Update Flutter SDK version to 2.17.0 81 | 82 | ## 0.0.8 83 | 84 | - Improved the board for better user experience. 85 | 86 | ## 0.0.7 87 | 88 | - Improved documentation and board UI. 89 | 90 | ## 0.0.6 91 | 92 | - Cached user UUID to prevent unnecessary API calls on second launch. 93 | 94 | ## 0.0.5 95 | 96 | - Seems like the previous bug fix didn't work. Fixed it again. 97 | 98 | ## 0.0.4 99 | 100 | - Fix bug when projectId changes 101 | 102 | ## 0.0.3 103 | 104 | - Set user details using `UserOrient.setUser()` method 105 | - Beautify the board interface 106 | - Fix initialization bug 107 | 108 | ## 0.0.2 109 | 110 | - Added new header style for board. 111 | - Couple of improvements to the package. 112 | 113 | ## 0.0.1 114 | 115 | - Initial release of the package. 116 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, UserOrient 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /PRIVACY-AND-POLICY.MD: -------------------------------------------------------------------------------- 1 | # Privacy Policy 2 | 3 | **Effective Date: 25 October 2024** 4 | 5 | UserOrient values your privacy. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our service. By accessing UserOrient, you agree to the practices described here. 6 | 7 | ## 1. Information We Collect 8 | 9 | ### Personal Data 10 | We may collect: 11 | - **Account Information**: email address upon signup. 12 | - **Usage Data**: Data on how you interact with UserOrient, such as feature requests, voting activities. 13 | 14 | ### Non-Personal Data 15 | - **Cookies and Analytics**: Information about your device and browsing actions, gathered for analytics and service improvement. 16 | 17 | ## 2. How We Use Your Information 18 | 19 | Collected data is used for: 20 | - Providing and improving the UserOrient service, 21 | - Communicating updates, feature announcements, and support, 22 | - Analyzing usage trends to improve user experience. 23 | 24 | ## 3. Sharing Your Information 25 | 26 | - **Service Providers**: We work with GDPR-compliant third parties to process payments, manage analytics, and support technical operations. Data shared with these providers is limited to what is necessary for service improvement. 27 | - **Legal Requirements**: UserOrient may disclose data if required by law or to protect the security and rights of our users or the public. 28 | 29 | ## 4. Your Rights 30 | 31 | ### Under GDPR and similar regulations, you have the right to: 32 | - **Access**: Request a copy of your data. 33 | - **Correction**: Update or correct personal data. 34 | - **Deletion**: Request deletion of your account and data, with certain legal exceptions. 35 | - **Withdraw Consent**: For data processing based on consent, you can withdraw consent at any time by contacting us. 36 | 37 | Requests should be directed to: **[kamran@userorient.com](mailto:kamran@userorient.com)** 38 | 39 | ## 5. Data Security 40 | 41 | We use industry-standard practices to protect your data, including encryption and secure data storage. However, no method is 100% secure. Please secure your UserOrient account credentials. 42 | 43 | ## 6. Data Retention 44 | 45 | We retain personal data as long as necessary for service provision or as required by law. Upon account deletion, personal data will be removed from our active systems. 46 | 47 | ## 7. International Data Transfers 48 | 49 | UserOrient operates globally. Data may be stored or processed in jurisdictions with differing privacy laws. We ensure appropriate safeguards for cross-border data transfers, as required by GDPR and other regulations. 50 | 51 | ## 8. Children’s Privacy 52 | 53 | UserOrient is not intended for use by individuals under 16 years old. We do not knowingly collect data from minors. If you believe we have collected such data, contact us to delete it. 54 | 55 | ## 9. Changes to This Policy 56 | 57 | We may update this Privacy Policy periodically. Major updates will be communicated via email or app notifications. The “Effective Date” at the top indicates when changes take effect. 58 | 59 | ## 10. Contact Us 60 | 61 | For questions or requests regarding this Privacy Policy, please contact us at: 62 | - **Email**: [kamran@userorient.com](mailto:kamran@userorient.com) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [UserOrient.com](https://userorient.com) 2 | 3 | [![Pub](https://img.shields.io/pub/v/userorient_flutter.svg)](https://pub.dartlang.org/packages/userorient_flutter) 4 | [![Pub Likes](https://img.shields.io/pub/likes/userorient_flutter)](https://pub.dev/packages/userorient_flutter/score) 5 | [![Popularity](https://img.shields.io/pub/popularity/userorient_flutter)](https://pub.dev/packages/userorient_flutter/score) 6 | [![Pub points](https://img.shields.io/pub/points/userorient_flutter)](https://pub.dev/packages/userorient_flutter/score) 7 | 8 | **Feature Voting Board for Flutter** 9 | 10 | UserOrient is a feature voting board that helps you collect feedback from your users and prioritize your development roadmap in your Flutter projects. 11 | 12 |

13 | UserOrient Cover 14 |

15 | 16 | ## Getting Started 17 | 18 | Considering that you have already created a project on [UserOrient.com](https://userorient.com) and received an API key, follow these steps to integrate the SDK into your Flutter app. 19 | 20 | ### Add the dependency 21 | 22 | Add the following to your `pubspec.yaml` file: 23 | 24 | ```yaml 25 | dependencies: 26 | userorient_flutter: 27 | ``` 28 | 29 | ### Initialize the SDK 30 | 31 | Initialize the SDK with your project's API key and preferred language: 32 | 33 | ```dart 34 | import 'package:userorient_flutter/userorient_flutter.dart'; 35 | 36 | void main() { 37 | UserOrient.configure( 38 | apiKey: 'YOUR_API_KEY', 39 | languageCode: 'en', 40 | ); 41 | ``` 42 | 43 | ### Display the board 44 | 45 | To show the UserOrient board, call `UserOrient.openBoard(context)`: 46 | 47 | ```dart 48 | import 'package:userorient_flutter/userorient_flutter.dart'; 49 | 50 | void openBoard() { 51 | // Set user information 52 | UserOrient.setUser( 53 | uniqueIdentifier: '123456', 54 | fullName: 'Kamran Bekirov', 55 | email: 'kamran@userorient.com', 56 | phoneNumber: '+1234567890', 57 | language: 'en', 58 | extra: { 59 | 'age': 27, 60 | 'is_premium': true, 61 | } 62 | ); 63 | 64 | // Display the board 65 | UserOrient.openBoard(context); 66 | } 67 | ``` 68 | 69 | > **Note:** It's recommended to call `UserOrient.setUser` before each board launch to ensure up-to-date user information. 70 | 71 | ## User Identification 72 | 73 | UserOrient requires a unique identifier (`uniqueIdentifier`) for each user. This can be an email address, phone number, or custom ID. If not provided, UserOrient will generate a random identifier. 74 | 75 | ## Logging Out 76 | 77 | When a user logs out of your app, call `UserOrient.clearCache()` to prevent potential issues: 78 | 79 | ```dart 80 | await UserOrient.clearCache(); 81 | ``` 82 | 83 | ## Contact 84 | 85 | For any questions or support, please reach out to us: 86 | 87 | - Email: [kamran@userorient.com](mailto:kamran@userorient.com) 88 | - Twitter: [@userorient](https://twitter.com/userorient) 89 | 90 | --- 91 | 92 |

93 | Developed by Kamran Bekirov, por el arte 94 |

95 | -------------------------------------------------------------------------------- /TERMS-AND-CONDITIONS.MD: -------------------------------------------------------------------------------- 1 | # Terms and Conditions 2 | 3 | **Effective Date: 24 October 2024** 4 | 5 | Welcome to UserOrient! By using our service, you agree to these Terms and Conditions. Please read them carefully. 6 | 7 | ## 1. Service Overview 8 | UserOrient provides a platform for voting on feature requests, particularly for Flutter projects. Our goal is to enhance software development through user-driven feedback. 9 | 10 | ## 2. User Accounts 11 | - **Registration**: Users must provide accurate information and maintain the security of their accounts. 12 | - **Eligibility**: UserOrient is for individuals aged 16 and above. Use by minors is not permitted. 13 | 14 | ## 3. Subscriptions and Payments 15 | - **Payment Terms**: Subscription fees are billed monthly or annually as selected. 16 | - **Cancellation**: Users may cancel subscriptions through their account settings, effective at the end of the current billing cycle. 17 | 18 | ## 4. User Conduct 19 | Users agree to interact respectfully and avoid: 20 | - Posting offensive or harmful content, 21 | - Violating intellectual property rights, 22 | - Engaging in illegal activities or misuse of the platform. 23 | 24 | ## 5. Content Ownership and License 25 | - **User Content**: Users retain ownership of content they submit, such as feature requests and comments. 26 | - **License to UserOrient**: By submitting content, users grant UserOrient a license to use and display it within the platform. 27 | 28 | ## 6. Limitation of Liability 29 | UserOrient is provided on an "as-is" basis. We disclaim liability for indirect damages, including data loss or service interruptions. 30 | 31 | ## 7. Privacy and Data Use 32 | Our Privacy Policy outlines how we handle user data. By using UserOrient, you agree to the collection and use of data as described. 33 | 34 | ## 8. Modifications to Terms 35 | We may update these Terms periodically. Changes will be posted, and users will be notified of significant updates. 36 | 37 | ## 9. Governing Law 38 | These Terms will be governed by applicable laws based on our place of incorporation. 39 | 40 | ## 10. Contact Us 41 | For any questions, reach out to us at: 42 | - **Email**: [kamran@userorient.com](mailto:kamran@userorient.com) 43 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | analyzer: 3 | errors: 4 | deprecated_member_use: ignore 5 | 6 | # Additional information about this file can be found at 7 | # https://dart.dev/guides/language/analysis-options 8 | -------------------------------------------------------------------------------- /assets/add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/completed-mark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/assets/cover.png -------------------------------------------------------------------------------- /assets/light-bulb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/uo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /assets/uo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /assets/upvote-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/upvote-on.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | #.vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | **/doc/api/ 28 | **/ios/Flutter/.last_build_id 29 | .dart_tool/ 30 | .flutter-plugins 31 | .flutter-plugins-dependencies 32 | .pub-cache/ 33 | .pub/ 34 | /build/ 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "300451adae589accbece3490f4396f10bdf15e6e" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 17 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 18 | - platform: android 19 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 20 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 21 | - platform: ios 22 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 23 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 24 | - platform: linux 25 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 26 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 27 | - platform: macos 28 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 29 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 30 | - platform: web 31 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 32 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 33 | - platform: windows 34 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e 35 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace "com.example.example" 27 | compileSdk flutter.compileSdkVersion 28 | ndkVersion flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 45 | applicationId "com.example.example" 46 | // You can update the following values to match your application needs. 47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 48 | minSdkVersion flutter.minSdkVersion 49 | targetSdkVersion flutter.targetSdkVersion 50 | versionCode flutterVersionCode.toInteger() 51 | versionName flutterVersionName 52 | } 53 | 54 | buildTypes { 55 | release { 56 | // TODO: Add your own signing config for the release build. 57 | // Signing with the debug keys for now, so `flutter run --release` works. 58 | signingConfig signingConfigs.debug 59 | } 60 | } 61 | } 62 | 63 | flutter { 64 | source '../..' 65 | } 66 | 67 | dependencies {} 68 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip 6 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | } 19 | 20 | plugins { 21 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 22 | id "com.android.application" version "7.3.0" apply false 23 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false 24 | } 25 | 26 | include ":app" 27 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - shared_preferences_foundation (0.0.1): 4 | - Flutter 5 | - FlutterMacOS 6 | - url_launcher_ios (0.0.1): 7 | - Flutter 8 | 9 | DEPENDENCIES: 10 | - Flutter (from `Flutter`) 11 | - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) 12 | - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) 13 | 14 | EXTERNAL SOURCES: 15 | Flutter: 16 | :path: Flutter 17 | shared_preferences_foundation: 18 | :path: ".symlinks/plugins/shared_preferences_foundation/darwin" 19 | url_launcher_ios: 20 | :path: ".symlinks/plugins/url_launcher_ios/ios" 21 | 22 | SPEC CHECKSUMS: 23 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 24 | shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 25 | url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe 26 | 27 | PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 28 | 29 | COCOAPODS: 1.16.2 30 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | B90E7DED794FF7F9F036D6CD /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6F3078042B688C9E6B0D896 /* Pods_RunnerTests.framework */; }; 18 | C7D116C2D8C4051B1107D348 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEFCD08173BEF356ABE419F6 /* Pods_Runner.framework */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 97C146ED1CF9000F007C117D; 27 | remoteInfo = Runner; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXCopyFilesBuildPhase section */ 32 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 33 | isa = PBXCopyFilesBuildPhase; 34 | buildActionMask = 2147483647; 35 | dstPath = ""; 36 | dstSubfolderSpec = 10; 37 | files = ( 38 | ); 39 | name = "Embed Frameworks"; 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXCopyFilesBuildPhase section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 02493A2BC92F3585484F50BA /* 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 = ""; }; 46 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 47 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 48 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 49 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 51 | 3C74039FB71E2FC7D5582A30 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 52 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 53 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 54 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 55 | 80DA25B8D5EF10FBF52BBDBF /* 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 = ""; }; 56 | 8A46D74D5E1E06657EDF08B1 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 57 | 8B9E5C7FB3F2990B969015C4 /* 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 = ""; }; 58 | 8CBDCF01D91F704ED82896E0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 59 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 60 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 61 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 64 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 65 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 66 | C6F3078042B688C9E6B0D896 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 67 | DEFCD08173BEF356ABE419F6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | /* End PBXFileReference section */ 69 | 70 | /* Begin PBXFrameworksBuildPhase section */ 71 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | C7D116C2D8C4051B1107D348 /* Pods_Runner.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | F8E6CA891AE778511EBEB33A /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | B90E7DED794FF7F9F036D6CD /* Pods_RunnerTests.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXFrameworksBuildPhase section */ 88 | 89 | /* Begin PBXGroup section */ 90 | 331C8082294A63A400263BE5 /* RunnerTests */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 331C807B294A618700263BE5 /* RunnerTests.swift */, 94 | ); 95 | path = RunnerTests; 96 | sourceTree = ""; 97 | }; 98 | 41C9ED40E44E760B87C3A9CD /* Frameworks */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | DEFCD08173BEF356ABE419F6 /* Pods_Runner.framework */, 102 | C6F3078042B688C9E6B0D896 /* Pods_RunnerTests.framework */, 103 | ); 104 | name = Frameworks; 105 | sourceTree = ""; 106 | }; 107 | 9740EEB11CF90186004384FC /* Flutter */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 111 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 112 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 113 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 114 | ); 115 | name = Flutter; 116 | sourceTree = ""; 117 | }; 118 | 97C146E51CF9000F007C117D = { 119 | isa = PBXGroup; 120 | children = ( 121 | 9740EEB11CF90186004384FC /* Flutter */, 122 | 97C146F01CF9000F007C117D /* Runner */, 123 | 97C146EF1CF9000F007C117D /* Products */, 124 | 331C8082294A63A400263BE5 /* RunnerTests */, 125 | 9DA0C97A368B172A051CF4D7 /* Pods */, 126 | 41C9ED40E44E760B87C3A9CD /* Frameworks */, 127 | ); 128 | sourceTree = ""; 129 | }; 130 | 97C146EF1CF9000F007C117D /* Products */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 97C146EE1CF9000F007C117D /* Runner.app */, 134 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 135 | ); 136 | name = Products; 137 | sourceTree = ""; 138 | }; 139 | 97C146F01CF9000F007C117D /* Runner */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 143 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 144 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 145 | 97C147021CF9000F007C117D /* Info.plist */, 146 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 147 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 148 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 149 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 150 | ); 151 | path = Runner; 152 | sourceTree = ""; 153 | }; 154 | 9DA0C97A368B172A051CF4D7 /* Pods */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 8B9E5C7FB3F2990B969015C4 /* Pods-Runner.debug.xcconfig */, 158 | 80DA25B8D5EF10FBF52BBDBF /* Pods-Runner.release.xcconfig */, 159 | 02493A2BC92F3585484F50BA /* Pods-Runner.profile.xcconfig */, 160 | 8A46D74D5E1E06657EDF08B1 /* Pods-RunnerTests.debug.xcconfig */, 161 | 8CBDCF01D91F704ED82896E0 /* Pods-RunnerTests.release.xcconfig */, 162 | 3C74039FB71E2FC7D5582A30 /* Pods-RunnerTests.profile.xcconfig */, 163 | ); 164 | name = Pods; 165 | path = Pods; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 331C8080294A63A400263BE5 /* RunnerTests */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 174 | buildPhases = ( 175 | F51E0A91E6539EC064B2DDE2 /* [CP] Check Pods Manifest.lock */, 176 | 331C807D294A63A400263BE5 /* Sources */, 177 | 331C807F294A63A400263BE5 /* Resources */, 178 | F8E6CA891AE778511EBEB33A /* Frameworks */, 179 | ); 180 | buildRules = ( 181 | ); 182 | dependencies = ( 183 | 331C8086294A63A400263BE5 /* PBXTargetDependency */, 184 | ); 185 | name = RunnerTests; 186 | productName = RunnerTests; 187 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; 188 | productType = "com.apple.product-type.bundle.unit-test"; 189 | }; 190 | 97C146ED1CF9000F007C117D /* Runner */ = { 191 | isa = PBXNativeTarget; 192 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 193 | buildPhases = ( 194 | AAAA648C053CC43ED99F660A /* [CP] Check Pods Manifest.lock */, 195 | 9740EEB61CF901F6004384FC /* Run Script */, 196 | 97C146EA1CF9000F007C117D /* Sources */, 197 | 97C146EB1CF9000F007C117D /* Frameworks */, 198 | 97C146EC1CF9000F007C117D /* Resources */, 199 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 200 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 201 | 6F6E1A71588F92DF4E3A2811 /* [CP] Embed Pods Frameworks */, 202 | ); 203 | buildRules = ( 204 | ); 205 | dependencies = ( 206 | ); 207 | name = Runner; 208 | productName = Runner; 209 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 210 | productType = "com.apple.product-type.application"; 211 | }; 212 | /* End PBXNativeTarget section */ 213 | 214 | /* Begin PBXProject section */ 215 | 97C146E61CF9000F007C117D /* Project object */ = { 216 | isa = PBXProject; 217 | attributes = { 218 | BuildIndependentTargetsInParallel = YES; 219 | LastUpgradeCheck = 1510; 220 | ORGANIZATIONNAME = ""; 221 | TargetAttributes = { 222 | 331C8080294A63A400263BE5 = { 223 | CreatedOnToolsVersion = 14.0; 224 | TestTargetID = 97C146ED1CF9000F007C117D; 225 | }; 226 | 97C146ED1CF9000F007C117D = { 227 | CreatedOnToolsVersion = 7.3.1; 228 | LastSwiftMigration = 1100; 229 | }; 230 | }; 231 | }; 232 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 233 | compatibilityVersion = "Xcode 9.3"; 234 | developmentRegion = en; 235 | hasScannedForEncodings = 0; 236 | knownRegions = ( 237 | en, 238 | Base, 239 | ); 240 | mainGroup = 97C146E51CF9000F007C117D; 241 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 242 | projectDirPath = ""; 243 | projectRoot = ""; 244 | targets = ( 245 | 97C146ED1CF9000F007C117D /* Runner */, 246 | 331C8080294A63A400263BE5 /* RunnerTests */, 247 | ); 248 | }; 249 | /* End PBXProject section */ 250 | 251 | /* Begin PBXResourcesBuildPhase section */ 252 | 331C807F294A63A400263BE5 /* Resources */ = { 253 | isa = PBXResourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | 97C146EC1CF9000F007C117D /* Resources */ = { 260 | isa = PBXResourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 264 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 265 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 266 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | /* End PBXResourcesBuildPhase section */ 271 | 272 | /* Begin PBXShellScriptBuildPhase section */ 273 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 274 | isa = PBXShellScriptBuildPhase; 275 | alwaysOutOfDate = 1; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | ); 279 | inputPaths = ( 280 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 281 | ); 282 | name = "Thin Binary"; 283 | outputPaths = ( 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | shellPath = /bin/sh; 287 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 288 | }; 289 | 6F6E1A71588F92DF4E3A2811 /* [CP] Embed Pods Frameworks */ = { 290 | isa = PBXShellScriptBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | ); 294 | inputFileListPaths = ( 295 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", 296 | ); 297 | name = "[CP] Embed Pods Frameworks"; 298 | outputFileListPaths = ( 299 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | shellPath = /bin/sh; 303 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 304 | showEnvVarsInLog = 0; 305 | }; 306 | 9740EEB61CF901F6004384FC /* Run Script */ = { 307 | isa = PBXShellScriptBuildPhase; 308 | alwaysOutOfDate = 1; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | ); 312 | inputPaths = ( 313 | ); 314 | name = "Run Script"; 315 | outputPaths = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | shellPath = /bin/sh; 319 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 320 | }; 321 | AAAA648C053CC43ED99F660A /* [CP] Check Pods Manifest.lock */ = { 322 | isa = PBXShellScriptBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | ); 326 | inputFileListPaths = ( 327 | ); 328 | inputPaths = ( 329 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 330 | "${PODS_ROOT}/Manifest.lock", 331 | ); 332 | name = "[CP] Check Pods Manifest.lock"; 333 | outputFileListPaths = ( 334 | ); 335 | outputPaths = ( 336 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | shellPath = /bin/sh; 340 | 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"; 341 | showEnvVarsInLog = 0; 342 | }; 343 | F51E0A91E6539EC064B2DDE2 /* [CP] Check Pods Manifest.lock */ = { 344 | isa = PBXShellScriptBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | ); 348 | inputFileListPaths = ( 349 | ); 350 | inputPaths = ( 351 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 352 | "${PODS_ROOT}/Manifest.lock", 353 | ); 354 | name = "[CP] Check Pods Manifest.lock"; 355 | outputFileListPaths = ( 356 | ); 357 | outputPaths = ( 358 | "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | shellPath = /bin/sh; 362 | 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"; 363 | showEnvVarsInLog = 0; 364 | }; 365 | /* End PBXShellScriptBuildPhase section */ 366 | 367 | /* Begin PBXSourcesBuildPhase section */ 368 | 331C807D294A63A400263BE5 /* Sources */ = { 369 | isa = PBXSourcesBuildPhase; 370 | buildActionMask = 2147483647; 371 | files = ( 372 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 373 | ); 374 | runOnlyForDeploymentPostprocessing = 0; 375 | }; 376 | 97C146EA1CF9000F007C117D /* Sources */ = { 377 | isa = PBXSourcesBuildPhase; 378 | buildActionMask = 2147483647; 379 | files = ( 380 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 381 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 382 | ); 383 | runOnlyForDeploymentPostprocessing = 0; 384 | }; 385 | /* End PBXSourcesBuildPhase section */ 386 | 387 | /* Begin PBXTargetDependency section */ 388 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { 389 | isa = PBXTargetDependency; 390 | target = 97C146ED1CF9000F007C117D /* Runner */; 391 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; 392 | }; 393 | /* End PBXTargetDependency section */ 394 | 395 | /* Begin PBXVariantGroup section */ 396 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 397 | isa = PBXVariantGroup; 398 | children = ( 399 | 97C146FB1CF9000F007C117D /* Base */, 400 | ); 401 | name = Main.storyboard; 402 | sourceTree = ""; 403 | }; 404 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 405 | isa = PBXVariantGroup; 406 | children = ( 407 | 97C147001CF9000F007C117D /* Base */, 408 | ); 409 | name = LaunchScreen.storyboard; 410 | sourceTree = ""; 411 | }; 412 | /* End PBXVariantGroup section */ 413 | 414 | /* Begin XCBuildConfiguration section */ 415 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 416 | isa = XCBuildConfiguration; 417 | buildSettings = { 418 | ALWAYS_SEARCH_USER_PATHS = NO; 419 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 420 | CLANG_ANALYZER_NONNULL = YES; 421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 422 | CLANG_CXX_LIBRARY = "libc++"; 423 | CLANG_ENABLE_MODULES = YES; 424 | CLANG_ENABLE_OBJC_ARC = YES; 425 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_COMMA = YES; 428 | CLANG_WARN_CONSTANT_CONVERSION = YES; 429 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 430 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 431 | CLANG_WARN_EMPTY_BODY = YES; 432 | CLANG_WARN_ENUM_CONVERSION = YES; 433 | CLANG_WARN_INFINITE_RECURSION = YES; 434 | CLANG_WARN_INT_CONVERSION = YES; 435 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 436 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 439 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 440 | CLANG_WARN_STRICT_PROTOTYPES = YES; 441 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 442 | CLANG_WARN_UNREACHABLE_CODE = YES; 443 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 444 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 445 | COPY_PHASE_STRIP = NO; 446 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 447 | ENABLE_NS_ASSERTIONS = NO; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_NO_COMMON_BLOCKS = YES; 452 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 453 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 454 | GCC_WARN_UNDECLARED_SELECTOR = YES; 455 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 456 | GCC_WARN_UNUSED_FUNCTION = YES; 457 | GCC_WARN_UNUSED_VARIABLE = YES; 458 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 459 | MTL_ENABLE_DEBUG_INFO = NO; 460 | SDKROOT = iphoneos; 461 | SUPPORTED_PLATFORMS = iphoneos; 462 | TARGETED_DEVICE_FAMILY = "1,2"; 463 | VALIDATE_PRODUCT = YES; 464 | }; 465 | name = Profile; 466 | }; 467 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 468 | isa = XCBuildConfiguration; 469 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 470 | buildSettings = { 471 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 472 | CLANG_ENABLE_MODULES = YES; 473 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 474 | ENABLE_BITCODE = NO; 475 | INFOPLIST_FILE = Runner/Info.plist; 476 | LD_RUNPATH_SEARCH_PATHS = ( 477 | "$(inherited)", 478 | "@executable_path/Frameworks", 479 | ); 480 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 481 | PRODUCT_NAME = "$(TARGET_NAME)"; 482 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 483 | SWIFT_VERSION = 5.0; 484 | VERSIONING_SYSTEM = "apple-generic"; 485 | }; 486 | name = Profile; 487 | }; 488 | 331C8088294A63A400263BE5 /* Debug */ = { 489 | isa = XCBuildConfiguration; 490 | baseConfigurationReference = 8A46D74D5E1E06657EDF08B1 /* Pods-RunnerTests.debug.xcconfig */; 491 | buildSettings = { 492 | BUNDLE_LOADER = "$(TEST_HOST)"; 493 | CODE_SIGN_STYLE = Automatic; 494 | CURRENT_PROJECT_VERSION = 1; 495 | GENERATE_INFOPLIST_FILE = YES; 496 | MARKETING_VERSION = 1.0; 497 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; 498 | PRODUCT_NAME = "$(TARGET_NAME)"; 499 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 500 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 501 | SWIFT_VERSION = 5.0; 502 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 503 | }; 504 | name = Debug; 505 | }; 506 | 331C8089294A63A400263BE5 /* Release */ = { 507 | isa = XCBuildConfiguration; 508 | baseConfigurationReference = 8CBDCF01D91F704ED82896E0 /* Pods-RunnerTests.release.xcconfig */; 509 | buildSettings = { 510 | BUNDLE_LOADER = "$(TEST_HOST)"; 511 | CODE_SIGN_STYLE = Automatic; 512 | CURRENT_PROJECT_VERSION = 1; 513 | GENERATE_INFOPLIST_FILE = YES; 514 | MARKETING_VERSION = 1.0; 515 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | SWIFT_VERSION = 5.0; 518 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 519 | }; 520 | name = Release; 521 | }; 522 | 331C808A294A63A400263BE5 /* Profile */ = { 523 | isa = XCBuildConfiguration; 524 | baseConfigurationReference = 3C74039FB71E2FC7D5582A30 /* Pods-RunnerTests.profile.xcconfig */; 525 | buildSettings = { 526 | BUNDLE_LOADER = "$(TEST_HOST)"; 527 | CODE_SIGN_STYLE = Automatic; 528 | CURRENT_PROJECT_VERSION = 1; 529 | GENERATE_INFOPLIST_FILE = YES; 530 | MARKETING_VERSION = 1.0; 531 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; 532 | PRODUCT_NAME = "$(TARGET_NAME)"; 533 | SWIFT_VERSION = 5.0; 534 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 535 | }; 536 | name = Profile; 537 | }; 538 | 97C147031CF9000F007C117D /* Debug */ = { 539 | isa = XCBuildConfiguration; 540 | buildSettings = { 541 | ALWAYS_SEARCH_USER_PATHS = NO; 542 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 543 | CLANG_ANALYZER_NONNULL = YES; 544 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 545 | CLANG_CXX_LIBRARY = "libc++"; 546 | CLANG_ENABLE_MODULES = YES; 547 | CLANG_ENABLE_OBJC_ARC = YES; 548 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 549 | CLANG_WARN_BOOL_CONVERSION = YES; 550 | CLANG_WARN_COMMA = YES; 551 | CLANG_WARN_CONSTANT_CONVERSION = YES; 552 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 553 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 554 | CLANG_WARN_EMPTY_BODY = YES; 555 | CLANG_WARN_ENUM_CONVERSION = YES; 556 | CLANG_WARN_INFINITE_RECURSION = YES; 557 | CLANG_WARN_INT_CONVERSION = YES; 558 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 559 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 560 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 561 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 562 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 563 | CLANG_WARN_STRICT_PROTOTYPES = YES; 564 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 565 | CLANG_WARN_UNREACHABLE_CODE = YES; 566 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 567 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 568 | COPY_PHASE_STRIP = NO; 569 | DEBUG_INFORMATION_FORMAT = dwarf; 570 | ENABLE_STRICT_OBJC_MSGSEND = YES; 571 | ENABLE_TESTABILITY = YES; 572 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 573 | GCC_C_LANGUAGE_STANDARD = gnu99; 574 | GCC_DYNAMIC_NO_PIC = NO; 575 | GCC_NO_COMMON_BLOCKS = YES; 576 | GCC_OPTIMIZATION_LEVEL = 0; 577 | GCC_PREPROCESSOR_DEFINITIONS = ( 578 | "DEBUG=1", 579 | "$(inherited)", 580 | ); 581 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 582 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 583 | GCC_WARN_UNDECLARED_SELECTOR = YES; 584 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 585 | GCC_WARN_UNUSED_FUNCTION = YES; 586 | GCC_WARN_UNUSED_VARIABLE = YES; 587 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 588 | MTL_ENABLE_DEBUG_INFO = YES; 589 | ONLY_ACTIVE_ARCH = YES; 590 | SDKROOT = iphoneos; 591 | TARGETED_DEVICE_FAMILY = "1,2"; 592 | }; 593 | name = Debug; 594 | }; 595 | 97C147041CF9000F007C117D /* Release */ = { 596 | isa = XCBuildConfiguration; 597 | buildSettings = { 598 | ALWAYS_SEARCH_USER_PATHS = NO; 599 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 600 | CLANG_ANALYZER_NONNULL = YES; 601 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 602 | CLANG_CXX_LIBRARY = "libc++"; 603 | CLANG_ENABLE_MODULES = YES; 604 | CLANG_ENABLE_OBJC_ARC = YES; 605 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 606 | CLANG_WARN_BOOL_CONVERSION = YES; 607 | CLANG_WARN_COMMA = YES; 608 | CLANG_WARN_CONSTANT_CONVERSION = YES; 609 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 610 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 611 | CLANG_WARN_EMPTY_BODY = YES; 612 | CLANG_WARN_ENUM_CONVERSION = YES; 613 | CLANG_WARN_INFINITE_RECURSION = YES; 614 | CLANG_WARN_INT_CONVERSION = YES; 615 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 616 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 617 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 618 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 619 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 620 | CLANG_WARN_STRICT_PROTOTYPES = YES; 621 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 622 | CLANG_WARN_UNREACHABLE_CODE = YES; 623 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 624 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 625 | COPY_PHASE_STRIP = NO; 626 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 627 | ENABLE_NS_ASSERTIONS = NO; 628 | ENABLE_STRICT_OBJC_MSGSEND = YES; 629 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 630 | GCC_C_LANGUAGE_STANDARD = gnu99; 631 | GCC_NO_COMMON_BLOCKS = YES; 632 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 633 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 634 | GCC_WARN_UNDECLARED_SELECTOR = YES; 635 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 636 | GCC_WARN_UNUSED_FUNCTION = YES; 637 | GCC_WARN_UNUSED_VARIABLE = YES; 638 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 639 | MTL_ENABLE_DEBUG_INFO = NO; 640 | SDKROOT = iphoneos; 641 | SUPPORTED_PLATFORMS = iphoneos; 642 | SWIFT_COMPILATION_MODE = wholemodule; 643 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 644 | TARGETED_DEVICE_FAMILY = "1,2"; 645 | VALIDATE_PRODUCT = YES; 646 | }; 647 | name = Release; 648 | }; 649 | 97C147061CF9000F007C117D /* Debug */ = { 650 | isa = XCBuildConfiguration; 651 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 652 | buildSettings = { 653 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 654 | CLANG_ENABLE_MODULES = YES; 655 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 656 | ENABLE_BITCODE = NO; 657 | INFOPLIST_FILE = Runner/Info.plist; 658 | LD_RUNPATH_SEARCH_PATHS = ( 659 | "$(inherited)", 660 | "@executable_path/Frameworks", 661 | ); 662 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 663 | PRODUCT_NAME = "$(TARGET_NAME)"; 664 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 665 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 666 | SWIFT_VERSION = 5.0; 667 | VERSIONING_SYSTEM = "apple-generic"; 668 | }; 669 | name = Debug; 670 | }; 671 | 97C147071CF9000F007C117D /* Release */ = { 672 | isa = XCBuildConfiguration; 673 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 674 | buildSettings = { 675 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 676 | CLANG_ENABLE_MODULES = YES; 677 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 678 | ENABLE_BITCODE = NO; 679 | INFOPLIST_FILE = Runner/Info.plist; 680 | LD_RUNPATH_SEARCH_PATHS = ( 681 | "$(inherited)", 682 | "@executable_path/Frameworks", 683 | ); 684 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 685 | PRODUCT_NAME = "$(TARGET_NAME)"; 686 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 687 | SWIFT_VERSION = 5.0; 688 | VERSIONING_SYSTEM = "apple-generic"; 689 | }; 690 | name = Release; 691 | }; 692 | /* End XCBuildConfiguration section */ 693 | 694 | /* Begin XCConfigurationList section */ 695 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 696 | isa = XCConfigurationList; 697 | buildConfigurations = ( 698 | 331C8088294A63A400263BE5 /* Debug */, 699 | 331C8089294A63A400263BE5 /* Release */, 700 | 331C808A294A63A400263BE5 /* Profile */, 701 | ); 702 | defaultConfigurationIsVisible = 0; 703 | defaultConfigurationName = Release; 704 | }; 705 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 706 | isa = XCConfigurationList; 707 | buildConfigurations = ( 708 | 97C147031CF9000F007C117D /* Debug */, 709 | 97C147041CF9000F007C117D /* Release */, 710 | 249021D3217E4FDB00AE95B9 /* Profile */, 711 | ); 712 | defaultConfigurationIsVisible = 0; 713 | defaultConfigurationName = Release; 714 | }; 715 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 716 | isa = XCConfigurationList; 717 | buildConfigurations = ( 718 | 97C147061CF9000F007C117D /* Debug */, 719 | 97C147071CF9000F007C117D /* Release */, 720 | 249021D4217E4FDB00AE95B9 /* Profile */, 721 | ); 722 | defaultConfigurationIsVisible = 0; 723 | defaultConfigurationName = Release; 724 | }; 725 | /* End XCConfigurationList section */ 726 | }; 727 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 728 | } 729 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 64 | 66 | 72 | 73 | 74 | 75 | 81 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UserOrient/userorient-flutter/35374c0ac1b2f36bd651527cf942e5bba5a3b155/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:userorient_flutter/userorient_flutter.dart'; 3 | 4 | void main() async { 5 | WidgetsFlutterBinding.ensureInitialized(); 6 | 7 | UserOrient.configure( 8 | apiKey: 'YOUR_API_KEY', 9 | languageCode: 'en', 10 | ); 11 | 12 | runApp(const MainApp()); 13 | } 14 | 15 | class MainApp extends StatelessWidget { 16 | const MainApp({super.key}); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return const MaterialApp( 21 | debugShowCheckedModeBanner: false, 22 | home: HomePage(), 23 | ); 24 | } 25 | } 26 | 27 | class HomePage extends StatelessWidget { 28 | const HomePage({super.key}); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return Scaffold( 33 | body: SizedBox( 34 | width: double.infinity, 35 | child: Column( 36 | mainAxisAlignment: MainAxisAlignment.center, 37 | children: [ 38 | ListTile( 39 | leading: const Icon(Icons.feedback), 40 | title: const Text( 41 | 'Feature requests', 42 | ), 43 | subtitle: const Text( 44 | 'View and vote on feature requests', 45 | ), 46 | onTap: () { 47 | UserOrient.setUser( 48 | // uniqueIdentifier: '123123', 49 | // fullName: 'Kamran', 50 | // phoneNumber: '+994501234567', 51 | // email: 'kamran@userorient.com', 52 | // language: 'az', 53 | // extra: { 54 | // 'is_premium': true, 55 | // 'is_azerbaijani': true, 56 | // 'online_session_count': 17, 57 | // 'subscription_date': '2021-09-01', 58 | // }, 59 | ); 60 | 61 | UserOrient.openBoard(context); 62 | }, 63 | ), 64 | ListTile( 65 | leading: const Icon(Icons.feedback), 66 | title: const Text( 67 | 'Logout', 68 | ), 69 | onTap: () { 70 | UserOrient.clearCache(); 71 | }, 72 | ), 73 | ], 74 | ), 75 | ), 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | args: 5 | dependency: transitive 6 | description: 7 | name: args 8 | sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.6.0" 12 | async: 13 | dependency: transitive 14 | description: 15 | name: async 16 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.13.0" 20 | boolean_selector: 21 | dependency: transitive 22 | description: 23 | name: boolean_selector 24 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.1.2" 28 | characters: 29 | dependency: transitive 30 | description: 31 | name: characters 32 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.4.0" 36 | clock: 37 | dependency: transitive 38 | description: 39 | name: clock 40 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.1.2" 44 | collection: 45 | dependency: transitive 46 | description: 47 | name: collection 48 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.19.1" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.3" 60 | ffi: 61 | dependency: transitive 62 | description: 63 | name: ffi 64 | sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "2.1.4" 68 | file: 69 | dependency: transitive 70 | description: 71 | name: file 72 | sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "7.0.1" 76 | flutter: 77 | dependency: "direct main" 78 | description: flutter 79 | source: sdk 80 | version: "0.0.0" 81 | flutter_lints: 82 | dependency: "direct dev" 83 | description: 84 | name: flutter_lints 85 | sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" 86 | url: "https://pub.dev" 87 | source: hosted 88 | version: "3.0.2" 89 | flutter_svg: 90 | dependency: transitive 91 | description: 92 | name: flutter_svg 93 | sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b 94 | url: "https://pub.dev" 95 | source: hosted 96 | version: "2.0.17" 97 | flutter_svg_provider: 98 | dependency: transitive 99 | description: 100 | name: flutter_svg_provider 101 | sha256: cda47ab350671ba51ae4605d48f4c82fa5a2c399d22ebda367c1b407234c5048 102 | url: "https://pub.dev" 103 | source: hosted 104 | version: "1.0.7" 105 | flutter_test: 106 | dependency: "direct dev" 107 | description: flutter 108 | source: sdk 109 | version: "0.0.0" 110 | flutter_web_plugins: 111 | dependency: transitive 112 | description: flutter 113 | source: sdk 114 | version: "0.0.0" 115 | http: 116 | dependency: transitive 117 | description: 118 | name: http 119 | sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f 120 | url: "https://pub.dev" 121 | source: hosted 122 | version: "1.3.0" 123 | http_parser: 124 | dependency: transitive 125 | description: 126 | name: http_parser 127 | sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" 128 | url: "https://pub.dev" 129 | source: hosted 130 | version: "4.1.2" 131 | leak_tracker: 132 | dependency: transitive 133 | description: 134 | name: leak_tracker 135 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "10.0.9" 139 | leak_tracker_flutter_testing: 140 | dependency: transitive 141 | description: 142 | name: leak_tracker_flutter_testing 143 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "3.0.9" 147 | leak_tracker_testing: 148 | dependency: transitive 149 | description: 150 | name: leak_tracker_testing 151 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "3.0.1" 155 | lints: 156 | dependency: transitive 157 | description: 158 | name: lints 159 | sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "3.0.0" 163 | matcher: 164 | dependency: transitive 165 | description: 166 | name: matcher 167 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "0.12.17" 171 | material_color_utilities: 172 | dependency: transitive 173 | description: 174 | name: material_color_utilities 175 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "0.11.1" 179 | meta: 180 | dependency: transitive 181 | description: 182 | name: meta 183 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "1.16.0" 187 | path: 188 | dependency: transitive 189 | description: 190 | name: path 191 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "1.9.1" 195 | path_parsing: 196 | dependency: transitive 197 | description: 198 | name: path_parsing 199 | sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "1.1.0" 203 | path_provider_linux: 204 | dependency: transitive 205 | description: 206 | name: path_provider_linux 207 | sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "2.2.1" 211 | path_provider_platform_interface: 212 | dependency: transitive 213 | description: 214 | name: path_provider_platform_interface 215 | sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "2.1.2" 219 | path_provider_windows: 220 | dependency: transitive 221 | description: 222 | name: path_provider_windows 223 | sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 224 | url: "https://pub.dev" 225 | source: hosted 226 | version: "2.3.0" 227 | petitparser: 228 | dependency: transitive 229 | description: 230 | name: petitparser 231 | sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" 232 | url: "https://pub.dev" 233 | source: hosted 234 | version: "6.1.0" 235 | platform: 236 | dependency: transitive 237 | description: 238 | name: platform 239 | sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" 240 | url: "https://pub.dev" 241 | source: hosted 242 | version: "3.1.6" 243 | plugin_platform_interface: 244 | dependency: transitive 245 | description: 246 | name: plugin_platform_interface 247 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" 248 | url: "https://pub.dev" 249 | source: hosted 250 | version: "2.1.8" 251 | shared_preferences: 252 | dependency: transitive 253 | description: 254 | name: shared_preferences 255 | sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" 256 | url: "https://pub.dev" 257 | source: hosted 258 | version: "2.5.2" 259 | shared_preferences_android: 260 | dependency: transitive 261 | description: 262 | name: shared_preferences_android 263 | sha256: a768fc8ede5f0c8e6150476e14f38e2417c0864ca36bb4582be8e21925a03c22 264 | url: "https://pub.dev" 265 | source: hosted 266 | version: "2.4.6" 267 | shared_preferences_foundation: 268 | dependency: transitive 269 | description: 270 | name: shared_preferences_foundation 271 | sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" 272 | url: "https://pub.dev" 273 | source: hosted 274 | version: "2.5.4" 275 | shared_preferences_linux: 276 | dependency: transitive 277 | description: 278 | name: shared_preferences_linux 279 | sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" 280 | url: "https://pub.dev" 281 | source: hosted 282 | version: "2.4.1" 283 | shared_preferences_platform_interface: 284 | dependency: transitive 285 | description: 286 | name: shared_preferences_platform_interface 287 | sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" 288 | url: "https://pub.dev" 289 | source: hosted 290 | version: "2.4.1" 291 | shared_preferences_web: 292 | dependency: transitive 293 | description: 294 | name: shared_preferences_web 295 | sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 296 | url: "https://pub.dev" 297 | source: hosted 298 | version: "2.4.3" 299 | shared_preferences_windows: 300 | dependency: transitive 301 | description: 302 | name: shared_preferences_windows 303 | sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" 304 | url: "https://pub.dev" 305 | source: hosted 306 | version: "2.4.1" 307 | sky_engine: 308 | dependency: transitive 309 | description: flutter 310 | source: sdk 311 | version: "0.0.0" 312 | source_span: 313 | dependency: transitive 314 | description: 315 | name: source_span 316 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 317 | url: "https://pub.dev" 318 | source: hosted 319 | version: "1.10.1" 320 | stack_trace: 321 | dependency: transitive 322 | description: 323 | name: stack_trace 324 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 325 | url: "https://pub.dev" 326 | source: hosted 327 | version: "1.12.1" 328 | stream_channel: 329 | dependency: transitive 330 | description: 331 | name: stream_channel 332 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 333 | url: "https://pub.dev" 334 | source: hosted 335 | version: "2.1.4" 336 | string_scanner: 337 | dependency: transitive 338 | description: 339 | name: string_scanner 340 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 341 | url: "https://pub.dev" 342 | source: hosted 343 | version: "1.4.1" 344 | term_glyph: 345 | dependency: transitive 346 | description: 347 | name: term_glyph 348 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 349 | url: "https://pub.dev" 350 | source: hosted 351 | version: "1.2.2" 352 | test_api: 353 | dependency: transitive 354 | description: 355 | name: test_api 356 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 357 | url: "https://pub.dev" 358 | source: hosted 359 | version: "0.7.4" 360 | typed_data: 361 | dependency: transitive 362 | description: 363 | name: typed_data 364 | sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 365 | url: "https://pub.dev" 366 | source: hosted 367 | version: "1.4.0" 368 | url_launcher: 369 | dependency: transitive 370 | description: 371 | name: url_launcher 372 | sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" 373 | url: "https://pub.dev" 374 | source: hosted 375 | version: "6.3.1" 376 | url_launcher_android: 377 | dependency: transitive 378 | description: 379 | name: url_launcher_android 380 | sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" 381 | url: "https://pub.dev" 382 | source: hosted 383 | version: "6.3.14" 384 | url_launcher_ios: 385 | dependency: transitive 386 | description: 387 | name: url_launcher_ios 388 | sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" 389 | url: "https://pub.dev" 390 | source: hosted 391 | version: "6.3.2" 392 | url_launcher_linux: 393 | dependency: transitive 394 | description: 395 | name: url_launcher_linux 396 | sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" 397 | url: "https://pub.dev" 398 | source: hosted 399 | version: "3.2.1" 400 | url_launcher_macos: 401 | dependency: transitive 402 | description: 403 | name: url_launcher_macos 404 | sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" 405 | url: "https://pub.dev" 406 | source: hosted 407 | version: "3.2.2" 408 | url_launcher_platform_interface: 409 | dependency: transitive 410 | description: 411 | name: url_launcher_platform_interface 412 | sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" 413 | url: "https://pub.dev" 414 | source: hosted 415 | version: "2.3.2" 416 | url_launcher_web: 417 | dependency: transitive 418 | description: 419 | name: url_launcher_web 420 | sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" 421 | url: "https://pub.dev" 422 | source: hosted 423 | version: "2.4.0" 424 | url_launcher_windows: 425 | dependency: transitive 426 | description: 427 | name: url_launcher_windows 428 | sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" 429 | url: "https://pub.dev" 430 | source: hosted 431 | version: "3.1.4" 432 | userorient_flutter: 433 | dependency: "direct main" 434 | description: 435 | path: ".." 436 | relative: true 437 | source: path 438 | version: "1.1.0" 439 | vector_graphics: 440 | dependency: transitive 441 | description: 442 | name: vector_graphics 443 | sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" 444 | url: "https://pub.dev" 445 | source: hosted 446 | version: "1.1.18" 447 | vector_graphics_codec: 448 | dependency: transitive 449 | description: 450 | name: vector_graphics_codec 451 | sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" 452 | url: "https://pub.dev" 453 | source: hosted 454 | version: "1.1.13" 455 | vector_graphics_compiler: 456 | dependency: transitive 457 | description: 458 | name: vector_graphics_compiler 459 | sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" 460 | url: "https://pub.dev" 461 | source: hosted 462 | version: "1.1.16" 463 | vector_math: 464 | dependency: transitive 465 | description: 466 | name: vector_math 467 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 468 | url: "https://pub.dev" 469 | source: hosted 470 | version: "2.1.4" 471 | vm_service: 472 | dependency: transitive 473 | description: 474 | name: vm_service 475 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 476 | url: "https://pub.dev" 477 | source: hosted 478 | version: "15.0.0" 479 | web: 480 | dependency: transitive 481 | description: 482 | name: web 483 | sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb 484 | url: "https://pub.dev" 485 | source: hosted 486 | version: "1.1.0" 487 | xdg_directories: 488 | dependency: transitive 489 | description: 490 | name: xdg_directories 491 | sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" 492 | url: "https://pub.dev" 493 | source: hosted 494 | version: "1.1.0" 495 | xml: 496 | dependency: transitive 497 | description: 498 | name: xml 499 | sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 500 | url: "https://pub.dev" 501 | source: hosted 502 | version: "6.5.0" 503 | sdks: 504 | dart: ">=3.7.0 <4.0.0" 505 | flutter: ">=3.27.0" 506 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: "A new Flutter project." 3 | publish_to: 'none' 4 | version: 1.0.0 5 | 6 | environment: 7 | sdk: '>=3.3.3 <4.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | userorient_flutter: 13 | path: ../ 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | flutter_lints: ^3.0.0 19 | 20 | flutter: 21 | uses-material-design: true 22 | -------------------------------------------------------------------------------- /lib/src/logic/l10n.dart: -------------------------------------------------------------------------------- 1 | import 'package:userorient_flutter/userorient_flutter.dart'; 2 | 3 | class L10n { 4 | static bool isSupportedLanguage(String languageCode) { 5 | return _content.containsKey(languageCode); 6 | } 7 | 8 | static const Map _content = { 9 | 'az': { 10 | 'title': 'Təkliflər', 11 | 'tip': 'Tezliklə görmək istədiklərinizə səs verin.', 12 | 'form_hint': 'Təklifiniz nədir?', 13 | 'submit_form': 'Göndər', 14 | 'sent_title': 'Təklif göndərildi!', 15 | 'sent_description': 16 | 'Təklifinizi nəzərdən keçirəcəyik və əgər bizim yol xəritəmizə uyğun gələrsə, onu siyahıya əlavə edəcəyik. Gözləmədə qalın!', 17 | 'go_back': 'Geri qayıt', 18 | 'add_feature': 'Təklif Göndər', 19 | 'roadmap': 'Yol Xəritəsi', 20 | 'implemented': 'Tamamlanmış', 21 | 'formEmpty': 'Təklifinizi daxil edin', 22 | }, 23 | 'en': { 24 | 'title': 'Features', 25 | 'tip': 'Vote the features you want to see soon.', 26 | 'form_hint': 'Describe your idea...', 27 | 'submit_form': 'Submit', 28 | 'sent_title': 'Feature request sent!', 29 | 'sent_description': 30 | 'We will review your request and if it fits our roadmap, we will add it to our list of features to build. Stay tuned!', 31 | 'go_back': 'Go back', 32 | 'add_feature': 'Suggest Feature', 33 | 'roadmap': 'Roadmap', 34 | 'implemented': 'Implemented', 35 | 'formEmpty': 'Please enter your suggestion', 36 | }, 37 | 'es': { 38 | 'title': 'Sugerencias', 39 | 'tip': 'Vota las funciones que deseas pronto.', 40 | 'form_hint': 'Describe tu idea...', 41 | 'submit_form': 'Enviar', 42 | 'sent_title': '¡Solicitud de sugerencia enviada!', 43 | 'sent_description': 44 | 'Revisaremos tu solicitud y, si encaja en nuestra hoja de ruta, la añadiremos a nuestra lista de características por desarrollar. ¡Mantente atento!', 45 | 'go_back': 'Volver', 46 | 'add_feature': 'Agregar Sugerencia', 47 | 'roadmap': 'Ruta', 48 | 'implemented': 'Implementado', 49 | 'formEmpty': 'Ingresa tu sugerencia', 50 | }, 51 | 'it': { 52 | 'title': 'Suggerimenti', 53 | 'tip': 'Vota le funzionalità che vuoi vedere presto.', 54 | 'form_hint': 'Descrivi la tua idea...', 55 | 'submit_form': 'Invia', 56 | 'sent_title': 'Richiesta di funzionalità inviata!', 57 | 'sent_description': 58 | 'Esamineremo la tua richiesta e, se si adatta alla nostra roadmap, la aggiungeremo alla nostra lista di funzionalità da sviluppare. Resta sintonizzato!', 59 | 'go_back': 'Torna indietro', 60 | 'add_feature': 'Aggiungi Funzionalità', 61 | 'roadmap': 'Rotta', 62 | 'implemented': 'Implementato', 63 | 'formEmpty': 'Inserisci il tuo suggerimento', 64 | }, 65 | 'tr': { 66 | 'title': 'Öneriler', 67 | 'tip': 'Yakında görmek isteklerinizi oylayın.', 68 | 'form_hint': 'Fikrinizi tanımlayın...', 69 | 'submit_form': 'Gönder', 70 | 'sent_title': 'Öneri isteği gönderildi!', 71 | 'sent_description': 72 | 'Talebinizi inceleyeceğiz ve yol haritamıza uyuyorsa, geliştirilecek özellikler listemize ekleyeceğiz. Takipte kalın!', 73 | 'go_back': 'Geri dön', 74 | 'add_feature': 'Öneri Gönder', 75 | 'roadmap': 'Yol Haritası', 76 | 'implemented': 'Tamamlanmış', 77 | 'formEmpty': 'Önerinizi girin', 78 | }, 79 | }; 80 | 81 | static String get _languageCode => UserOrient.languageCode; 82 | 83 | static String get tip => _content[_languageCode]!['tip'] ?? 'N/A'; 84 | static String get formHint => _content[_languageCode]!['form_hint'] ?? 'N/A'; 85 | static String get submitForm => 86 | _content[_languageCode]!['submit_form'] ?? 'N/A'; 87 | static String get sentTitle => 88 | _content[_languageCode]!['sent_title'] ?? 'N/A'; 89 | static String get sentDescription => 90 | _content[_languageCode]!['sent_description'] ?? 'N/A'; 91 | static String get goBack => _content[_languageCode]!['go_back'] ?? 'N/A'; 92 | 93 | static String get addFeature => 94 | _content[_languageCode]!['add_feature'] ?? 'N/A'; 95 | static String get title => _content[_languageCode]!['title'] ?? 'N/A'; 96 | static String get roadmap => _content[_languageCode]!['roadmap'] ?? 'N/A'; 97 | static String get implemented => 98 | _content[_languageCode]!['implemented'] ?? 'N/A'; 99 | static String get formEmpty => _content[_languageCode]!['formEmpty'] ?? 'N/A'; 100 | } 101 | -------------------------------------------------------------------------------- /lib/src/logic/user_orient.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | import 'package:userorient_flutter/src/logic/l10n.dart'; 5 | import 'package:userorient_flutter/src/utilities/navigation.dart'; 6 | 7 | import 'package:userorient_flutter/src/models/feature.dart'; 8 | import 'package:userorient_flutter/src/logic/user_orient_data.dart'; 9 | import 'package:userorient_flutter/src/models/user.dart'; 10 | import 'package:userorient_flutter/src/utilities/helper_functions.dart'; 11 | import 'package:userorient_flutter/src/views/board_view.dart'; 12 | import 'package:userorient_flutter/src/views/form_view.dart'; 13 | 14 | class UserOrient { 15 | static final ValueNotifier?> features = ValueNotifier(null); 16 | 17 | static String? _apiKey; 18 | static User? user; 19 | static UserUUID? userUuid; 20 | static bool _isInitialized = false; 21 | static String languageCode = 'en'; 22 | 23 | /// Open the UserOrient board view 24 | static Future openBoard(BuildContext context) { 25 | _initialize(); 26 | return Navigation.push(context, const BoardView()); 27 | } 28 | 29 | /// Open the UserOrient feature request form 30 | static Future openForm(BuildContext context) { 31 | _initialize(); 32 | return Navigation.push(context, const FormView()); 33 | } 34 | 35 | /// Configure the UserOrient SDK. This method must be called before using the SDK. 36 | /// 37 | /// [apiKey] is the API Key from the UserOrient dashboard. 38 | /// [languageCode] is the language code for the user's language. 39 | static void configure({ 40 | required String apiKey, 41 | required String languageCode, 42 | }) { 43 | /// Ignore the language code if it's not English 44 | if (L10n.isSupportedLanguage(languageCode)) { 45 | UserOrient.languageCode = languageCode.toLowerCase(); 46 | } 47 | 48 | _apiKey = apiKey; 49 | } 50 | 51 | static void setUser({ 52 | String? uniqueIdentifier, 53 | String? fullName, 54 | String? email, 55 | String? phoneNumber, 56 | String? language, 57 | Map? extra, 58 | }) { 59 | final User user = User( 60 | uniqueIdentifier: uniqueIdentifier, 61 | fullName: fullName, 62 | email: email, 63 | phoneNumber: phoneNumber, 64 | language: language, 65 | extra: extra, 66 | ); 67 | 68 | UserOrient.user = user; 69 | 70 | logUO('Set user', emoji: '👤'); 71 | } 72 | 73 | static Future clearCache() async { 74 | _isInitialized = false; 75 | userUuid = null; 76 | 77 | features.value = null; 78 | 79 | final SharedPreferences prefs = await SharedPreferences.getInstance(); 80 | await prefs.remove('user_orient_project_id'); 81 | await prefs.remove('user_orient_user_uuid'); 82 | 83 | logUO('Cache cleared', emoji: '🆑'); 84 | } 85 | 86 | static Future _initialize() async { 87 | final SharedPreferences prefs = await SharedPreferences.getInstance(); 88 | 89 | final String? cachedProjectId = prefs.getString('user_orient_project_id'); 90 | final bool hasProjectId = cachedProjectId != null; 91 | final bool projectChanged = hasProjectId && cachedProjectId != _apiKey; 92 | 93 | if (projectChanged) { 94 | await clearCache(); 95 | 96 | logUO('Project changed, cache cleared...', emoji: '🔄'); 97 | } 98 | 99 | if (!_isInitialized) { 100 | logUO('Initializing the SDK', emoji: '🚁'); 101 | 102 | if (_apiKey == null) { 103 | throw 'Call `UserOrient.configure()` method before using the SDK'; 104 | } 105 | 106 | // TODO: if user id is cached, continue do that in the background 107 | userUuid = await UserOrientData.resolveUserUuid( 108 | projectId: _apiKey!, 109 | user: user, 110 | ); 111 | 112 | await _fetchAndSetFeatures(); 113 | 114 | logUO( 115 | 'Initialization completed for project $_apiKey', 116 | emoji: '✅', 117 | ); 118 | 119 | await prefs.setString('user_orient_project_id', _apiKey!); 120 | 121 | _isInitialized = true; 122 | } else { 123 | await _fetchAndSetFeatures(); 124 | } 125 | } 126 | 127 | static Future _fetchAndSetFeatures() async { 128 | final List results = await Future.wait([ 129 | UserOrientData.getFeatures(projectId: _apiKey!, userId: userUuid!), 130 | ]); 131 | 132 | final List features = results[0]; 133 | UserOrient.features.value = features; 134 | } 135 | 136 | /// Toggle the upvote status of a feature. Used internally by the SDK. 137 | static Future toggleUpvote(Feature feature) async { 138 | final List updatedFeatures = UserOrient.features.value!.map((f) { 139 | if (f.id == feature.id) { 140 | return feature.copyWith( 141 | voted: !feature.voted, 142 | voteCount: 143 | feature.voted ? feature.voteCount - 1 : feature.voteCount + 1, 144 | ); 145 | } 146 | 147 | return f; 148 | }).toList(); 149 | 150 | UserOrient.features.value = updatedFeatures; 151 | 152 | await UserOrientData.toggleUpvote( 153 | projectId: _apiKey!, 154 | userId: userUuid!, 155 | feature: feature, 156 | ); 157 | 158 | logUO( 159 | !feature.voted ? 'Upvoted' : 'Removed upvote', 160 | emoji: !feature.voted ? '👍' : '😶‍🌫️', 161 | ); 162 | } 163 | 164 | /// Submit a feature request. Used internally by the SDK. 165 | static Future submitForm({ 166 | required String content, 167 | }) async { 168 | logUO('Sending feature request', emoji: '📬'); 169 | 170 | await UserOrientData.sendFeatureRequest( 171 | projectId: _apiKey!, 172 | userId: userUuid!, 173 | content: content, 174 | ); 175 | 176 | logUO('Feature request sent', emoji: '🚀'); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /lib/src/logic/user_orient_data.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:http/http.dart' as http; 4 | import 'package:shared_preferences/shared_preferences.dart'; 5 | 6 | import 'package:userorient_flutter/src/models/endpoint.dart'; 7 | import 'package:userorient_flutter/src/models/feature.dart'; 8 | import 'package:userorient_flutter/src/models/user.dart'; 9 | import 'package:userorient_flutter/src/utilities/helper_functions.dart'; 10 | import 'package:userorient_flutter/src/utilities/restful_endpoints.dart'; 11 | 12 | typedef UserUUID = String; 13 | 14 | class UserOrientData { 15 | static Future syncUser({ 16 | required User? user, 17 | required String? cachedId, 18 | required String projectId, 19 | }) async { 20 | user ??= const User.anonymous(); 21 | final Endpoint endpoint = RestfulEndpoints.syncUser(projectId); 22 | 23 | logUO('Syncing user: ${user.toJson(cachedId)}', emoji: '🔄'); 24 | 25 | final http.Response response = await http.post( 26 | Uri.parse(endpoint.url), 27 | body: jsonEncode(user.toJson(cachedId)), 28 | headers: { 29 | 'Content-Type': 'application/json', 30 | }, 31 | ); 32 | 33 | logUO(response.body.toString(), emoji: '👀'); 34 | 35 | return jsonDecode(response.body)['id']; 36 | } 37 | 38 | static Future> getFeatures({ 39 | required String projectId, 40 | required String userId, 41 | }) async { 42 | final Endpoint endpoint = RestfulEndpoints.features( 43 | apiKey: projectId, 44 | userId: userId, 45 | ); 46 | 47 | final http.Response response = await http.get( 48 | Uri.parse(endpoint.url), 49 | ); 50 | 51 | // TODO: throws user not found when an old project's user has been used, sync user before, check if it exists then continue 52 | 53 | final List features = 54 | (jsonDecode(response.body)['features'] as List) 55 | .map((feature) => Feature.fromJson(feature)) 56 | .toList(); 57 | 58 | features.sort((a, b) => b.voteCount.compareTo(a.voteCount)); 59 | 60 | return features; 61 | } 62 | 63 | static Future toggleUpvote({ 64 | required String projectId, 65 | required String userId, 66 | required Feature feature, 67 | }) async { 68 | final Endpoint endpoint = RestfulEndpoints.toggleUpvote( 69 | projectId: projectId, 70 | userId: userId, 71 | featureId: feature.id, 72 | ); 73 | 74 | await http.post( 75 | Uri.parse(endpoint.url), 76 | body: jsonEncode(endpoint.body), 77 | headers: { 78 | 'Content-Type': 'application/json', 79 | }, 80 | ); 81 | } 82 | 83 | static Future sendFeatureRequest({ 84 | required String projectId, 85 | required String userId, 86 | required String content, 87 | }) async { 88 | final Endpoint endpoint = RestfulEndpoints.sendFeedback( 89 | projectId: projectId, 90 | content: content, 91 | userId: userId, 92 | ); 93 | 94 | await http.post( 95 | Uri.parse(endpoint.url), 96 | headers: { 97 | 'Content-Type': 'application/json', 98 | }, 99 | body: jsonEncode(endpoint.body), 100 | ); 101 | } 102 | 103 | static Future resolveUserUuid({ 104 | required String projectId, 105 | required User? user, 106 | }) async { 107 | final SharedPreferences prefs = await SharedPreferences.getInstance(); 108 | final String? cachedUuid = prefs.getString('user_orient_user_uuid'); 109 | 110 | if (cachedUuid != null) { 111 | logUO('Found cached UUID: $cachedUuid', emoji: '🔍'); 112 | 113 | UserOrientData.syncUser( 114 | user: user, 115 | projectId: projectId, 116 | cachedId: cachedUuid, 117 | ).ignore(); 118 | 119 | return cachedUuid; 120 | } else { 121 | final UserUUID uuid = await UserOrientData.syncUser( 122 | user: user, 123 | cachedId: null, 124 | projectId: projectId, 125 | ); 126 | 127 | await prefs.setString('user_orient_user_uuid', uuid); 128 | 129 | logUO('Acquired a new UUID: $uuid', emoji: '🆕'); 130 | 131 | return uuid; 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /lib/src/models/endpoint.dart: -------------------------------------------------------------------------------- 1 | class Endpoint { 2 | final String url; 3 | final String method; 4 | final dynamic body; 5 | 6 | const Endpoint({ 7 | required this.url, 8 | required this.method, 9 | this.body, 10 | }); 11 | 12 | factory Endpoint.get({ 13 | required String url, 14 | dynamic body, 15 | }) { 16 | return Endpoint( 17 | url: url, 18 | method: 'GET', 19 | body: body, 20 | ); 21 | } 22 | 23 | factory Endpoint.post({ 24 | required String url, 25 | dynamic body, 26 | }) { 27 | return Endpoint( 28 | url: url, 29 | method: 'POST', 30 | body: body, 31 | ); 32 | } 33 | 34 | factory Endpoint.put({ 35 | required String url, 36 | dynamic body, 37 | }) { 38 | return Endpoint( 39 | url: url, 40 | method: 'PUT', 41 | body: body, 42 | ); 43 | } 44 | 45 | factory Endpoint.delete({ 46 | required String url, 47 | dynamic body, 48 | }) { 49 | return Endpoint( 50 | url: url, 51 | method: 'DELETE', 52 | body: body, 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/models/feature.dart: -------------------------------------------------------------------------------- 1 | import 'package:userorient_flutter/src/models/label.dart'; 2 | 3 | class Feature { 4 | final String id; 5 | final String status; 6 | final String projectId; 7 | final String ownerType; 8 | final String? ownerFirstName; 9 | final String? ownerLastName; 10 | final int voteCount; 11 | final DateTime? createdAt; 12 | final bool voted; 13 | final Map title; 14 | final Map description; 15 | final List