├── .gitignore
├── .metadata
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── friendlyeats
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── friendlyeater.png
├── firebase.json
├── firestore.indexes.json
├── firestore.rules
├── 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
│ ├── GoogleService-Info.plist
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── main.dart
└── src
│ ├── app.dart
│ ├── home_page.dart
│ ├── model
│ ├── data.dart
│ ├── filter.dart
│ ├── restaurant.dart
│ ├── review.dart
│ └── values.dart
│ ├── restaurant_page.dart
│ └── widgets
│ ├── app_bar.dart
│ ├── card.dart
│ ├── dialogs
│ ├── filter_select.dart
│ └── review_create.dart
│ ├── empty_list.dart
│ ├── filter_bar.dart
│ ├── grid.dart
│ ├── review.dart
│ └── stars.dart
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
└── web
├── favicon.png
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Firebase
37 | .firebase
38 | .firebaserc
39 |
40 | # Exceptions to above rules.
41 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
42 |
--------------------------------------------------------------------------------
/.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: b7d221227ca1c9916974784f682f4bb8d2513878
8 | channel: master
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to the Firebase FriendlyChat Codelab
2 |
3 | We'd love for you to contribute to our source code and to make the Firebase FriendlyChat Codelab even better than it is today! Here are the guidelines we'd like you to follow:
4 |
5 | - [Code of Conduct](#coc)
6 | - [Question or Problem?](#question)
7 | - [Issues and Bugs](#issue)
8 | - [Feature Requests](#feature)
9 | - [Submission Guidelines](#submit)
10 | - [Coding Rules](#rules)
11 | - [Signing the CLA](#cla)
12 |
13 | ## Code of Conduct
14 |
15 | As contributors and maintainers of the Firebase FriendlyChat Codelab project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
16 |
17 | Communication through any of Firebase's channels (GitHub, StackOverflow, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
18 |
19 | We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the project to do the same.
20 |
21 | If any member of the community violates this code of conduct, the maintainers of the Firebase Android Quickstarts project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
22 |
23 | If you are subject to or witness unacceptable behavior, or have any other concerns, please drop us a line at nivco@google.com.
24 |
25 | ## Got a Question or Problem?
26 |
27 | If you have questions about how to use the Firebase FriendlyChat Codelab, please direct these to [StackOverflow][stackoverflow] and use the `firebase` tag. We are also available on GitHub issues.
28 |
29 | If you feel that we're missing an important bit of documentation, feel free to
30 | file an issue so we can help. Here's an example to get you started:
31 |
32 | ```
33 | What are you trying to do or find out more about?
34 |
35 | Where have you looked?
36 |
37 | Where did you expect to find this information?
38 | ```
39 |
40 | ## Found an Issue?
41 | If you find a bug in the source code or a mistake in the documentation, you can help us by
42 | submitting an issue to our [GitHub Repository][github]. Even better you can submit a Pull Request
43 | with a fix.
44 |
45 | See [below](#submit) for some guidelines.
46 |
47 | ## Submission Guidelines
48 |
49 | ### Submitting an Issue
50 | Before you submit your issue search the archive, maybe your question was already answered.
51 |
52 | If your issue appears to be a bug, and hasn't been reported, open a new issue.
53 | Help us to maximize the effort we can spend fixing issues and adding new
54 | features, by not reporting duplicate issues. Providing the following information will increase the
55 | chances of your issue being dealt with quickly:
56 |
57 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
58 | * **Motivation for or Use Case** - explain why this is a bug for you
59 | * **Browsers and Operating System** - is this a problem with all browsers or only IE9?
60 | * **Reproduce the Error** - provide a live example (using JSBin) or a unambiguous set of steps.
61 | * **Related Issues** - has a similar issue been reported before?
62 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
63 | causing the problem (line of code or commit)
64 |
65 | **If you get help, help others. Good karma rulez!**
66 |
67 | Here's a template to get you started:
68 |
69 | ```
70 | Browser:
71 | Browser version:
72 | Operating system:
73 | Operating system version:
74 |
75 | What steps will reproduce the problem:
76 | 1.
77 | 2.
78 | 3.
79 |
80 | What is the expected result?
81 |
82 | What happens instead of that?
83 |
84 | Please provide any other information below, and attach a screenshot if possible.
85 | ```
86 |
87 | ### Submitting a Pull Request
88 | Before you submit your pull request consider the following guidelines:
89 |
90 | * Search [GitHub](https://github.com/firebase/codelab-friendlychat/pulls) for an open or closed Pull Request
91 | that relates to your submission. You don't want to duplicate effort.
92 | * Please sign our [Contributor License Agreement (CLA)](#cla) before sending pull
93 | requests. We cannot accept code without this.
94 | * Make your changes in a new git branch:
95 |
96 | ```shell
97 | git checkout -b my-fix-branch master
98 | ```
99 |
100 | * Create your patch, **including appropriate test cases**.
101 | * Follow our [Coding Rules](#rules).
102 | * Avoid checking in files that shouldn't be tracked (e.g `node_modules`, `gulp-cache`, `.tmp`, `.idea`). We recommend using a [global](#global-gitignore) gitignore for this.
103 | * Make sure **not** to include a recompiled version of the files found in `/css` and `/js` as part of your PR. We will generate these automatically.
104 | * Commit your changes using a descriptive commit message.
105 |
106 | ```shell
107 | git commit -a
108 | ```
109 | Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
110 |
111 | * Build your changes locally to ensure all the tests pass:
112 |
113 | ```shell
114 | gulp
115 | ```
116 |
117 | * Push your branch to GitHub:
118 |
119 | ```shell
120 | git push origin my-fix-branch
121 | ```
122 |
123 | * In GitHub, send a pull request to `codelab-friendlychat:master`.
124 | * If we suggest changes then:
125 | * Make the required updates.
126 | * Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
127 |
128 | ```shell
129 | git rebase master -i
130 | git push origin my-fix-branch -f
131 | ```
132 |
133 | That's it! Thank you for your contribution!
134 |
135 | #### After your pull request is merged
136 |
137 | After your pull request is merged, you can safely delete your branch and pull the changes
138 | from the main (upstream) repository:
139 |
140 | * Delete the remote branch on GitHub either through the GitHub Android UI or your local shell as follows:
141 |
142 | ```shell
143 | git push origin --delete my-fix-branch
144 | ```
145 |
146 | * Check out the master branch:
147 |
148 | ```shell
149 | git checkout master -f
150 | ```
151 |
152 | * Delete the local branch:
153 |
154 | ```shell
155 | git branch -D my-fix-branch
156 | ```
157 |
158 | * Update your master with the latest upstream version:
159 |
160 | ```shell
161 | git pull --ff upstream master
162 | ```
163 |
164 | ## Signing the CLA
165 |
166 | Please sign our [Contributor License Agreement][google-cla] (CLA) before sending pull requests. For any code
167 | changes to be accepted, the CLA must be signed. It's a quick process, we promise!
168 |
169 | *This guide was inspired by the [AngularJS contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).*
170 |
171 | [github]: https://github.com/firebase/friendlychat
172 | [google-cla]: https://cla.developers.google.com
173 | [js-style-guide]: http://google.github.io/styleguide/javascriptguide.xml
174 | [py-style-guide]: http://google.github.io/styleguide/pyguide.html
175 | [jsbin]: http://jsbin.com/
176 | [stackoverflow]: http://stackoverflow.com/questions/tagged/firebase
177 | [global-gitignore]: https://help.github.com/articles/ignoring-files/#create-a-global-gitignore
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FlutterFire Codelab: Friendly Eats
2 | A cross-platform Flutter port of the "Friendly Eats" Firestore codelab.
3 |
4 | This is the source code for the FlutterFire Friendly Eats codelab. It includes
5 | start and end versions of the required code.
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:pedantic/analysis_options.yaml
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 29
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "com.example.friendlyeats"
42 | minSdkVersion 21
43 | targetSdkVersion 29
44 | multiDexEnabled true
45 | versionCode flutterVersionCode.toInteger()
46 | versionName flutterVersionName
47 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
48 | }
49 |
50 | buildTypes {
51 | release {
52 | // TODO: Add your own signing config for the release build.
53 | // Signing with the debug keys for now, so `flutter run --release` works.
54 | signingConfig signingConfigs.debug
55 | }
56 | }
57 | }
58 |
59 | flutter {
60 | source '../..'
61 | }
62 |
63 | dependencies {
64 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
65 | implementation 'com.android.support:multidex:1.0.3'
66 | testImplementation 'junit:junit:4.12'
67 | androidTestImplementation 'androidx.test:runner:1.3.0'
68 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
69 | }
70 |
71 | apply plugin: 'com.google.gms.google-services'
72 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
24 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
42 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/friendlyeats/MainActivity.kt:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.example.friendlyeats
16 |
17 | import androidx.annotation.NonNull;
18 | import io.flutter.embedding.android.FlutterActivity
19 | import io.flutter.embedding.engine.FlutterEngine
20 | import io.flutter.plugins.GeneratedPluginRegistrant
21 |
22 | class MainActivity: FlutterActivity() {
23 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
24 | GeneratedPluginRegistrant.registerWith(flutterEngine);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
24 |
25 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.0.1'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | classpath 'com.google.gms:google-services:4.3.3'
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | rootProject.buildDir = '../build'
23 | subprojects {
24 | project.buildDir = "${rootProject.buildDir}/${project.name}"
25 | }
26 | subprojects {
27 | project.evaluationDependsOn(':app')
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 06 18:43:15 CEST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/assets/friendlyeater.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/assets/friendlyeater.png
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": {
3 | "predeploy": "flutter clean && flutter build web",
4 | "public": "build/web",
5 | "ignore": [
6 | "firebase.json",
7 | "**/.*",
8 | "**/node_modules/**"
9 | ],
10 | "rewrites": [
11 | {
12 | "source": "**",
13 | "destination": "/index.html"
14 | }
15 | ]
16 | },
17 | "firestore": {
18 | "rules": "firestore.rules",
19 | "indexes": "firestore.indexes.json"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/firestore.indexes.json:
--------------------------------------------------------------------------------
1 | {
2 | "indexes": [
3 | {
4 | "collectionGroup": "restaurants",
5 | "queryScope": "COLLECTION",
6 | "fields": [
7 | {
8 | "fieldPath": "price",
9 | "order": "ASCENDING"
10 | },
11 | {
12 | "fieldPath": "avgRating",
13 | "order": "DESCENDING"
14 | }
15 | ]
16 | },
17 | {
18 | "collectionGroup": "restaurants",
19 | "queryScope": "COLLECTION",
20 | "fields": [
21 | {
22 | "fieldPath": "city",
23 | "order": "ASCENDING"
24 | },
25 | {
26 | "fieldPath": "avgRating",
27 | "order": "DESCENDING"
28 | }
29 | ]
30 | },
31 | {
32 | "collectionGroup": "restaurants",
33 | "queryScope": "COLLECTION",
34 | "fields": [
35 | {
36 | "fieldPath": "price",
37 | "order": "ASCENDING"
38 | },
39 | {
40 | "fieldPath": "numRatings",
41 | "order": "DESCENDING"
42 | }
43 | ]
44 | },
45 | {
46 | "collectionGroup": "restaurants",
47 | "queryScope": "COLLECTION",
48 | "fields": [
49 | {
50 | "fieldPath": "city",
51 | "order": "ASCENDING"
52 | },
53 | {
54 | "fieldPath": "numRatings",
55 | "order": "DESCENDING"
56 | }
57 | ]
58 | },
59 | {
60 | "collectionGroup": "restaurants",
61 | "queryScope": "COLLECTION",
62 | "fields": [
63 | {
64 | "fieldPath": "category",
65 | "order": "ASCENDING"
66 | },
67 | {
68 | "fieldPath": "avgRating",
69 | "order": "DESCENDING"
70 | }
71 | ]
72 | },
73 | {
74 | "collectionGroup": "restaurants",
75 | "queryScope": "COLLECTION",
76 | "fields": [
77 | {
78 | "fieldPath": "category",
79 | "order": "ASCENDING"
80 | },
81 | {
82 | "fieldPath": "price",
83 | "order": "ASCENDING"
84 | }
85 | ]
86 | },
87 | {
88 | "collectionGroup": "restaurants",
89 | "queryScope": "COLLECTION",
90 | "fields": [
91 | {
92 | "fieldPath": "city",
93 | "order": "ASCENDING"
94 | },
95 | {
96 | "fieldPath": "price",
97 | "order": "ASCENDING"
98 | }
99 | ]
100 | },
101 | {
102 | "collectionGroup": "restaurants",
103 | "queryScope": "COLLECTION",
104 | "fields": [
105 | {
106 | "fieldPath": "category",
107 | "order": "ASCENDING"
108 | },
109 | {
110 | "fieldPath": "numRatings",
111 | "order": "DESCENDING"
112 | }
113 | ]
114 | }
115 | ],
116 | "fieldOverrides": []
117 | }
--------------------------------------------------------------------------------
/firestore.rules:
--------------------------------------------------------------------------------
1 | service cloud.firestore {
2 | match /databases/{database}/documents {
3 | // Restaurants:
4 | // - Authenticated user can read
5 | // - Authenticated user can create/update (for demo)
6 | // - Validate updates
7 | // - Deletes are not allowed
8 | match /restaurants/{restaurantId} {
9 | allow read, create: if request.auth != null;
10 | allow update: if request.auth != null
11 | && request.resource.data.name == resource.data.name
12 | allow delete: if false;
13 |
14 | // Ratings:
15 | // - Authenticated user can read
16 | // - Authenticated user can create if userId matches
17 | // - Deletes and updates are not allowed
18 | match /ratings/{ratingId} {
19 | allow read: if request.auth != null;
20 | allow create: if request.auth != null
21 | && request.resource.data.userId == request.auth.uid;
22 | allow update, delete: if false;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.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 parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | generated_key_values = {}
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) do |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | generated_key_values[podname] = podpath
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | end
32 | generated_key_values
33 | end
34 |
35 | target 'Runner' do
36 | use_frameworks!
37 | use_modular_headers!
38 |
39 | # Flutter Pod
40 |
41 | copied_flutter_dir = File.join(__dir__, 'Flutter')
42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
48 |
49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
50 | unless File.exist?(generated_xcode_build_settings_path)
51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
52 | end
53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
55 |
56 | unless File.exist?(copied_framework_path)
57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
58 | end
59 | unless File.exist?(copied_podspec_path)
60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
61 | end
62 | end
63 |
64 | # Keep pod path relative so it can be checked into Podfile.lock.
65 | pod 'Flutter', :path => 'Flutter'
66 |
67 | # Plugin Pods
68 |
69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
70 | # referring to absolute paths on developers' machines.
71 | system('rm -rf .symlinks')
72 | system('mkdir -p .symlinks/plugins')
73 | plugin_pods = parse_KV_file('../.flutter-plugins')
74 | plugin_pods.each do |name, path|
75 | symlink = File.join('.symlinks', 'plugins', name)
76 | File.symlink(path, symlink)
77 | pod name, :path => File.join(symlink, 'ios')
78 | end
79 | end
80 |
81 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
82 | install! 'cocoapods', :disable_input_output_paths => true
83 |
84 | post_install do |installer|
85 | installer.pods_project.targets.each do |target|
86 | target.build_configurations.each do |config|
87 | config.build_settings['ENABLE_BITCODE'] = 'NO'
88 | end
89 | end
90 | end
91 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - abseil/algorithm (0.20190808):
3 | - abseil/algorithm/algorithm (= 0.20190808)
4 | - abseil/algorithm/container (= 0.20190808)
5 | - abseil/algorithm/algorithm (0.20190808)
6 | - abseil/algorithm/container (0.20190808):
7 | - abseil/algorithm/algorithm
8 | - abseil/base/core_headers
9 | - abseil/meta/type_traits
10 | - abseil/base (0.20190808):
11 | - abseil/base/atomic_hook (= 0.20190808)
12 | - abseil/base/base (= 0.20190808)
13 | - abseil/base/base_internal (= 0.20190808)
14 | - abseil/base/bits (= 0.20190808)
15 | - abseil/base/config (= 0.20190808)
16 | - abseil/base/core_headers (= 0.20190808)
17 | - abseil/base/dynamic_annotations (= 0.20190808)
18 | - abseil/base/endian (= 0.20190808)
19 | - abseil/base/log_severity (= 0.20190808)
20 | - abseil/base/malloc_internal (= 0.20190808)
21 | - abseil/base/pretty_function (= 0.20190808)
22 | - abseil/base/spinlock_wait (= 0.20190808)
23 | - abseil/base/throw_delegate (= 0.20190808)
24 | - abseil/base/atomic_hook (0.20190808)
25 | - abseil/base/base (0.20190808):
26 | - abseil/base/atomic_hook
27 | - abseil/base/base_internal
28 | - abseil/base/config
29 | - abseil/base/core_headers
30 | - abseil/base/dynamic_annotations
31 | - abseil/base/log_severity
32 | - abseil/base/spinlock_wait
33 | - abseil/meta/type_traits
34 | - abseil/base/base_internal (0.20190808):
35 | - abseil/meta/type_traits
36 | - abseil/base/bits (0.20190808):
37 | - abseil/base/core_headers
38 | - abseil/base/config (0.20190808)
39 | - abseil/base/core_headers (0.20190808):
40 | - abseil/base/config
41 | - abseil/base/dynamic_annotations (0.20190808)
42 | - abseil/base/endian (0.20190808):
43 | - abseil/base/config
44 | - abseil/base/core_headers
45 | - abseil/base/log_severity (0.20190808):
46 | - abseil/base/core_headers
47 | - abseil/base/malloc_internal (0.20190808):
48 | - abseil/base/base
49 | - abseil/base/config
50 | - abseil/base/core_headers
51 | - abseil/base/dynamic_annotations
52 | - abseil/base/spinlock_wait
53 | - abseil/base/pretty_function (0.20190808)
54 | - abseil/base/spinlock_wait (0.20190808):
55 | - abseil/base/core_headers
56 | - abseil/base/throw_delegate (0.20190808):
57 | - abseil/base/base
58 | - abseil/base/config
59 | - abseil/memory (0.20190808):
60 | - abseil/memory/memory (= 0.20190808)
61 | - abseil/memory/memory (0.20190808):
62 | - abseil/base/core_headers
63 | - abseil/meta/type_traits
64 | - abseil/meta (0.20190808):
65 | - abseil/meta/type_traits (= 0.20190808)
66 | - abseil/meta/type_traits (0.20190808):
67 | - abseil/base/config
68 | - abseil/numeric/int128 (0.20190808):
69 | - abseil/base/config
70 | - abseil/base/core_headers
71 | - abseil/strings/internal (0.20190808):
72 | - abseil/base/core_headers
73 | - abseil/base/endian
74 | - abseil/meta/type_traits
75 | - abseil/strings/strings (0.20190808):
76 | - abseil/base/base
77 | - abseil/base/bits
78 | - abseil/base/config
79 | - abseil/base/core_headers
80 | - abseil/base/endian
81 | - abseil/base/throw_delegate
82 | - abseil/memory/memory
83 | - abseil/meta/type_traits
84 | - abseil/numeric/int128
85 | - abseil/strings/internal
86 | - abseil/time (0.20190808):
87 | - abseil/time/internal (= 0.20190808)
88 | - abseil/time/time (= 0.20190808)
89 | - abseil/time/internal (0.20190808):
90 | - abseil/time/internal/cctz (= 0.20190808)
91 | - abseil/time/internal/cctz (0.20190808):
92 | - abseil/time/internal/cctz/civil_time (= 0.20190808)
93 | - abseil/time/internal/cctz/includes (= 0.20190808)
94 | - abseil/time/internal/cctz/time_zone (= 0.20190808)
95 | - abseil/time/internal/cctz/civil_time (0.20190808)
96 | - abseil/time/internal/cctz/includes (0.20190808)
97 | - abseil/time/internal/cctz/time_zone (0.20190808):
98 | - abseil/time/internal/cctz/civil_time
99 | - abseil/time/time (0.20190808):
100 | - abseil/base/base
101 | - abseil/base/core_headers
102 | - abseil/numeric/int128
103 | - abseil/strings/strings
104 | - abseil/time/internal/cctz/civil_time
105 | - abseil/time/internal/cctz/time_zone
106 | - abseil/types (0.20190808):
107 | - abseil/types/any (= 0.20190808)
108 | - abseil/types/bad_any_cast (= 0.20190808)
109 | - abseil/types/bad_any_cast_impl (= 0.20190808)
110 | - abseil/types/bad_optional_access (= 0.20190808)
111 | - abseil/types/bad_variant_access (= 0.20190808)
112 | - abseil/types/compare (= 0.20190808)
113 | - abseil/types/optional (= 0.20190808)
114 | - abseil/types/span (= 0.20190808)
115 | - abseil/types/variant (= 0.20190808)
116 | - abseil/types/any (0.20190808):
117 | - abseil/base/config
118 | - abseil/base/core_headers
119 | - abseil/meta/type_traits
120 | - abseil/types/bad_any_cast
121 | - abseil/utility/utility
122 | - abseil/types/bad_any_cast (0.20190808):
123 | - abseil/base/config
124 | - abseil/types/bad_any_cast_impl
125 | - abseil/types/bad_any_cast_impl (0.20190808):
126 | - abseil/base/base
127 | - abseil/base/config
128 | - abseil/types/bad_optional_access (0.20190808):
129 | - abseil/base/base
130 | - abseil/base/config
131 | - abseil/types/bad_variant_access (0.20190808):
132 | - abseil/base/base
133 | - abseil/base/config
134 | - abseil/types/compare (0.20190808):
135 | - abseil/base/core_headers
136 | - abseil/meta/type_traits
137 | - abseil/types/optional (0.20190808):
138 | - abseil/base/base_internal
139 | - abseil/base/config
140 | - abseil/base/core_headers
141 | - abseil/memory/memory
142 | - abseil/meta/type_traits
143 | - abseil/types/bad_optional_access
144 | - abseil/utility/utility
145 | - abseil/types/span (0.20190808):
146 | - abseil/algorithm/algorithm
147 | - abseil/base/core_headers
148 | - abseil/base/throw_delegate
149 | - abseil/meta/type_traits
150 | - abseil/types/variant (0.20190808):
151 | - abseil/base/base_internal
152 | - abseil/base/config
153 | - abseil/base/core_headers
154 | - abseil/meta/type_traits
155 | - abseil/types/bad_variant_access
156 | - abseil/utility/utility
157 | - abseil/utility/utility (0.20190808):
158 | - abseil/base/base_internal
159 | - abseil/base/config
160 | - abseil/meta/type_traits
161 | - BoringSSL-GRPC (0.0.3):
162 | - BoringSSL-GRPC/Implementation (= 0.0.3)
163 | - BoringSSL-GRPC/Interface (= 0.0.3)
164 | - BoringSSL-GRPC/Implementation (0.0.3):
165 | - BoringSSL-GRPC/Interface (= 0.0.3)
166 | - BoringSSL-GRPC/Interface (0.0.3)
167 | - cloud_firestore (0.0.1):
168 | - Firebase/Core
169 | - Firebase/Firestore (~> 6.0)
170 | - Flutter
171 | - cloud_firestore_web (0.1.0):
172 | - Flutter
173 | - Firebase/Auth (6.14.0):
174 | - Firebase/CoreOnly
175 | - FirebaseAuth (~> 6.4.1)
176 | - Firebase/Core (6.14.0):
177 | - Firebase/CoreOnly
178 | - FirebaseAnalytics (= 6.1.7)
179 | - Firebase/CoreOnly (6.14.0):
180 | - FirebaseCore (= 6.5.0)
181 | - Firebase/Firestore (6.14.0):
182 | - Firebase/CoreOnly
183 | - FirebaseFirestore (~> 1.8.2)
184 | - firebase_auth (0.0.1):
185 | - Firebase/Auth (~> 6.3)
186 | - Firebase/Core
187 | - Flutter
188 | - firebase_auth_web (0.1.0):
189 | - Flutter
190 | - firebase_core (0.0.1):
191 | - Firebase/Core
192 | - Flutter
193 | - firebase_core_web (0.1.0):
194 | - Flutter
195 | - FirebaseAnalytics (6.1.7):
196 | - FirebaseCore (~> 6.5)
197 | - FirebaseInstanceID (~> 4.2)
198 | - GoogleAppMeasurement (= 6.1.7)
199 | - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
200 | - GoogleUtilities/MethodSwizzler (~> 6.0)
201 | - GoogleUtilities/Network (~> 6.0)
202 | - "GoogleUtilities/NSData+zlib (~> 6.0)"
203 | - nanopb (= 0.3.9011)
204 | - FirebaseAuth (6.4.1):
205 | - FirebaseAuthInterop (~> 1.0)
206 | - FirebaseCore (~> 6.2)
207 | - GoogleUtilities/AppDelegateSwizzler (~> 6.2)
208 | - GoogleUtilities/Environment (~> 6.2)
209 | - GTMSessionFetcher/Core (~> 1.1)
210 | - FirebaseAuthInterop (1.0.0)
211 | - FirebaseCore (6.5.0):
212 | - FirebaseCoreDiagnostics (~> 1.0)
213 | - FirebaseCoreDiagnosticsInterop (~> 1.0)
214 | - GoogleUtilities/Environment (~> 6.4)
215 | - GoogleUtilities/Logger (~> 6.4)
216 | - FirebaseCoreDiagnostics (1.1.2):
217 | - FirebaseCoreDiagnosticsInterop (~> 1.0)
218 | - GoogleDataTransportCCTSupport (~> 1.0)
219 | - GoogleUtilities/Environment (~> 6.2)
220 | - GoogleUtilities/Logger (~> 6.2)
221 | - nanopb (~> 0.3.901)
222 | - FirebaseCoreDiagnosticsInterop (1.1.0)
223 | - FirebaseFirestore (1.8.3):
224 | - abseil/algorithm (= 0.20190808)
225 | - abseil/base (= 0.20190808)
226 | - abseil/memory (= 0.20190808)
227 | - abseil/meta (= 0.20190808)
228 | - abseil/strings/strings (= 0.20190808)
229 | - abseil/time (= 0.20190808)
230 | - abseil/types (= 0.20190808)
231 | - FirebaseAuthInterop (~> 1.0)
232 | - FirebaseCore (~> 6.2)
233 | - "gRPC-C++ (= 0.0.9)"
234 | - leveldb-library (~> 1.22)
235 | - nanopb (~> 0.3.901)
236 | - FirebaseInstanceID (4.2.8):
237 | - FirebaseCore (~> 6.5)
238 | - GoogleUtilities/Environment (~> 6.4)
239 | - GoogleUtilities/UserDefaults (~> 6.4)
240 | - Flutter (1.0.0)
241 | - GoogleAppMeasurement (6.1.7):
242 | - GoogleUtilities/AppDelegateSwizzler (~> 6.0)
243 | - GoogleUtilities/MethodSwizzler (~> 6.0)
244 | - GoogleUtilities/Network (~> 6.0)
245 | - "GoogleUtilities/NSData+zlib (~> 6.0)"
246 | - nanopb (= 0.3.9011)
247 | - GoogleDataTransport (3.2.0)
248 | - GoogleDataTransportCCTSupport (1.2.3):
249 | - GoogleDataTransport (~> 3.2)
250 | - nanopb (~> 0.3.901)
251 | - GoogleUtilities/AppDelegateSwizzler (6.4.0):
252 | - GoogleUtilities/Environment
253 | - GoogleUtilities/Logger
254 | - GoogleUtilities/Network
255 | - GoogleUtilities/Environment (6.4.0)
256 | - GoogleUtilities/Logger (6.4.0):
257 | - GoogleUtilities/Environment
258 | - GoogleUtilities/MethodSwizzler (6.4.0):
259 | - GoogleUtilities/Logger
260 | - GoogleUtilities/Network (6.4.0):
261 | - GoogleUtilities/Logger
262 | - "GoogleUtilities/NSData+zlib"
263 | - GoogleUtilities/Reachability
264 | - "GoogleUtilities/NSData+zlib (6.4.0)"
265 | - GoogleUtilities/Reachability (6.4.0):
266 | - GoogleUtilities/Logger
267 | - GoogleUtilities/UserDefaults (6.4.0):
268 | - GoogleUtilities/Logger
269 | - "gRPC-C++ (0.0.9)":
270 | - "gRPC-C++/Implementation (= 0.0.9)"
271 | - "gRPC-C++/Interface (= 0.0.9)"
272 | - "gRPC-C++/Implementation (0.0.9)":
273 | - "gRPC-C++/Interface (= 0.0.9)"
274 | - gRPC-Core (= 1.21.0)
275 | - nanopb (~> 0.3)
276 | - "gRPC-C++/Interface (0.0.9)"
277 | - gRPC-Core (1.21.0):
278 | - gRPC-Core/Implementation (= 1.21.0)
279 | - gRPC-Core/Interface (= 1.21.0)
280 | - gRPC-Core/Implementation (1.21.0):
281 | - BoringSSL-GRPC (= 0.0.3)
282 | - gRPC-Core/Interface (= 1.21.0)
283 | - nanopb (~> 0.3)
284 | - gRPC-Core/Interface (1.21.0)
285 | - GTMSessionFetcher/Core (1.3.0)
286 | - leveldb-library (1.22)
287 | - nanopb (0.3.9011):
288 | - nanopb/decode (= 0.3.9011)
289 | - nanopb/encode (= 0.3.9011)
290 | - nanopb/decode (0.3.9011)
291 | - nanopb/encode (0.3.9011)
292 |
293 | DEPENDENCIES:
294 | - cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`)
295 | - cloud_firestore_web (from `.symlinks/plugins/cloud_firestore_web/ios`)
296 | - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
297 | - firebase_auth_web (from `.symlinks/plugins/firebase_auth_web/ios`)
298 | - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
299 | - firebase_core_web (from `.symlinks/plugins/firebase_core_web/ios`)
300 | - Flutter (from `Flutter`)
301 |
302 | SPEC REPOS:
303 | trunk:
304 | - abseil
305 | - BoringSSL-GRPC
306 | - Firebase
307 | - FirebaseAnalytics
308 | - FirebaseAuth
309 | - FirebaseAuthInterop
310 | - FirebaseCore
311 | - FirebaseCoreDiagnostics
312 | - FirebaseCoreDiagnosticsInterop
313 | - FirebaseFirestore
314 | - FirebaseInstanceID
315 | - GoogleAppMeasurement
316 | - GoogleDataTransport
317 | - GoogleDataTransportCCTSupport
318 | - GoogleUtilities
319 | - "gRPC-C++"
320 | - gRPC-Core
321 | - GTMSessionFetcher
322 | - leveldb-library
323 | - nanopb
324 |
325 | EXTERNAL SOURCES:
326 | cloud_firestore:
327 | :path: ".symlinks/plugins/cloud_firestore/ios"
328 | cloud_firestore_web:
329 | :path: ".symlinks/plugins/cloud_firestore_web/ios"
330 | firebase_auth:
331 | :path: ".symlinks/plugins/firebase_auth/ios"
332 | firebase_auth_web:
333 | :path: ".symlinks/plugins/firebase_auth_web/ios"
334 | firebase_core:
335 | :path: ".symlinks/plugins/firebase_core/ios"
336 | firebase_core_web:
337 | :path: ".symlinks/plugins/firebase_core_web/ios"
338 | Flutter:
339 | :path: Flutter
340 |
341 | SPEC CHECKSUMS:
342 | abseil: 18063d773f5366ff8736a050fe035a28f635fd27
343 | BoringSSL-GRPC: db8764df3204ccea016e1c8dd15d9a9ad63ff318
344 | cloud_firestore: b5f108f6c57f1ad913b9388b1dc60f925ada9066
345 | cloud_firestore_web: 9ec3dc7f5f98de5129339802d491c1204462bfec
346 | Firebase: 0219bb4782eb1406f1b9b0628a2e625484ce910d
347 | firebase_auth: 6838289663da45c488af0a82c246928588fcddc5
348 | firebase_auth_web: 0955c07bcc06e84af76b9d4e32e6f31518f2d7de
349 | firebase_core: 87e4c7cef68de46c0326ce2ee907fc7e365ead7e
350 | firebase_core_web: d501d8b946b60c8af265428ce483b0fff5ad52d1
351 | FirebaseAnalytics: f68b9f3f1241385129ae0a83b63627fc420c05e5
352 | FirebaseAuth: 831577b184ecaba38bc886768c1c22a450cc44e3
353 | FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc
354 | FirebaseCore: 632e05cc5e1199d9147122c16d92305eb04c34bd
355 | FirebaseCoreDiagnostics: 511f4f3ed7d440bb69127e8b97c2bc8befae639e
356 | FirebaseCoreDiagnosticsInterop: e9b1b023157e3a2fc6418b5cb601e79b9af7b3a0
357 | FirebaseFirestore: 52120e2833f804a874ba1a9f59aab864a8ae2286
358 | FirebaseInstanceID: ce993a3c3670a8f5d47ce371ac5d143c560608c5
359 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
360 | GoogleAppMeasurement: db118eb61a97dd8c4f7014e368d3c335cbbcf80a
361 | GoogleDataTransport: 8e9b210c97d55fbff306cc5468ff91b9cb32dcf5
362 | GoogleDataTransportCCTSupport: 202d7cdf9c4a7d81a2bb7f7e7e1ba6faa421b1f2
363 | GoogleUtilities: 29bd0d8f850efbd28cff6d99e8b7da1f8d236bcf
364 | "gRPC-C++": 9dfe7b44821e7b3e44aacad2af29d2c21f7cde83
365 | gRPC-Core: c9aef9a261a1247e881b18059b84d597293c9947
366 | GTMSessionFetcher: 43b8b64263023d4f32caa0b40f4c8bfa3c5f36d8
367 | leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7
368 | nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd
369 |
370 | PODFILE CHECKSUM: 083258d7f5e80b42ea9bfee905fe93049bc04c64
371 |
372 | COCOAPODS: 1.8.4
373 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14 | 4E6AE99023C5523B0054CD0B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4E6AE98F23C5523B0054CD0B /* GoogleService-Info.plist */; };
15 | 5994BF50A55C9234F6CE2437 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC8DC4D9D63AA5628988D997 /* Pods_Runner.framework */; };
16 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
17 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
18 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXCopyFilesBuildPhase section */
25 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
26 | isa = PBXCopyFilesBuildPhase;
27 | buildActionMask = 2147483647;
28 | dstPath = "";
29 | dstSubfolderSpec = 10;
30 | files = (
31 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
32 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
33 | );
34 | name = "Embed Frameworks";
35 | runOnlyForDeploymentPostprocessing = 0;
36 | };
37 | /* End PBXCopyFilesBuildPhase section */
38 |
39 | /* Begin PBXFileReference section */
40 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
41 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
42 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
43 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
44 | 4E6AE98F23C5523B0054CD0B /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
45 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
46 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
48 | 82B4EE027F4730CA59A1D524 /* 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 = ""; };
49 | 929D4C38AF7A5D083948F514 /* 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 = ""; };
50 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
51 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
52 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | D3730576206202E2BBF69A90 /* 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 = ""; };
59 | FC8DC4D9D63AA5628988D997 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
60 | /* End PBXFileReference section */
61 |
62 | /* Begin PBXFrameworksBuildPhase section */
63 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
64 | isa = PBXFrameworksBuildPhase;
65 | buildActionMask = 2147483647;
66 | files = (
67 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
68 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
69 | 5994BF50A55C9234F6CE2437 /* Pods_Runner.framework in Frameworks */,
70 | );
71 | runOnlyForDeploymentPostprocessing = 0;
72 | };
73 | /* End PBXFrameworksBuildPhase section */
74 |
75 | /* Begin PBXGroup section */
76 | 2AD26530CE3D81EC486539A5 /* Pods */ = {
77 | isa = PBXGroup;
78 | children = (
79 | 929D4C38AF7A5D083948F514 /* Pods-Runner.debug.xcconfig */,
80 | 82B4EE027F4730CA59A1D524 /* Pods-Runner.release.xcconfig */,
81 | D3730576206202E2BBF69A90 /* Pods-Runner.profile.xcconfig */,
82 | );
83 | path = Pods;
84 | sourceTree = "";
85 | };
86 | 4E2F694171925FA0034EFEC6 /* Frameworks */ = {
87 | isa = PBXGroup;
88 | children = (
89 | FC8DC4D9D63AA5628988D997 /* Pods_Runner.framework */,
90 | );
91 | name = Frameworks;
92 | sourceTree = "";
93 | };
94 | 9740EEB11CF90186004384FC /* Flutter */ = {
95 | isa = PBXGroup;
96 | children = (
97 | 3B80C3931E831B6300D905FE /* App.framework */,
98 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
99 | 9740EEBA1CF902C7004384FC /* Flutter.framework */,
100 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
101 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
102 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
103 | );
104 | name = Flutter;
105 | sourceTree = "";
106 | };
107 | 97C146E51CF9000F007C117D = {
108 | isa = PBXGroup;
109 | children = (
110 | 9740EEB11CF90186004384FC /* Flutter */,
111 | 97C146F01CF9000F007C117D /* Runner */,
112 | 97C146EF1CF9000F007C117D /* Products */,
113 | 2AD26530CE3D81EC486539A5 /* Pods */,
114 | 4E2F694171925FA0034EFEC6 /* Frameworks */,
115 | );
116 | sourceTree = "";
117 | };
118 | 97C146EF1CF9000F007C117D /* Products */ = {
119 | isa = PBXGroup;
120 | children = (
121 | 97C146EE1CF9000F007C117D /* Runner.app */,
122 | );
123 | name = Products;
124 | sourceTree = "";
125 | };
126 | 97C146F01CF9000F007C117D /* Runner */ = {
127 | isa = PBXGroup;
128 | children = (
129 | 4E6AE98F23C5523B0054CD0B /* GoogleService-Info.plist */,
130 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
131 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
132 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
133 | 97C147021CF9000F007C117D /* Info.plist */,
134 | 97C146F11CF9000F007C117D /* Supporting Files */,
135 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
136 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
137 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
138 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
139 | );
140 | path = Runner;
141 | sourceTree = "";
142 | };
143 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
144 | isa = PBXGroup;
145 | children = (
146 | );
147 | name = "Supporting Files";
148 | sourceTree = "";
149 | };
150 | /* End PBXGroup section */
151 |
152 | /* Begin PBXNativeTarget section */
153 | 97C146ED1CF9000F007C117D /* Runner */ = {
154 | isa = PBXNativeTarget;
155 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
156 | buildPhases = (
157 | 8D34655A799084B65C947429 /* [CP] Check Pods Manifest.lock */,
158 | 9740EEB61CF901F6004384FC /* Run Script */,
159 | 97C146EA1CF9000F007C117D /* Sources */,
160 | 97C146EB1CF9000F007C117D /* Frameworks */,
161 | 97C146EC1CF9000F007C117D /* Resources */,
162 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
163 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
164 | 2102BF0CA61E3896152D724B /* [CP] Embed Pods Frameworks */,
165 | );
166 | buildRules = (
167 | );
168 | dependencies = (
169 | );
170 | name = Runner;
171 | productName = Runner;
172 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
173 | productType = "com.apple.product-type.application";
174 | };
175 | /* End PBXNativeTarget section */
176 |
177 | /* Begin PBXProject section */
178 | 97C146E61CF9000F007C117D /* Project object */ = {
179 | isa = PBXProject;
180 | attributes = {
181 | LastUpgradeCheck = 1020;
182 | ORGANIZATIONNAME = "";
183 | TargetAttributes = {
184 | 97C146ED1CF9000F007C117D = {
185 | CreatedOnToolsVersion = 7.3.1;
186 | DevelopmentTeam = WQ96K2ZV89;
187 | LastSwiftMigration = 1100;
188 | };
189 | };
190 | };
191 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
192 | compatibilityVersion = "Xcode 3.2";
193 | developmentRegion = en;
194 | hasScannedForEncodings = 0;
195 | knownRegions = (
196 | en,
197 | Base,
198 | );
199 | mainGroup = 97C146E51CF9000F007C117D;
200 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
201 | projectDirPath = "";
202 | projectRoot = "";
203 | targets = (
204 | 97C146ED1CF9000F007C117D /* Runner */,
205 | );
206 | };
207 | /* End PBXProject section */
208 |
209 | /* Begin PBXResourcesBuildPhase section */
210 | 97C146EC1CF9000F007C117D /* Resources */ = {
211 | isa = PBXResourcesBuildPhase;
212 | buildActionMask = 2147483647;
213 | files = (
214 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
215 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
216 | 4E6AE99023C5523B0054CD0B /* GoogleService-Info.plist in Resources */,
217 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
218 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | /* End PBXResourcesBuildPhase section */
223 |
224 | /* Begin PBXShellScriptBuildPhase section */
225 | 2102BF0CA61E3896152D724B /* [CP] Embed Pods Frameworks */ = {
226 | isa = PBXShellScriptBuildPhase;
227 | buildActionMask = 2147483647;
228 | files = (
229 | );
230 | inputPaths = (
231 | );
232 | name = "[CP] Embed Pods Frameworks";
233 | outputPaths = (
234 | );
235 | runOnlyForDeploymentPostprocessing = 0;
236 | shellPath = /bin/sh;
237 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
238 | showEnvVarsInLog = 0;
239 | };
240 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
241 | isa = PBXShellScriptBuildPhase;
242 | buildActionMask = 2147483647;
243 | files = (
244 | );
245 | inputPaths = (
246 | );
247 | name = "Thin Binary";
248 | outputPaths = (
249 | );
250 | runOnlyForDeploymentPostprocessing = 0;
251 | shellPath = /bin/sh;
252 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
253 | };
254 | 8D34655A799084B65C947429 /* [CP] Check Pods Manifest.lock */ = {
255 | isa = PBXShellScriptBuildPhase;
256 | buildActionMask = 2147483647;
257 | files = (
258 | );
259 | inputFileListPaths = (
260 | );
261 | inputPaths = (
262 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
263 | "${PODS_ROOT}/Manifest.lock",
264 | );
265 | name = "[CP] Check Pods Manifest.lock";
266 | outputFileListPaths = (
267 | );
268 | outputPaths = (
269 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
270 | );
271 | runOnlyForDeploymentPostprocessing = 0;
272 | shellPath = /bin/sh;
273 | 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";
274 | showEnvVarsInLog = 0;
275 | };
276 | 9740EEB61CF901F6004384FC /* Run Script */ = {
277 | isa = PBXShellScriptBuildPhase;
278 | buildActionMask = 2147483647;
279 | files = (
280 | );
281 | inputPaths = (
282 | );
283 | name = "Run Script";
284 | outputPaths = (
285 | );
286 | runOnlyForDeploymentPostprocessing = 0;
287 | shellPath = /bin/sh;
288 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
289 | };
290 | /* End PBXShellScriptBuildPhase section */
291 |
292 | /* Begin PBXSourcesBuildPhase section */
293 | 97C146EA1CF9000F007C117D /* Sources */ = {
294 | isa = PBXSourcesBuildPhase;
295 | buildActionMask = 2147483647;
296 | files = (
297 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
298 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
299 | );
300 | runOnlyForDeploymentPostprocessing = 0;
301 | };
302 | /* End PBXSourcesBuildPhase section */
303 |
304 | /* Begin PBXVariantGroup section */
305 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
306 | isa = PBXVariantGroup;
307 | children = (
308 | 97C146FB1CF9000F007C117D /* Base */,
309 | );
310 | name = Main.storyboard;
311 | sourceTree = "";
312 | };
313 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
314 | isa = PBXVariantGroup;
315 | children = (
316 | 97C147001CF9000F007C117D /* Base */,
317 | );
318 | name = LaunchScreen.storyboard;
319 | sourceTree = "";
320 | };
321 | /* End PBXVariantGroup section */
322 |
323 | /* Begin XCBuildConfiguration section */
324 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
325 | isa = XCBuildConfiguration;
326 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
327 | buildSettings = {
328 | ALWAYS_SEARCH_USER_PATHS = NO;
329 | CLANG_ANALYZER_NONNULL = YES;
330 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
331 | CLANG_CXX_LIBRARY = "libc++";
332 | CLANG_ENABLE_MODULES = YES;
333 | CLANG_ENABLE_OBJC_ARC = YES;
334 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
335 | CLANG_WARN_BOOL_CONVERSION = YES;
336 | CLANG_WARN_COMMA = YES;
337 | CLANG_WARN_CONSTANT_CONVERSION = YES;
338 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
340 | CLANG_WARN_EMPTY_BODY = YES;
341 | CLANG_WARN_ENUM_CONVERSION = YES;
342 | CLANG_WARN_INFINITE_RECURSION = YES;
343 | CLANG_WARN_INT_CONVERSION = YES;
344 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
345 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
346 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
347 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
348 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
349 | CLANG_WARN_STRICT_PROTOTYPES = YES;
350 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
351 | CLANG_WARN_UNREACHABLE_CODE = YES;
352 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
353 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
354 | COPY_PHASE_STRIP = NO;
355 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
356 | ENABLE_NS_ASSERTIONS = NO;
357 | ENABLE_STRICT_OBJC_MSGSEND = YES;
358 | GCC_C_LANGUAGE_STANDARD = gnu99;
359 | GCC_NO_COMMON_BLOCKS = YES;
360 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
361 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
362 | GCC_WARN_UNDECLARED_SELECTOR = YES;
363 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
364 | GCC_WARN_UNUSED_FUNCTION = YES;
365 | GCC_WARN_UNUSED_VARIABLE = YES;
366 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
367 | MTL_ENABLE_DEBUG_INFO = NO;
368 | SDKROOT = iphoneos;
369 | SUPPORTED_PLATFORMS = iphoneos;
370 | TARGETED_DEVICE_FAMILY = "1,2";
371 | VALIDATE_PRODUCT = YES;
372 | };
373 | name = Profile;
374 | };
375 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
376 | isa = XCBuildConfiguration;
377 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
378 | buildSettings = {
379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
380 | CLANG_ENABLE_MODULES = YES;
381 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
382 | DEVELOPMENT_TEAM = WQ96K2ZV89;
383 | ENABLE_BITCODE = NO;
384 | FRAMEWORK_SEARCH_PATHS = (
385 | "$(inherited)",
386 | "$(PROJECT_DIR)/Flutter",
387 | );
388 | INFOPLIST_FILE = Runner/Info.plist;
389 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
390 | LIBRARY_SEARCH_PATHS = (
391 | "$(inherited)",
392 | "$(PROJECT_DIR)/Flutter",
393 | );
394 | PRODUCT_BUNDLE_IDENTIFIER = com.example.friendlyeats;
395 | PRODUCT_NAME = Runner;
396 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
397 | SWIFT_VERSION = 5.0;
398 | VERSIONING_SYSTEM = "apple-generic";
399 | };
400 | name = Profile;
401 | };
402 | 97C147031CF9000F007C117D /* Debug */ = {
403 | isa = XCBuildConfiguration;
404 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
405 | buildSettings = {
406 | ALWAYS_SEARCH_USER_PATHS = NO;
407 | CLANG_ANALYZER_NONNULL = YES;
408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
409 | CLANG_CXX_LIBRARY = "libc++";
410 | CLANG_ENABLE_MODULES = YES;
411 | CLANG_ENABLE_OBJC_ARC = YES;
412 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
413 | CLANG_WARN_BOOL_CONVERSION = YES;
414 | CLANG_WARN_COMMA = YES;
415 | CLANG_WARN_CONSTANT_CONVERSION = YES;
416 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
417 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
418 | CLANG_WARN_EMPTY_BODY = YES;
419 | CLANG_WARN_ENUM_CONVERSION = YES;
420 | CLANG_WARN_INFINITE_RECURSION = YES;
421 | CLANG_WARN_INT_CONVERSION = YES;
422 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
423 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
424 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
425 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
426 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
427 | CLANG_WARN_STRICT_PROTOTYPES = YES;
428 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
429 | CLANG_WARN_UNREACHABLE_CODE = YES;
430 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
431 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
432 | COPY_PHASE_STRIP = NO;
433 | DEBUG_INFORMATION_FORMAT = dwarf;
434 | ENABLE_STRICT_OBJC_MSGSEND = YES;
435 | ENABLE_TESTABILITY = YES;
436 | GCC_C_LANGUAGE_STANDARD = gnu99;
437 | GCC_DYNAMIC_NO_PIC = NO;
438 | GCC_NO_COMMON_BLOCKS = YES;
439 | GCC_OPTIMIZATION_LEVEL = 0;
440 | GCC_PREPROCESSOR_DEFINITIONS = (
441 | "DEBUG=1",
442 | "$(inherited)",
443 | );
444 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
445 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
446 | GCC_WARN_UNDECLARED_SELECTOR = YES;
447 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
448 | GCC_WARN_UNUSED_FUNCTION = YES;
449 | GCC_WARN_UNUSED_VARIABLE = YES;
450 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
451 | MTL_ENABLE_DEBUG_INFO = YES;
452 | ONLY_ACTIVE_ARCH = YES;
453 | SDKROOT = iphoneos;
454 | TARGETED_DEVICE_FAMILY = "1,2";
455 | };
456 | name = Debug;
457 | };
458 | 97C147041CF9000F007C117D /* Release */ = {
459 | isa = XCBuildConfiguration;
460 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
461 | buildSettings = {
462 | ALWAYS_SEARCH_USER_PATHS = NO;
463 | CLANG_ANALYZER_NONNULL = YES;
464 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
465 | CLANG_CXX_LIBRARY = "libc++";
466 | CLANG_ENABLE_MODULES = YES;
467 | CLANG_ENABLE_OBJC_ARC = YES;
468 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
469 | CLANG_WARN_BOOL_CONVERSION = YES;
470 | CLANG_WARN_COMMA = YES;
471 | CLANG_WARN_CONSTANT_CONVERSION = YES;
472 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
473 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
474 | CLANG_WARN_EMPTY_BODY = YES;
475 | CLANG_WARN_ENUM_CONVERSION = YES;
476 | CLANG_WARN_INFINITE_RECURSION = YES;
477 | CLANG_WARN_INT_CONVERSION = YES;
478 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
479 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
480 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
481 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
482 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
483 | CLANG_WARN_STRICT_PROTOTYPES = YES;
484 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
485 | CLANG_WARN_UNREACHABLE_CODE = YES;
486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
487 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
488 | COPY_PHASE_STRIP = NO;
489 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
490 | ENABLE_NS_ASSERTIONS = NO;
491 | ENABLE_STRICT_OBJC_MSGSEND = YES;
492 | GCC_C_LANGUAGE_STANDARD = gnu99;
493 | GCC_NO_COMMON_BLOCKS = YES;
494 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
495 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
496 | GCC_WARN_UNDECLARED_SELECTOR = YES;
497 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
498 | GCC_WARN_UNUSED_FUNCTION = YES;
499 | GCC_WARN_UNUSED_VARIABLE = YES;
500 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
501 | MTL_ENABLE_DEBUG_INFO = NO;
502 | SDKROOT = iphoneos;
503 | SUPPORTED_PLATFORMS = iphoneos;
504 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
505 | TARGETED_DEVICE_FAMILY = "1,2";
506 | VALIDATE_PRODUCT = YES;
507 | };
508 | name = Release;
509 | };
510 | 97C147061CF9000F007C117D /* Debug */ = {
511 | isa = XCBuildConfiguration;
512 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
513 | buildSettings = {
514 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
515 | CLANG_ENABLE_MODULES = YES;
516 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
517 | DEVELOPMENT_TEAM = WQ96K2ZV89;
518 | ENABLE_BITCODE = NO;
519 | FRAMEWORK_SEARCH_PATHS = (
520 | "$(inherited)",
521 | "$(PROJECT_DIR)/Flutter",
522 | );
523 | INFOPLIST_FILE = Runner/Info.plist;
524 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
525 | LIBRARY_SEARCH_PATHS = (
526 | "$(inherited)",
527 | "$(PROJECT_DIR)/Flutter",
528 | );
529 | PRODUCT_BUNDLE_IDENTIFIER = com.example.friendlyeats;
530 | PRODUCT_NAME = Runner;
531 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
532 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
533 | SWIFT_VERSION = 5.0;
534 | VERSIONING_SYSTEM = "apple-generic";
535 | };
536 | name = Debug;
537 | };
538 | 97C147071CF9000F007C117D /* Release */ = {
539 | isa = XCBuildConfiguration;
540 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
541 | buildSettings = {
542 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
543 | CLANG_ENABLE_MODULES = YES;
544 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
545 | DEVELOPMENT_TEAM = WQ96K2ZV89;
546 | ENABLE_BITCODE = NO;
547 | FRAMEWORK_SEARCH_PATHS = (
548 | "$(inherited)",
549 | "$(PROJECT_DIR)/Flutter",
550 | );
551 | INFOPLIST_FILE = Runner/Info.plist;
552 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
553 | LIBRARY_SEARCH_PATHS = (
554 | "$(inherited)",
555 | "$(PROJECT_DIR)/Flutter",
556 | );
557 | PRODUCT_BUNDLE_IDENTIFIER = com.example.friendlyeats;
558 | PRODUCT_NAME = Runner;
559 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
560 | SWIFT_VERSION = 5.0;
561 | VERSIONING_SYSTEM = "apple-generic";
562 | };
563 | name = Release;
564 | };
565 | /* End XCBuildConfiguration section */
566 |
567 | /* Begin XCConfigurationList section */
568 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
569 | isa = XCConfigurationList;
570 | buildConfigurations = (
571 | 97C147031CF9000F007C117D /* Debug */,
572 | 97C147041CF9000F007C117D /* Release */,
573 | 249021D3217E4FDB00AE95B9 /* Profile */,
574 | );
575 | defaultConfigurationIsVisible = 0;
576 | defaultConfigurationName = Release;
577 | };
578 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
579 | isa = XCConfigurationList;
580 | buildConfigurations = (
581 | 97C147061CF9000F007C117D /* Debug */,
582 | 97C147071CF9000F007C117D /* Release */,
583 | 249021D4217E4FDB00AE95B9 /* Profile */,
584 | );
585 | defaultConfigurationIsVisible = 0;
586 | defaultConfigurationName = Release;
587 | };
588 | /* End XCConfigurationList section */
589 | };
590 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
591 | }
592 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import UIKit
16 | import Flutter
17 |
18 | @UIApplicationMain
19 | @objc class AppDelegate: FlutterAppDelegate {
20 | override func application(
21 | _ application: UIApplication,
22 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
23 | ) -> Bool {
24 | GeneratedPluginRegistrant.register(with: self)
25 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google LLC
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #import "GeneratedPluginRegistrant.h"
18 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:firebase_core/firebase_core.dart';
16 | import 'package:flutter/material.dart';
17 |
18 | import 'src/app.dart' deferred as app;
19 |
20 | void main() async {
21 | // Initialize Firebase
22 | WidgetsFlutterBinding.ensureInitialized();
23 | await Firebase.initializeApp();
24 |
25 | final Future loadedLibrary = await app.loadLibrary();
26 | runApp(
27 | FutureBuilder(
28 | future: loadedLibrary,
29 | builder: (snapshot, context) => app.FriendlyEatsApp(),
30 | ),
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/lib/src/app.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 |
17 | import 'home_page.dart';
18 | import 'restaurant_page.dart';
19 |
20 | class FriendlyEatsApp extends StatelessWidget {
21 | @override
22 | Widget build(BuildContext context) {
23 | return MaterialApp(
24 | title: 'FriendlyEats',
25 | onGenerateRoute: (settings) {
26 | switch (settings.name) {
27 | case RestaurantPage.route:
28 | final RestaurantPageArguments arguments = settings.arguments;
29 | return MaterialPageRoute(
30 | builder: (context) => RestaurantPage(
31 | restaurantId: arguments.id,
32 | ));
33 | break;
34 | default:
35 | // return MaterialPageRoute(
36 | // builder: (context) => RestaurantPage(
37 | // restaurantId: 'lV81npEeboEActMpUJjn',
38 | // ));
39 | // Everything defaults to home, but maybe we want a custom 404 here
40 | return MaterialPageRoute(builder: (context) => HomePage());
41 | }
42 | },
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/src/home_page.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 | import 'dart:math';
17 |
18 | import 'package:cloud_firestore/cloud_firestore.dart';
19 | import 'package:firebase_auth/firebase_auth.dart';
20 | import 'package:flutter/material.dart';
21 |
22 | import 'restaurant_page.dart';
23 | import 'model/data.dart' as data;
24 | import 'model/filter.dart';
25 | import 'model/restaurant.dart';
26 | import 'widgets/empty_list.dart';
27 | import 'widgets/filter_bar.dart';
28 | import 'widgets/grid.dart';
29 | import 'widgets/dialogs/filter_select.dart';
30 |
31 | class HomePage extends StatefulWidget {
32 | static const route = '/';
33 |
34 | HomePage({Key key}) : super(key: key);
35 |
36 | @override
37 | _HomePageState createState() => _HomePageState();
38 | }
39 |
40 | class _HomePageState extends State {
41 | _HomePageState() {
42 | FirebaseAuth.instance
43 | .signInAnonymously()
44 | .then((UserCredential userCredential) {
45 | _currentSubscription =
46 | data.loadAllRestaurants().listen(_updateRestaurants);
47 | });
48 | }
49 |
50 | @override
51 | void dispose() {
52 | _currentSubscription?.cancel();
53 | super.dispose();
54 | }
55 |
56 | StreamSubscription _currentSubscription;
57 | bool _isLoading = true;
58 | List _restaurants = [];
59 | Filter _filter;
60 |
61 | void _updateRestaurants(QuerySnapshot snapshot) {
62 | setState(() {
63 | _isLoading = false;
64 | _restaurants = data.getRestaurantsFromQuery(snapshot);
65 | });
66 | }
67 |
68 | Future _onAddRandomRestaurantsPressed() async {
69 | final numReviews = Random().nextInt(10) + 20;
70 |
71 | final restaurants = List.generate(numReviews, (_) => Restaurant.random());
72 | data.addRestaurantsBatch(restaurants);
73 | }
74 |
75 | Future _onFilterBarPressed() async {
76 | final filter = await showDialog(
77 | context: context,
78 | builder: (_) => FilterSelectDialog(filter: _filter),
79 | );
80 | if (filter != null) {
81 | await _currentSubscription?.cancel();
82 | setState(() {
83 | _isLoading = true;
84 | _filter = filter;
85 | if (filter.isDefault) {
86 | _currentSubscription =
87 | data.loadAllRestaurants().listen(_updateRestaurants);
88 | } else {
89 | _currentSubscription =
90 | data.loadFilteredRestaurants(filter).listen(_updateRestaurants);
91 | }
92 | });
93 | }
94 | }
95 |
96 | @override
97 | Widget build(BuildContext context) {
98 | return Scaffold(
99 | appBar: AppBar(
100 | leading: Icon(Icons.restaurant),
101 | title: Text('FriendlyEats'),
102 | bottom: PreferredSize(
103 | preferredSize: Size(320, 48),
104 | child: Padding(
105 | padding: EdgeInsets.fromLTRB(6, 0, 6, 4),
106 | child: FilterBar(
107 | filter: _filter,
108 | onPressed: _onFilterBarPressed,
109 | ),
110 | ),
111 | ),
112 | ),
113 | body: Center(
114 | child: Container(
115 | constraints: BoxConstraints(maxWidth: 1280),
116 | child: _isLoading
117 | ? CircularProgressIndicator()
118 | : _restaurants.isNotEmpty
119 | ? RestaurantGrid(
120 | restaurants: _restaurants,
121 | onRestaurantPressed: (id) {
122 | // TODO: Add deep links on web
123 | Navigator.pushNamed(context, RestaurantPage.route,
124 | arguments: RestaurantPageArguments(id: id));
125 | })
126 | : EmptyListView(
127 | child: Text('FriendlyEats has no restaurants yet!'),
128 | onPressed: _onAddRandomRestaurantsPressed,
129 | ),
130 | ),
131 | ),
132 | );
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/lib/src/model/data.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:cloud_firestore/cloud_firestore.dart';
16 |
17 | import './filter.dart';
18 | import './restaurant.dart';
19 | import './review.dart';
20 |
21 | // This is the file that Codelab users will primarily work on.
22 |
23 | Future addRestaurant(Restaurant restaurant) {
24 | // TODO: Complete the "Add restaurants to Firestore" step.
25 | return Future.value();
26 | }
27 |
28 | Stream loadAllRestaurants() {
29 | // TODO: Complete the "Display data from Cloud Firestore" step.
30 | return Stream.value(null);
31 | }
32 |
33 | List getRestaurantsFromQuery(QuerySnapshot snapshot) {
34 | // TODO: Complete the "Display data from Cloud Firestore" step.
35 | return [];
36 | }
37 |
38 | Future getRestaurant(String restaurantId) {
39 | // TODO: Complete the "Get data" step.
40 | return Future.value(null);
41 | }
42 |
43 | Future addReview({String restaurantId, Review review}) {
44 | // TODO: Complete the "Write data in a transaction" step.
45 | return Future.value();
46 | }
47 |
48 | Stream loadFilteredRestaurants(Filter filter) {
49 | // TODO: Complete the "Sorting and filtering data" step.
50 | return Stream.value(null);
51 | }
52 |
53 | void addRestaurantsBatch(List restaurants) {
54 | restaurants.forEach((Restaurant restaurant) {
55 | addRestaurant(restaurant);
56 | });
57 | }
58 |
--------------------------------------------------------------------------------
/lib/src/model/filter.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | typedef FilterChangedCallback = void Function(T newValue);
16 |
17 | class Filter {
18 | final String city;
19 | final int price;
20 | final String category;
21 | final String sort;
22 |
23 | bool get isDefault {
24 | return (city == null && price == null && category == null && sort == null);
25 | }
26 |
27 | Filter({this.city, this.price, this.category, this.sort});
28 | }
29 |
--------------------------------------------------------------------------------
/lib/src/model/restaurant.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:math';
16 |
17 | import 'package:cloud_firestore/cloud_firestore.dart';
18 |
19 | import './values.dart';
20 |
21 | typedef RestaurantPressedCallback = void Function(String restaurantId);
22 |
23 | typedef CloseRestaurantPressedCallback = void Function();
24 |
25 | class Restaurant {
26 | final String id;
27 | final String name;
28 | final String category;
29 | final String city;
30 | final double avgRating;
31 | final int numRatings;
32 | final int price;
33 | final String photo;
34 | final DocumentReference reference;
35 |
36 | Restaurant._({this.name, this.category, this.city, this.price, this.photo})
37 | : id = null,
38 | numRatings = 0,
39 | avgRating = 0,
40 | reference = null;
41 |
42 | Restaurant.fromSnapshot(DocumentSnapshot snapshot)
43 | : assert(snapshot != null),
44 | id = snapshot.id,
45 | name = snapshot.data()['name'],
46 | category = snapshot.data()['category'],
47 | city = snapshot.data()['city'],
48 | avgRating = snapshot.data()['avgRating'].toDouble(),
49 | numRatings = snapshot.data()['numRatings'],
50 | price = snapshot.data()['price'],
51 | photo = snapshot.data()['photo'],
52 | reference = snapshot.reference;
53 |
54 | factory Restaurant.random() {
55 | return Restaurant._(
56 | category: getRandomCategory(),
57 | city: getRandomCity(),
58 | name: getRandomName(),
59 | price: Random().nextInt(3) + 1,
60 | photo: getRandomPhoto(),
61 | );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/model/review.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:math';
16 |
17 | import 'package:cloud_firestore/cloud_firestore.dart';
18 |
19 | import './values.dart';
20 |
21 | // This is called "ratings" in the backend.
22 | class Review {
23 | final String id;
24 | final String userId;
25 | final double rating;
26 | final String text;
27 | final String userName;
28 | final Timestamp timestamp;
29 |
30 | final DocumentReference reference;
31 |
32 | Review.fromSnapshot(DocumentSnapshot snapshot)
33 | : assert(snapshot != null),
34 | id = snapshot.id,
35 | rating = snapshot.data()['rating'].toDouble(),
36 | text = snapshot.data()['text'],
37 | userName = snapshot.data()['userName'],
38 | userId = snapshot.data()['userId'],
39 | timestamp = snapshot.data()['timestamp'],
40 | reference = snapshot.reference;
41 |
42 | Review.fromUserInput({this.rating, this.text, this.userName, this.userId})
43 | : id = null,
44 | timestamp = null,
45 | reference = null;
46 |
47 | factory Review.random({String userName, String userId}) {
48 | final rating = Random().nextInt(4) + 1;
49 | final review = getRandomReviewText(rating);
50 | return Review.fromUserInput(
51 | rating: rating.toDouble(),
52 | text: review,
53 | userName: userName,
54 | userId: userId);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/src/model/values.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:math';
16 |
17 | final cities = [
18 | 'Albuquerque',
19 | 'Arlington',
20 | 'Atlanta',
21 | 'Austin',
22 | 'Baltimore',
23 | 'Boston',
24 | 'Charlotte',
25 | 'Chicago',
26 | 'Cleveland',
27 | 'Colorado Springs',
28 | 'Columbus',
29 | 'Dallas',
30 | 'Denver',
31 | 'Detroit',
32 | 'El Paso',
33 | 'Fort Worth',
34 | 'Fresno',
35 | 'Houston',
36 | 'Indianapolis',
37 | 'Jacksonville',
38 | 'Kansas City',
39 | 'Las Vegas',
40 | 'Long Island',
41 | 'Los Angeles',
42 | 'Louisville',
43 | 'Memphis',
44 | 'Mesa',
45 | 'Miami',
46 | 'Milwaukee',
47 | 'Nashville',
48 | 'New York',
49 | 'Oakland',
50 | 'Oklahoma',
51 | 'Omaha',
52 | 'Philadelphia',
53 | 'Phoenix',
54 | 'Portland',
55 | 'Raleigh',
56 | 'Sacramento',
57 | 'San Antonio',
58 | 'San Diego',
59 | 'San Francisco',
60 | 'San Jose',
61 | 'Seattle',
62 | 'Tucson',
63 | 'Tulsa',
64 | 'Virginia Beach',
65 | 'Washington',
66 | ];
67 |
68 | final categories = [
69 | 'Brunch',
70 | 'Burgers',
71 | 'Coffee',
72 | 'Deli',
73 | 'Dim Sum',
74 | 'Indian',
75 | 'Italian',
76 | 'Mediterranean',
77 | 'Mexican',
78 | 'Pizza',
79 | 'Ramen',
80 | 'Sushi',
81 | ];
82 |
83 | final _words = [
84 | 'Bar',
85 | 'Deli',
86 | 'Diner',
87 | 'Fire',
88 | 'Grill',
89 | 'Drive Thru',
90 | 'Place',
91 | 'Best',
92 | 'Spot',
93 | 'Trattoria',
94 | 'Steakhouse',
95 | 'Churrasco',
96 | 'Tavern',
97 | 'Cafe',
98 | 'Pop-up',
99 | 'Yummy',
100 | 'Belly',
101 | 'Snack',
102 | 'Fast',
103 | 'Turbo',
104 | 'Hyper',
105 | 'Prime',
106 | 'Eatin\'',
107 | ];
108 |
109 | final _reviewTextPerRating = {
110 | 1: [
111 | 'Would never eat here again!',
112 | 'Such an awful place!',
113 | 'Not sure if they had a bad day off, but the food was very bad.'
114 | ],
115 | 2: [
116 | 'Not my cup of tea.',
117 | 'Unlikely that we will ever come again.',
118 | 'Quite bad, but I\'ve had worse!'
119 | ],
120 | 3: [
121 | 'Exactly okay :/',
122 | 'Unimpressed, but not disappointed!',
123 | '3 estrellas y van que arden.'
124 | ],
125 | 4: [
126 | 'Actually pretty good, would recommend!',
127 | 'I really like this place, I come quite often!',
128 | 'A great experience, as usual!'
129 | ],
130 | 5: [
131 | 'This is my favorite place. Literally',
132 | 'This place is ALWAYS great!',
133 | 'I recommend this to all my friends and family!'
134 | ],
135 | };
136 |
137 | final random = Random();
138 |
139 | String getRandomReviewText(int rating) {
140 | final reviews = _reviewTextPerRating[rating];
141 | return reviews[random.nextInt(reviews.length)];
142 | }
143 |
144 | String getRandomName() {
145 | final firstWord = random.nextInt(_words.length);
146 | var nextWord;
147 | do {
148 | nextWord = random.nextInt(_words.length);
149 | } while (firstWord == nextWord);
150 | return '${_words[firstWord]} ${_words[nextWord]}';
151 | }
152 |
153 | String getRandomCategory() {
154 | return categories[random.nextInt(categories.length)];
155 | }
156 |
157 | String getRandomCity() {
158 | return cities[random.nextInt(cities.length)];
159 | }
160 |
161 | String getRandomPhoto() {
162 | final photoId = random.nextInt(21) + 1;
163 | return 'https://storage.googleapis.com/firestorequickstarts.appspot.com/food_$photoId.png';
164 | }
165 |
--------------------------------------------------------------------------------
/lib/src/restaurant_page.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 | import 'dart:math';
17 |
18 | import 'package:cloud_firestore/cloud_firestore.dart';
19 | import 'package:firebase_auth/firebase_auth.dart';
20 | import 'package:flutter/foundation.dart';
21 | import 'package:flutter/material.dart';
22 | import 'package:sliver_fab/sliver_fab.dart';
23 |
24 | import 'widgets/empty_list.dart';
25 | import 'model/data.dart' as data;
26 | import 'model/restaurant.dart';
27 | import 'model/review.dart';
28 | import 'widgets/app_bar.dart';
29 | import 'widgets/review.dart';
30 | import 'widgets/dialogs/review_create.dart';
31 |
32 | class RestaurantPage extends StatefulWidget {
33 | static const route = '/restaurant';
34 |
35 | final String _restaurantId;
36 |
37 | RestaurantPage({Key key, @required String restaurantId})
38 | : _restaurantId = restaurantId,
39 | super(key: key);
40 |
41 | @override
42 | _RestaurantPageState createState() =>
43 | _RestaurantPageState(restaurantId: _restaurantId);
44 | }
45 |
46 | class _RestaurantPageState extends State {
47 | _RestaurantPageState({@required String restaurantId}) {
48 | FirebaseAuth.instance
49 | .signInAnonymously()
50 | .then((UserCredential userCredential) {
51 | data.getRestaurant(restaurantId).then((Restaurant restaurant) {
52 | _currentReviewSubscription?.cancel();
53 | setState(() {
54 | if (userCredential.user.displayName == null ||
55 | userCredential.user.displayName.isEmpty) {
56 | _userName = 'Anonymous (${kIsWeb ? "Web" : "Mobile"})';
57 | } else {
58 | _userName = userCredential.user.displayName;
59 | }
60 | _restaurant = restaurant;
61 | _userId = userCredential.user.uid;
62 |
63 | // Initialize the reviews snapshot...
64 | _currentReviewSubscription = _restaurant.reference
65 | .collection('ratings')
66 | .orderBy('timestamp', descending: true)
67 | .snapshots()
68 | .listen((QuerySnapshot reviewSnap) {
69 | setState(() {
70 | _isLoading = false;
71 | _reviews = reviewSnap.docs.map((DocumentSnapshot doc) {
72 | return Review.fromSnapshot(doc);
73 | }).toList();
74 | });
75 | });
76 | });
77 | });
78 | });
79 | }
80 |
81 | @override
82 | void dispose() {
83 | _currentReviewSubscription?.cancel();
84 | super.dispose();
85 | }
86 |
87 | bool _isLoading = true;
88 | StreamSubscription _currentReviewSubscription;
89 |
90 | Restaurant _restaurant;
91 | String _userId;
92 | String _userName;
93 | List _reviews = [];
94 |
95 | void _onCreateReviewPressed(BuildContext context) async {
96 | final newReview = await showDialog(
97 | context: context,
98 | builder: (_) => ReviewCreateDialog(
99 | userId: _userId,
100 | userName: _userName,
101 | ),
102 | );
103 | if (newReview != null) {
104 | // Save the review
105 | return data.addReview(
106 | restaurantId: _restaurant.id,
107 | review: newReview,
108 | );
109 | }
110 | }
111 |
112 | void _onAddRandomReviewsPressed() async {
113 | // Await adding a random number of random reviews
114 | final numReviews = Random().nextInt(5) + 5;
115 | for (var i = 0; i < numReviews; i++) {
116 | await data.addReview(
117 | restaurantId: _restaurant.id,
118 | review: Review.random(
119 | userId: _userId,
120 | userName: _userName,
121 | ),
122 | );
123 | }
124 | }
125 |
126 | @override
127 | Widget build(BuildContext context) {
128 | return _isLoading
129 | ? Center(child: CircularProgressIndicator())
130 | : Scaffold(
131 | body: Builder(
132 | builder: (context) => SliverFab(
133 | floatingWidget: FloatingActionButton(
134 | tooltip: 'Add a review',
135 | backgroundColor: Colors.amber,
136 | child: Icon(Icons.add),
137 | onPressed: () => _onCreateReviewPressed(context),
138 | ),
139 | floatingPosition: FloatingPosition(right: 16),
140 | expandedHeight: RestaurantAppBar.appBarHeight,
141 | slivers: [
142 | RestaurantAppBar(
143 | restaurant: _restaurant,
144 | onClosePressed: () => Navigator.pop(context),
145 | ),
146 | _reviews.isNotEmpty
147 | ? SliverPadding(
148 | padding: EdgeInsets.fromLTRB(16, 24, 16, 8),
149 | sliver: SliverList(
150 | delegate: SliverChildListDelegate(_reviews
151 | .map((Review review) =>
152 | RestaurantReview(review: review))
153 | .toList()),
154 | ),
155 | )
156 | : SliverFillRemaining(
157 | hasScrollBody: false,
158 | child: EmptyListView(
159 | child: Text('${_restaurant.name} has no reviews.'),
160 | onPressed: _onAddRandomReviewsPressed,
161 | ),
162 | ),
163 | ],
164 | ),
165 | ),
166 | );
167 | }
168 | }
169 |
170 | class RestaurantPageArguments {
171 | final String id;
172 |
173 | RestaurantPageArguments({@required this.id});
174 | }
175 |
--------------------------------------------------------------------------------
/lib/src/widgets/app_bar.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 |
17 | import '../model/restaurant.dart';
18 | import 'stars.dart';
19 |
20 | class RestaurantAppBar extends StatelessWidget {
21 | static final double appBarHeight = 160;
22 |
23 | RestaurantAppBar({
24 | this.restaurant,
25 | CloseRestaurantPressedCallback onClosePressed,
26 | }) : _onPressed = onClosePressed;
27 |
28 | final Restaurant restaurant;
29 |
30 | final CloseRestaurantPressedCallback _onPressed;
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | return SliverAppBar(
35 | leading: IconButton(
36 | onPressed: _onPressed,
37 | icon: Icon(Icons.close),
38 | iconSize: 32,
39 | ),
40 | expandedHeight: appBarHeight,
41 | forceElevated: true,
42 | flexibleSpace: FlexibleSpaceBar(
43 | centerTitle: false,
44 | title: Wrap(
45 | children: [
46 | Text(
47 | restaurant.name,
48 | overflow: TextOverflow.ellipsis,
49 | ),
50 | Row(
51 | crossAxisAlignment: CrossAxisAlignment.center,
52 | children: [
53 | Container(
54 | width: 80,
55 | alignment: Alignment.bottomLeft,
56 | child: StarRating(
57 | rating: restaurant.avgRating,
58 | color: Colors.white,
59 | size: 16,
60 | ),
61 | ),
62 | Padding(
63 | padding: EdgeInsets.only(left: 6),
64 | child: Text(
65 | '\$' * restaurant.price,
66 | style: TextStyle(
67 | fontSize: Theme.of(context).textTheme.caption.fontSize),
68 | ),
69 | ),
70 | ],
71 | ),
72 | Padding(
73 | padding: EdgeInsets.only(top: 2),
74 | child: Text(
75 | '${restaurant.category} ● ${restaurant.city}',
76 | style: TextStyle(
77 | fontSize: Theme.of(context).textTheme.caption.fontSize),
78 | ),
79 | ),
80 | ],
81 | ),
82 | background: Stack(
83 | fit: StackFit.expand,
84 | children: [
85 | Image.network(
86 | restaurant.photo,
87 | fit: BoxFit.cover,
88 | ),
89 | Container(
90 | decoration: BoxDecoration(
91 | gradient: LinearGradient(
92 | begin: Alignment.topCenter,
93 | end: Alignment.bottomCenter,
94 | colors: [
95 | const Color(0x00000000),
96 | const Color(0xAA000000),
97 | ],
98 | ),
99 | ),
100 | ),
101 | ],
102 | ),
103 | ),
104 | );
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/lib/src/widgets/card.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/foundation.dart';
16 | import 'package:flutter/material.dart';
17 |
18 | import '../model/restaurant.dart';
19 | import 'stars.dart';
20 |
21 | class RestaurantCard extends StatelessWidget {
22 | RestaurantCard({
23 | this.restaurant,
24 | @required RestaurantPressedCallback onRestaurantPressed,
25 | }) : _onPressed = onRestaurantPressed;
26 |
27 | final Restaurant restaurant;
28 |
29 | final RestaurantPressedCallback _onPressed;
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return Card(
34 | child: InkWell(
35 | onTap: () => _onPressed(restaurant.id),
36 | splashColor: Colors.blue.withAlpha(30),
37 | child: Container(
38 | height: 250,
39 | child: Column(
40 | children: [
41 | // TODO: Make this a Hero widget so we can transition to it?
42 | Expanded(
43 | child: Container(
44 | alignment: Alignment.centerLeft,
45 | decoration: BoxDecoration(
46 | image: DecorationImage(
47 | image: NetworkImage(restaurant.photo),
48 | fit: BoxFit.cover,
49 | ),
50 | ),
51 | child: null),
52 | ),
53 | Padding(
54 | padding: EdgeInsets.all(8),
55 | child: Column(
56 | crossAxisAlignment: CrossAxisAlignment.start,
57 | mainAxisAlignment: MainAxisAlignment.end,
58 | children: [
59 | Row(
60 | crossAxisAlignment: CrossAxisAlignment.center,
61 | children: [
62 | Expanded(
63 | child: Text(
64 | restaurant.name,
65 | style: Theme.of(context).textTheme.headline6,
66 | ),
67 | ),
68 | Text(
69 | '\$' * restaurant.price,
70 | style: Theme.of(context).textTheme.caption,
71 | ),
72 | ],
73 | ),
74 | Container(
75 | padding: EdgeInsets.fromLTRB(0, (kIsWeb ? 0 : 2), 0, 4),
76 | alignment: Alignment.bottomLeft,
77 | child: StarRating(
78 | rating: restaurant.avgRating,
79 | ),
80 | ),
81 | Container(
82 | alignment: Alignment.bottomLeft,
83 | child: Text(
84 | '${restaurant.category} ● ${restaurant.city}',
85 | style: Theme.of(context).textTheme.caption,
86 | ),
87 | ),
88 | ],
89 | ),
90 | ),
91 | ],
92 | ),
93 | ),
94 | ));
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/lib/src/widgets/dialogs/filter_select.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:math' as math;
16 |
17 | import 'package:flutter/material.dart';
18 |
19 | import '../../model/values.dart' as hardcoded;
20 | import '../../model/filter.dart';
21 |
22 | class FilterSelectDialog extends StatefulWidget {
23 | FilterSelectDialog({Key key, Filter filter})
24 | : _filter = filter,
25 | super(key: key);
26 |
27 | final Filter _filter;
28 |
29 | @override
30 | _FilterSelectDialogState createState() =>
31 | _FilterSelectDialogState(filter: _filter);
32 | }
33 |
34 | class _FilterSelectDialogState extends State {
35 | _FilterSelectDialogState({Filter filter}) {
36 | if (filter != null && !filter.isDefault) {
37 | _category = filter.category;
38 | _city = filter.city;
39 | _price = filter.price;
40 | _sort = filter.sort;
41 | }
42 | }
43 |
44 | String _category;
45 | String _city;
46 | int _price;
47 | String _sort;
48 |
49 | Widget _buildDropdown(
50 | List labels,
51 | List values,
52 | dynamic selected,
53 | FilterChangedCallback onChanged,
54 | ) {
55 | final items = [
56 | for (var i = 0; i < values.length; i++)
57 | DropdownMenuItem(value: values[i], child: Text(labels[i])),
58 | ];
59 | return DropdownButton(
60 | items: items,
61 | isExpanded: true,
62 | value: selected,
63 | onChanged: onChanged,
64 | );
65 | }
66 |
67 | Widget _buildDropdownRow({
68 | List values,
69 | List labels,
70 | T selected,
71 | IconData icon,
72 | FilterChangedCallback onChanged,
73 | }) {
74 | return Row(
75 | mainAxisSize: MainAxisSize.max,
76 | children: [
77 | Icon(icon),
78 | Expanded(
79 | child: Padding(
80 | padding: EdgeInsets.fromLTRB(16, 0, 8, 0),
81 | child: _buildDropdown(labels, values, selected, onChanged),
82 | ),
83 | ),
84 | ],
85 | );
86 | }
87 |
88 | Widget _buildCategoryDropdown({
89 | String selected,
90 | FilterChangedCallback onChanged,
91 | }) {
92 | return _buildDropdownRow(
93 | labels: ['Any Cuisine', ...hardcoded.categories],
94 | values: [null, ...hardcoded.categories],
95 | selected: selected,
96 | icon: Icons.fastfood,
97 | onChanged: onChanged,
98 | );
99 | }
100 |
101 | Widget _buildCityDropdown({
102 | String selected,
103 | FilterChangedCallback onChanged,
104 | }) {
105 | return _buildDropdownRow(
106 | labels: ['Any Location', ...hardcoded.cities],
107 | values: [null, ...hardcoded.cities],
108 | selected: selected,
109 | icon: Icons.location_on,
110 | onChanged: onChanged,
111 | );
112 | }
113 |
114 | Widget _buildPriceDropdown({
115 | int selected,
116 | FilterChangedCallback onChanged,
117 | }) {
118 | return _buildDropdownRow(
119 | labels: ['Any Price', '\$', '\$\$', '\$\$\$', '\$\$\$\$'],
120 | values: [null, 1, 2, 3, 4],
121 | selected: selected,
122 | icon: Icons.monetization_on,
123 | onChanged: onChanged,
124 | );
125 | }
126 |
127 | Widget _buildSortDropdown({
128 | String selected,
129 | FilterChangedCallback onChanged,
130 | }) {
131 | return _buildDropdownRow(
132 | labels: ['Rating', 'Reviews'],
133 | values: ['avgRating', 'numRatings'],
134 | selected: selected,
135 | icon: Icons.sort,
136 | onChanged: onChanged,
137 | );
138 | }
139 |
140 | @override
141 | Widget build(BuildContext context) {
142 | return AlertDialog(
143 | title: Row(
144 | mainAxisAlignment: MainAxisAlignment.start,
145 | children: [
146 | Icon(Icons.filter_list),
147 | Padding(
148 | padding: EdgeInsets.fromLTRB(16, 0, 8, 0),
149 | child: Text('Filter'),
150 | ),
151 | ],
152 | ),
153 | content: Container(
154 | width: math.min(MediaQuery.of(context).size.width, 740),
155 | height: math.min(MediaQuery.of(context).size.height, 200),
156 | child: Column(
157 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
158 | children: [
159 | _buildCategoryDropdown(
160 | selected: _category,
161 | onChanged: (String value) {
162 | setState(() {
163 | _category = value;
164 | });
165 | }),
166 | _buildCityDropdown(
167 | selected: _city,
168 | onChanged: (String value) {
169 | setState(() {
170 | _city = value;
171 | });
172 | }),
173 | _buildPriceDropdown(
174 | selected: _price,
175 | onChanged: (int value) {
176 | setState(() {
177 | _price = value;
178 | });
179 | }),
180 | _buildSortDropdown(
181 | selected: _sort ?? 'avgRating',
182 | onChanged: (String value) {
183 | setState(() {
184 | _sort = value;
185 | });
186 | }),
187 | ],
188 | ),
189 | ),
190 | actions: [
191 | FlatButton(
192 | child: Text('CLEAR ALL'),
193 | onPressed: () => Navigator.pop(context, Filter()),
194 | ),
195 | RaisedButton(
196 | child: Text('ACCEPT'),
197 | onPressed: () => Navigator.pop(
198 | context,
199 | Filter(
200 | category: _category,
201 | city: _city,
202 | price: _price,
203 | sort: _sort,
204 | )),
205 | ),
206 | ],
207 | );
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/lib/src/widgets/dialogs/review_create.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:math' as math;
16 |
17 | import 'package:flutter/material.dart';
18 | import 'package:smooth_star_rating/smooth_star_rating.dart';
19 |
20 | import '../../model/review.dart';
21 |
22 | class ReviewCreateDialog extends StatefulWidget {
23 | final String userName;
24 | final String userId;
25 |
26 | ReviewCreateDialog({this.userName, this.userId, Key key});
27 |
28 | @override
29 | _ReviewCreateDialogState createState() => _ReviewCreateDialogState();
30 | }
31 |
32 | class _ReviewCreateDialogState extends State {
33 | double rating = 0;
34 | String review;
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | Color color = rating == 0 ? Colors.grey : Colors.amber;
39 | return AlertDialog(
40 | title: Text('Add a Review'),
41 | content: Container(
42 | width: math.min(MediaQuery.of(context).size.width, 740),
43 | height: math.min(MediaQuery.of(context).size.height, 180),
44 | child: Column(
45 | mainAxisAlignment: MainAxisAlignment.start,
46 | children: [
47 | Container(
48 | margin: EdgeInsets.fromLTRB(0, 0, 0, 16),
49 | child: SmoothStarRating(
50 | starCount: 5,
51 | rating: rating,
52 | color: color,
53 | borderColor: Colors.grey,
54 | size: 32,
55 | onRated: (value) {
56 | if (mounted) {
57 | rating = value;
58 | }
59 | },
60 | ),
61 | ),
62 | Expanded(
63 | child: TextField(
64 | decoration: InputDecoration.collapsed(
65 | hintText: 'Type your review here.'),
66 | keyboardType: TextInputType.multiline,
67 | maxLines: null,
68 | onChanged: (value) {
69 | if (mounted) {
70 | setState(() {
71 | review = value;
72 | });
73 | }
74 | },
75 | ),
76 | ),
77 | ],
78 | ),
79 | ),
80 | actions: [
81 | FlatButton(
82 | child: Text('CANCEL'),
83 | onPressed: () => Navigator.pop(context, null),
84 | ),
85 | RaisedButton(
86 | child: Text('SAVE'),
87 | onPressed: () => Navigator.pop(
88 | context,
89 | Review.fromUserInput(
90 | rating: rating,
91 | text: review,
92 | userId: widget.userId,
93 | userName: widget.userName,
94 | ),
95 | ),
96 | ),
97 | ],
98 | );
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/lib/src/widgets/empty_list.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 |
17 | typedef EmptyListActionButtonCallback = void Function();
18 |
19 | class EmptyListView extends StatelessWidget {
20 | EmptyListView({
21 | this.child,
22 | this.onPressed,
23 | });
24 |
25 | final Widget child;
26 | final EmptyListActionButtonCallback onPressed;
27 | @override
28 | Widget build(BuildContext context) {
29 | final screenWidth = MediaQuery.of(context).size.width;
30 | final screenHeight = MediaQuery.of(context).size.height;
31 | var imageSize = 600.0;
32 | if (screenWidth < 640 || screenHeight < 820) {
33 | imageSize = 300;
34 | }
35 | return Center(
36 | child: Column(
37 | mainAxisSize: MainAxisSize.min,
38 | children: [
39 | Container(
40 | width: imageSize,
41 | height: imageSize,
42 | child: Image.asset(
43 | 'assets/friendlyeater.png',
44 | ),
45 | ),
46 | child,
47 | RaisedButton(child: Text('ADD SOME'), onPressed: onPressed),
48 | ],
49 | ),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/src/widgets/filter_bar.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 |
17 | import '../model/filter.dart';
18 |
19 | const _boldStyle = TextStyle(fontWeight: FontWeight.bold);
20 |
21 | class FilterBar extends StatelessWidget {
22 | FilterBar({@required VoidCallback onPressed, Filter filter})
23 | : _onPressed = onPressed,
24 | _filter = filter;
25 |
26 | final VoidCallback _onPressed;
27 | final Filter _filter;
28 |
29 | List _buildCategorySpans(Filter filter) {
30 | final noneSelected =
31 | filter == null || filter.isDefault || filter.category == null;
32 | return [
33 | if (noneSelected) TextSpan(text: 'All Restaurants', style: _boldStyle),
34 | if (!noneSelected) ...[
35 | TextSpan(text: '${filter.category}', style: _boldStyle),
36 | TextSpan(text: ' places'),
37 | ],
38 | ];
39 | }
40 |
41 | List _buildPriceSpans(Filter filter) {
42 | return [
43 | if (filter.price != null) ...[
44 | TextSpan(text: ' of '),
45 | TextSpan(text: '\$' * filter.price, style: _boldStyle),
46 | ],
47 | ];
48 | }
49 |
50 | List _buildTitleSpans(Filter filter) {
51 | return [
52 | ..._buildCategorySpans(filter),
53 | if (filter != null && !filter.isDefault) ..._buildPriceSpans(filter),
54 | ];
55 | }
56 |
57 | List _buildCitySpans(Filter filter) {
58 | return [
59 | if (filter.city != null) ...[
60 | TextSpan(text: 'in '),
61 | TextSpan(text: '${filter.city} ', style: _boldStyle),
62 | ],
63 | ];
64 | }
65 |
66 | List _buildSubtitleSpans(Filter filter) {
67 | final orderedByRating =
68 | filter == null || filter.sort == null || filter.sort == 'avgRating';
69 | return [
70 | if (filter != null) ..._buildCitySpans(filter),
71 | if (orderedByRating) TextSpan(text: 'by rating'),
72 | if (!orderedByRating) TextSpan(text: 'by # reviews'),
73 | ];
74 | }
75 |
76 | @override
77 | Widget build(BuildContext context) {
78 | return FlatButton(
79 | color: Colors.white,
80 | padding: EdgeInsets.all(6),
81 | onPressed: _onPressed,
82 | child: Row(
83 | children: [
84 | Icon(Icons.filter_list),
85 | Expanded(
86 | child: Padding(
87 | padding: EdgeInsets.fromLTRB(6, 0, 6, 0),
88 | child: Column(
89 | crossAxisAlignment: CrossAxisAlignment.start,
90 | children: [
91 | RichText(
92 | overflow: TextOverflow.ellipsis,
93 | text: TextSpan(
94 | style: Theme.of(context).textTheme.bodyText2,
95 | children: _buildTitleSpans(_filter),
96 | ),
97 | ),
98 | RichText(
99 | overflow: TextOverflow.ellipsis,
100 | text: TextSpan(
101 | style: Theme.of(context).textTheme.caption,
102 | children: _buildSubtitleSpans(_filter),
103 | ),
104 | ),
105 | ],
106 | ),
107 | ),
108 | ),
109 | ],
110 | ),
111 | );
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/lib/src/widgets/grid.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:math' as math;
16 |
17 | import 'package:flutter/material.dart';
18 | import 'package:responsive_grid/responsive_grid.dart';
19 |
20 | import '../model/restaurant.dart';
21 | import 'card.dart';
22 |
23 | const double _minSpacingPx = 16;
24 | const double _cardWidth = 360;
25 |
26 | class RestaurantGrid extends StatelessWidget {
27 | RestaurantGrid({
28 | @required RestaurantPressedCallback onRestaurantPressed,
29 | @required List restaurants,
30 | }) : _onRestaurantPressed = onRestaurantPressed,
31 | _restaurants = restaurants;
32 |
33 | final RestaurantPressedCallback _onRestaurantPressed;
34 | final List _restaurants;
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | return ResponsiveGridList(
39 | // ResponsiveGridList crashes if desiredItemWidth + 2*minSpacing > Device window on Android
40 | desiredItemWidth: math.min(
41 | _cardWidth, MediaQuery.of(context).size.width - (2 * _minSpacingPx)),
42 | minSpacing: _minSpacingPx,
43 | children: _restaurants
44 | .map((restaurant) => RestaurantCard(
45 | restaurant: restaurant,
46 | onRestaurantPressed: _onRestaurantPressed,
47 | ))
48 | .toList(),
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/src/widgets/review.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 |
17 | import '../model/review.dart';
18 | import 'stars.dart';
19 |
20 | class RestaurantReview extends StatelessWidget {
21 | RestaurantReview({
22 | this.review,
23 | });
24 |
25 | final Review review;
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return Center(
30 | child: Container(
31 | constraints: BoxConstraints(maxWidth: 600),
32 | padding: EdgeInsets.fromLTRB(0, 16, 0, 16),
33 | decoration: BoxDecoration(
34 | border: Border(
35 | bottom: BorderSide(
36 | color: Colors.grey,
37 | width: 1,
38 | style: BorderStyle.solid,
39 | ))),
40 | child: Column(
41 | children: [
42 | Row(
43 | children: [
44 | Expanded(
45 | child: Text(
46 | review.userName,
47 | style: Theme.of(context).textTheme.caption,
48 | ),
49 | ),
50 | StarRating(rating: review.rating, size: 16),
51 | ],
52 | ),
53 | Row(
54 | children: [
55 | Expanded(
56 | child: Container(
57 | padding: EdgeInsets.fromLTRB(0, 8, 0, 0),
58 | child: Text(review.text ?? ''),
59 | ),
60 | ),
61 | ],
62 | ),
63 | ],
64 | ),
65 | ),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/src/widgets/stars.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'package:flutter/material.dart';
16 | import 'package:smooth_star_rating/smooth_star_rating.dart';
17 |
18 | class StarRating extends StatelessWidget {
19 | StarRating({
20 | this.rating,
21 | this.color = Colors.amber,
22 | this.size = 24,
23 | });
24 |
25 | final double rating;
26 | final double size;
27 | final Color color;
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return SmoothStarRating(
32 | starCount: 5,
33 | allowHalfRating: true,
34 | rating: rating,
35 | color: color,
36 | borderColor: color,
37 | size: size,
38 | isReadOnly: true,
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.5.0-nullsafety"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.1.0-nullsafety"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.1.0-nullsafety.2"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.2.0-nullsafety"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0-nullsafety"
39 | cloud_firestore:
40 | dependency: "direct main"
41 | description:
42 | name: cloud_firestore
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "0.14.0+2"
46 | cloud_firestore_platform_interface:
47 | dependency: transitive
48 | description:
49 | name: cloud_firestore_platform_interface
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "2.0.1"
53 | cloud_firestore_web:
54 | dependency: transitive
55 | description:
56 | name: cloud_firestore_web
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "0.2.0+1"
60 | collection:
61 | dependency: transitive
62 | description:
63 | name: collection
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "1.15.0-nullsafety.2"
67 | fake_async:
68 | dependency: transitive
69 | description:
70 | name: fake_async
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "1.1.0-nullsafety"
74 | firebase:
75 | dependency: transitive
76 | description:
77 | name: firebase
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "7.3.0"
81 | firebase_auth:
82 | dependency: "direct main"
83 | description:
84 | name: firebase_auth
85 | url: "https://pub.dartlang.org"
86 | source: hosted
87 | version: "0.18.0+1"
88 | firebase_auth_platform_interface:
89 | dependency: transitive
90 | description:
91 | name: firebase_auth_platform_interface
92 | url: "https://pub.dartlang.org"
93 | source: hosted
94 | version: "2.0.1"
95 | firebase_auth_web:
96 | dependency: transitive
97 | description:
98 | name: firebase_auth_web
99 | url: "https://pub.dartlang.org"
100 | source: hosted
101 | version: "0.3.0+1"
102 | firebase_core:
103 | dependency: "direct main"
104 | description:
105 | name: firebase_core
106 | url: "https://pub.dartlang.org"
107 | source: hosted
108 | version: "0.5.0"
109 | firebase_core_platform_interface:
110 | dependency: transitive
111 | description:
112 | name: firebase_core_platform_interface
113 | url: "https://pub.dartlang.org"
114 | source: hosted
115 | version: "2.0.0"
116 | firebase_core_web:
117 | dependency: transitive
118 | description:
119 | name: firebase_core_web
120 | url: "https://pub.dartlang.org"
121 | source: hosted
122 | version: "0.2.0"
123 | flutter:
124 | dependency: "direct main"
125 | description: flutter
126 | source: sdk
127 | version: "0.0.0"
128 | flutter_test:
129 | dependency: "direct dev"
130 | description: flutter
131 | source: sdk
132 | version: "0.0.0"
133 | flutter_web_plugins:
134 | dependency: transitive
135 | description: flutter
136 | source: sdk
137 | version: "0.0.0"
138 | http:
139 | dependency: transitive
140 | description:
141 | name: http
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "0.12.0+3"
145 | http_parser:
146 | dependency: transitive
147 | description:
148 | name: http_parser
149 | url: "https://pub.dartlang.org"
150 | source: hosted
151 | version: "3.1.3"
152 | intl:
153 | dependency: transitive
154 | description:
155 | name: intl
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "0.16.1"
159 | js:
160 | dependency: transitive
161 | description:
162 | name: js
163 | url: "https://pub.dartlang.org"
164 | source: hosted
165 | version: "0.6.1+1"
166 | matcher:
167 | dependency: transitive
168 | description:
169 | name: matcher
170 | url: "https://pub.dartlang.org"
171 | source: hosted
172 | version: "0.12.10-nullsafety"
173 | meta:
174 | dependency: transitive
175 | description:
176 | name: meta
177 | url: "https://pub.dartlang.org"
178 | source: hosted
179 | version: "1.3.0-nullsafety.2"
180 | path:
181 | dependency: transitive
182 | description:
183 | name: path
184 | url: "https://pub.dartlang.org"
185 | source: hosted
186 | version: "1.8.0-nullsafety"
187 | pedantic:
188 | dependency: "direct dev"
189 | description:
190 | name: pedantic
191 | url: "https://pub.dartlang.org"
192 | source: hosted
193 | version: "1.9.0"
194 | plugin_platform_interface:
195 | dependency: transitive
196 | description:
197 | name: plugin_platform_interface
198 | url: "https://pub.dartlang.org"
199 | source: hosted
200 | version: "1.0.2"
201 | quiver:
202 | dependency: transitive
203 | description:
204 | name: quiver
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "2.0.5"
208 | responsive_grid:
209 | dependency: "direct main"
210 | description:
211 | name: responsive_grid
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "1.2.1+1"
215 | sky_engine:
216 | dependency: transitive
217 | description: flutter
218 | source: sdk
219 | version: "0.0.99"
220 | sliver_fab:
221 | dependency: "direct main"
222 | description:
223 | name: sliver_fab
224 | url: "https://pub.dartlang.org"
225 | source: hosted
226 | version: "1.0.0"
227 | smooth_star_rating:
228 | dependency: "direct main"
229 | description:
230 | name: smooth_star_rating
231 | url: "https://pub.dartlang.org"
232 | source: hosted
233 | version: "1.1.1"
234 | source_span:
235 | dependency: transitive
236 | description:
237 | name: source_span
238 | url: "https://pub.dartlang.org"
239 | source: hosted
240 | version: "1.8.0-nullsafety"
241 | stack_trace:
242 | dependency: transitive
243 | description:
244 | name: stack_trace
245 | url: "https://pub.dartlang.org"
246 | source: hosted
247 | version: "1.10.0-nullsafety"
248 | stream_channel:
249 | dependency: transitive
250 | description:
251 | name: stream_channel
252 | url: "https://pub.dartlang.org"
253 | source: hosted
254 | version: "2.1.0-nullsafety"
255 | string_scanner:
256 | dependency: transitive
257 | description:
258 | name: string_scanner
259 | url: "https://pub.dartlang.org"
260 | source: hosted
261 | version: "1.1.0-nullsafety"
262 | term_glyph:
263 | dependency: transitive
264 | description:
265 | name: term_glyph
266 | url: "https://pub.dartlang.org"
267 | source: hosted
268 | version: "1.2.0-nullsafety"
269 | test_api:
270 | dependency: transitive
271 | description:
272 | name: test_api
273 | url: "https://pub.dartlang.org"
274 | source: hosted
275 | version: "0.2.19-nullsafety"
276 | typed_data:
277 | dependency: transitive
278 | description:
279 | name: typed_data
280 | url: "https://pub.dartlang.org"
281 | source: hosted
282 | version: "1.3.0-nullsafety.2"
283 | vector_math:
284 | dependency: transitive
285 | description:
286 | name: vector_math
287 | url: "https://pub.dartlang.org"
288 | source: hosted
289 | version: "2.1.0-nullsafety.2"
290 | sdks:
291 | dart: ">=2.10.0-0.0.dev <2.10.0"
292 | flutter: ">=1.12.13+hotfix.5 <2.0.0"
293 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | name: friendlyeats
16 | description: A new Flutter project.
17 |
18 | # version: 1.0.0
19 | publish_to: none
20 |
21 | environment:
22 | sdk: ">=2.7.0 <3.0.0"
23 |
24 | dependencies:
25 | firebase_core: ^0.5.0
26 | firebase_auth: ^0.18.0+1
27 | cloud_firestore: ^0.14.0+2
28 | responsive_grid: ^1.2.1+1
29 | smooth_star_rating: ^1.1.1
30 | sliver_fab: ^1.0.0
31 | flutter:
32 | sdk: flutter
33 |
34 | dev_dependencies:
35 | pedantic: ^1.9.0
36 | flutter_test:
37 | sdk: flutter
38 |
39 |
40 | # For information on the generic Dart part of this file, see the
41 | # following page: https://dart.dev/tools/pub/pubspec
42 |
43 | # The following section is specific to Flutter.
44 | flutter:
45 | # The following line ensures that the Material Icons font is
46 | # included with your application, so that you can use the icons in
47 | # the material Icons class.
48 | uses-material-design: true
49 |
50 | # For details regarding assets, see
51 | # https://flutter.dev/assets-and-images
52 | assets:
53 | - assets/friendlyeater.png
54 |
55 | # To add custom fonts to your application, add a fonts section here,
56 | # in this "flutter" section. Each entry in this list should have a
57 | # "family" key with the font family name, and a "fonts" key with a
58 | # list giving the asset and other descriptors for the font. For
59 | # example:
60 | # fonts:
61 | # - family: Schyler
62 | # fonts:
63 | # - asset: fonts/Schyler-Regular.ttf
64 | # - asset: fonts/Schyler-Italic.ttf
65 | # style: italic
66 | # - family: Trajan Pro
67 | # fonts:
68 | # - asset: fonts/TrajanPro.ttf
69 | # - asset: fonts/TrajanPro_Bold.ttf
70 | # weight: 700
71 | #
72 | # For details regarding fonts from package dependencies,
73 | # see https://flutter.dev/custom-fonts/#from-packages
74 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // This is a basic Flutter widget test.
16 | //
17 | // To perform an interaction with a widget in your test, use the WidgetTester
18 | // utility that Flutter provides. For example, you can send tap and scroll
19 | // gestures. You can also use WidgetTester to find child widgets in the widget
20 | // tree, read text, and verify that the values of widget properties are correct.
21 |
22 | import 'package:flutter/material.dart';
23 | import 'package:flutter_test/flutter_test.dart';
24 |
25 | import 'package:friendlyeats/src/app.dart';
26 |
27 | void main() {
28 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
29 | // Build our app and trigger a frame.
30 | await tester.pumpWidget(FriendlyEatsApp());
31 |
32 | // Verify that our counter starts at 0.
33 | expect(find.text('0'), findsOneWidget);
34 | expect(find.text('1'), findsNothing);
35 |
36 | // Tap the '+' icon and trigger a frame.
37 | await tester.tap(find.byIcon(Icons.add));
38 | await tester.pump();
39 |
40 | // Verify that our counter has incremented.
41 | expect(find.text('0'), findsNothing);
42 | expect(find.text('1'), findsOneWidget);
43 | });
44 | }
45 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FirebaseExtended/codelab-friendlyeats-flutter/6f7603c33f2ef0f7e37ff1730991e1982327aa6f/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | friendlyeats
34 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
61 |
62 |
63 |
66 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "friendlyeats",
3 | "short_name": "friendlyeats",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------