Initial main_m3 branch commit
							
								
								
									
										32
									
								
								.github/ISSUE_TEMPLATE/android-basics-cupcake-app.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,32 @@
 | 
			
		||||
---
 | 
			
		||||
name: Navigate between screens with Compose issue template
 | 
			
		||||
about: Issue template for Navigate between screens with Compose
 | 
			
		||||
title: 'Navigate between screens with Compose: Android Basics with Compose'
 | 
			
		||||
labels: ''
 | 
			
		||||
assignees: ''
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
**URL of codelab**
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**In which task and step of the codelab can this issue be found?**
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**Describe the problem**
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**Steps to reproduce?**
 | 
			
		||||
1. Go to...
 | 
			
		||||
2. Click on...
 | 
			
		||||
3. See error...
 | 
			
		||||
 | 
			
		||||
**Versions**
 | 
			
		||||
_Android Studio version:_ 
 | 
			
		||||
_API version of the emulator:_ 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**Additional information**
 | 
			
		||||
_Include screenshots if they would be useful in clarifying the problem._
 | 
			
		||||
							
								
								
									
										36
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,36 @@
 | 
			
		||||
# built application files
 | 
			
		||||
*.apk
 | 
			
		||||
*.ap_
 | 
			
		||||
 | 
			
		||||
# Mac files
 | 
			
		||||
.DS_Store
 | 
			
		||||
 | 
			
		||||
# files for the dex VM
 | 
			
		||||
*.dex
 | 
			
		||||
 | 
			
		||||
# Java class files
 | 
			
		||||
*.class
 | 
			
		||||
 | 
			
		||||
# generated files
 | 
			
		||||
bin/
 | 
			
		||||
gen/
 | 
			
		||||
 | 
			
		||||
# Ignore gradle files
 | 
			
		||||
.gradle/
 | 
			
		||||
build/
 | 
			
		||||
 | 
			
		||||
# Local configuration file (sdk path, etc)
 | 
			
		||||
local.properties
 | 
			
		||||
 | 
			
		||||
# Proguard folder generated by Eclipse
 | 
			
		||||
proguard/
 | 
			
		||||
proguard-project.txt
 | 
			
		||||
 | 
			
		||||
# Eclipse files
 | 
			
		||||
.project
 | 
			
		||||
.classpath
 | 
			
		||||
.settings/
 | 
			
		||||
 | 
			
		||||
# Android Studio/IDEA
 | 
			
		||||
*.iml
 | 
			
		||||
.idea
 | 
			
		||||
							
								
								
									
										29
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,29 @@
 | 
			
		||||
# How to Contribute
 | 
			
		||||
 | 
			
		||||
We'd love to accept your patches and contributions to this project. There are
 | 
			
		||||
just a few small guidelines you need to follow.
 | 
			
		||||
 | 
			
		||||
## Contributor License Agreement
 | 
			
		||||
 | 
			
		||||
Contributions to this project must be accompanied by a Contributor License
 | 
			
		||||
Agreement (CLA). You (or your employer) retain the copyright to your
 | 
			
		||||
contribution; this simply gives us permission to use and redistribute your
 | 
			
		||||
contributions as part of the project. Head over to
 | 
			
		||||
<https://cla.developers.google.com/> to see your current agreements on file or
 | 
			
		||||
to sign a new one.
 | 
			
		||||
 | 
			
		||||
You generally only need to submit a CLA once, so if you've already submitted one
 | 
			
		||||
(even if it was for a different project), you probably don't need to do it
 | 
			
		||||
again.
 | 
			
		||||
 | 
			
		||||
## Code reviews
 | 
			
		||||
 | 
			
		||||
All submissions, including submissions by project members, require review. We
 | 
			
		||||
use GitHub pull requests for this purpose. Consult
 | 
			
		||||
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
 | 
			
		||||
information on using pull requests.
 | 
			
		||||
 | 
			
		||||
## Community Guidelines
 | 
			
		||||
 | 
			
		||||
This project follows
 | 
			
		||||
[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
 | 
			
		||||
							
								
								
									
										201
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,201 @@
 | 
			
		||||
 Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   APPENDIX: How to apply the Apache License to your work.
 | 
			
		||||
 | 
			
		||||
      To apply the Apache License to your work, attach the following
 | 
			
		||||
      boilerplate notice, with the fields enclosed by brackets "[]"
 | 
			
		||||
      replaced with your own identifying information. (Don't include
 | 
			
		||||
      the brackets!)  The text should be enclosed in the appropriate
 | 
			
		||||
      comment syntax for the file format. We also recommend that a
 | 
			
		||||
      file or class name and description of purpose be included on the
 | 
			
		||||
      same "printed page" as the copyright notice for easier
 | 
			
		||||
      identification within third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright [yyyy] [name of copyright owner]
 | 
			
		||||
 | 
			
		||||
   Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
   you may not use this file except in compliance with the License.
 | 
			
		||||
   You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
   Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
   distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
   See the License for the specific language governing permissions and
 | 
			
		||||
   limitations under the License.
 | 
			
		||||
							
								
								
									
										24
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,24 @@
 | 
			
		||||
Cupcake app
 | 
			
		||||
=================================
 | 
			
		||||
 | 
			
		||||
This app contains an order flow for cupcakes with options for quantity, flavor, and pickup date.
 | 
			
		||||
The order details get displayed on an order summary screen and can be shared to another app to
 | 
			
		||||
send the order.
 | 
			
		||||
 | 
			
		||||
TODO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Pre-requisites
 | 
			
		||||
--------------
 | 
			
		||||
* Experience with Kotlin syntax.
 | 
			
		||||
* How to create and run a project in Android Studio.
 | 
			
		||||
* How to create composable functions 
 | 
			
		||||
* TODO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Getting Started
 | 
			
		||||
---------------
 | 
			
		||||
1. Install Android Studio, if you don't already have it.
 | 
			
		||||
2. Download the sample.
 | 
			
		||||
3. Import the sample into Android Studio.
 | 
			
		||||
4. Build and run the sample.
 | 
			
		||||
							
								
								
									
										90
									
								
								app/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,90 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
plugins {
 | 
			
		||||
    id 'com.android.application'
 | 
			
		||||
    id 'org.jetbrains.kotlin.android'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
android {
 | 
			
		||||
    namespace 'com.example.cupcake'
 | 
			
		||||
    compileSdk 33
 | 
			
		||||
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        applicationId "com.example.cupcake"
 | 
			
		||||
        minSdk 24
 | 
			
		||||
        targetSdk 33
 | 
			
		||||
        versionCode 1
 | 
			
		||||
        versionName "1.0"
 | 
			
		||||
 | 
			
		||||
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 | 
			
		||||
        vectorDrawables {
 | 
			
		||||
            useSupportLibrary true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    buildTypes {
 | 
			
		||||
        release {
 | 
			
		||||
            minifyEnabled false
 | 
			
		||||
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    compileOptions {
 | 
			
		||||
        sourceCompatibility JavaVersion.VERSION_1_8
 | 
			
		||||
        targetCompatibility JavaVersion.VERSION_1_8
 | 
			
		||||
    }
 | 
			
		||||
    kotlinOptions {
 | 
			
		||||
        jvmTarget = '1.8'
 | 
			
		||||
        freeCompilerArgs += "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api"
 | 
			
		||||
    }
 | 
			
		||||
    buildFeatures {
 | 
			
		||||
        compose true
 | 
			
		||||
    }
 | 
			
		||||
    composeOptions {
 | 
			
		||||
        kotlinCompilerExtensionVersion '1.4.7'
 | 
			
		||||
    }
 | 
			
		||||
    packagingOptions {
 | 
			
		||||
        resources {
 | 
			
		||||
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
 | 
			
		||||
    implementation platform('androidx.compose:compose-bom:2023.05.00')
 | 
			
		||||
    implementation 'androidx.activity:activity-compose:1.7.1'
 | 
			
		||||
    implementation 'androidx.compose.material3:material3'
 | 
			
		||||
    implementation 'androidx.compose.runtime:runtime'
 | 
			
		||||
    implementation 'androidx.compose.runtime:runtime-livedata'
 | 
			
		||||
    implementation 'androidx.compose.ui:ui'
 | 
			
		||||
    implementation 'androidx.compose.ui:ui-graphics'
 | 
			
		||||
    implementation 'androidx.compose.ui:ui-tooling-preview'
 | 
			
		||||
    implementation 'androidx.core:core-ktx:1.10.0'
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
 | 
			
		||||
    implementation 'androidx.navigation:navigation-compose:2.5.3'
 | 
			
		||||
 | 
			
		||||
    androidTestImplementation platform('androidx.compose:compose-bom:2023.05.00')
 | 
			
		||||
    androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
 | 
			
		||||
    androidTestImplementation 'androidx.navigation:navigation-testing:2.5.3'
 | 
			
		||||
    androidTestImplementation 'androidx.test.espresso:espresso-intents:3.5.1'
 | 
			
		||||
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
 | 
			
		||||
 | 
			
		||||
    debugImplementation 'androidx.compose.ui:ui-test-manifest'
 | 
			
		||||
    debugImplementation 'androidx.compose.ui:ui-tooling'
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								app/proguard-rules.pro
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
# Add project specific ProGuard rules here.
 | 
			
		||||
# You can control the set of applied configuration files using the
 | 
			
		||||
# proguardFiles setting in build.gradle.
 | 
			
		||||
#
 | 
			
		||||
# For more details, see
 | 
			
		||||
#   http://developer.android.com/guide/developing/tools/proguard.html
 | 
			
		||||
 | 
			
		||||
# If your project uses WebView with JS, uncomment the following
 | 
			
		||||
# and specify the fully qualified class name to the JavaScript interface
 | 
			
		||||
# class:
 | 
			
		||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
 | 
			
		||||
#   public *;
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
# Uncomment this to preserve the line number information for
 | 
			
		||||
# debugging stack traces.
 | 
			
		||||
#-keepattributes SourceFile,LineNumberTable
 | 
			
		||||
 | 
			
		||||
# If you keep the line number information, uncomment this to
 | 
			
		||||
# hide the original source file name.
 | 
			
		||||
#-renamesourcefileattribute SourceFile
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.test
 | 
			
		||||
 | 
			
		||||
import androidx.activity.ComponentActivity
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.ui.test.SemanticsNodeInteraction
 | 
			
		||||
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
 | 
			
		||||
import androidx.compose.ui.test.onNodeWithText
 | 
			
		||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Finds a semantics node with the given string resource id.
 | 
			
		||||
 *
 | 
			
		||||
 * The [onNodeWithText] finder provided by compose ui test API, doesn't support usage of
 | 
			
		||||
 * string resource id to find the semantics node. This extension function accesses string resource
 | 
			
		||||
 * using underlying activity property and passes it to [onNodeWithText] function as argument and
 | 
			
		||||
 * returns the [SemanticsNodeInteraction] object.
 | 
			
		||||
 */
 | 
			
		||||
fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.onNodeWithStringId(
 | 
			
		||||
    @StringRes id: Int
 | 
			
		||||
): SemanticsNodeInteraction = onNodeWithText(activity.getString(id))
 | 
			
		||||
@ -0,0 +1,153 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.test
 | 
			
		||||
 | 
			
		||||
import androidx.activity.ComponentActivity
 | 
			
		||||
import androidx.compose.ui.test.assertIsDisplayed
 | 
			
		||||
import androidx.compose.ui.test.assertIsEnabled
 | 
			
		||||
import androidx.compose.ui.test.assertIsNotEnabled
 | 
			
		||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
 | 
			
		||||
import androidx.compose.ui.test.onNodeWithText
 | 
			
		||||
import androidx.compose.ui.test.performClick
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
import com.example.cupcake.data.DataSource
 | 
			
		||||
import com.example.cupcake.data.OrderUiState
 | 
			
		||||
import com.example.cupcake.ui.OrderSummaryScreen
 | 
			
		||||
import com.example.cupcake.ui.SelectOptionScreen
 | 
			
		||||
import com.example.cupcake.ui.StartOrderScreen
 | 
			
		||||
import org.junit.Rule
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
 | 
			
		||||
class CupcakeOrderScreenTest {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Note: To access to an empty activity, the code uses ComponentActivity instead of
 | 
			
		||||
     * MainActivity.
 | 
			
		||||
     */
 | 
			
		||||
    @get:Rule
 | 
			
		||||
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()
 | 
			
		||||
 | 
			
		||||
    private val fakeOrderUiState = OrderUiState(
 | 
			
		||||
        quantity = 6,
 | 
			
		||||
        flavor = "Vanilla",
 | 
			
		||||
        date = "Wed Jul 21",
 | 
			
		||||
        price = "$100",
 | 
			
		||||
        pickupOptions = listOf()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When quantity options are provided to StartOrderScreen, the options are displayed on the
 | 
			
		||||
     * screen.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    fun startOrderScreen_verifyContent() {
 | 
			
		||||
 | 
			
		||||
        // When StartOrderScreen is loaded
 | 
			
		||||
        composeTestRule.setContent {
 | 
			
		||||
            StartOrderScreen(
 | 
			
		||||
                quantityOptions = DataSource.quantityOptions,
 | 
			
		||||
                onNextButtonClicked = {}
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Then all the options are displayed on the screen.
 | 
			
		||||
        DataSource.quantityOptions.forEach {
 | 
			
		||||
            composeTestRule.onNodeWithStringId(it.first).assertIsDisplayed()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When list of options and subtotal are provided to SelectOptionScreen,the options and subtotal
 | 
			
		||||
     * are displayed on the screen and the next button is disabled.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    fun selectOptionScreen_verifyContent() {
 | 
			
		||||
        // Given list of options
 | 
			
		||||
        val flavours = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
 | 
			
		||||
        // And sub total
 | 
			
		||||
        val subTotal = "$100"
 | 
			
		||||
 | 
			
		||||
        // When SelectOptionScreen is loaded
 | 
			
		||||
        composeTestRule.setContent {
 | 
			
		||||
            SelectOptionScreen(subtotal = subTotal, options = flavours)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Then all the options are displayed on the screen.
 | 
			
		||||
        flavours.forEach { flavour ->
 | 
			
		||||
            composeTestRule.onNodeWithText(flavour).assertIsDisplayed()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // And then the subtotal is displayed correctly.
 | 
			
		||||
        composeTestRule.onNodeWithText(
 | 
			
		||||
            composeTestRule.activity.getString(
 | 
			
		||||
                R.string.subtotal_price,
 | 
			
		||||
                subTotal
 | 
			
		||||
            )
 | 
			
		||||
        ).assertIsDisplayed()
 | 
			
		||||
 | 
			
		||||
        // And then the next button is disabled
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.next).assertIsNotEnabled()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When list of options and subtotal are provided to SelectOptionScreen, and one of the option
 | 
			
		||||
     * is selected, then the next button is enabled.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    fun selectOptionScreen_optionSelected_NextButtonEnabled() {
 | 
			
		||||
        // Given list of options
 | 
			
		||||
        val flavours = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
 | 
			
		||||
        // And sub total
 | 
			
		||||
        val subTotal = "$100"
 | 
			
		||||
 | 
			
		||||
        // When SelectOptionScreen is loaded
 | 
			
		||||
        composeTestRule.setContent {
 | 
			
		||||
            SelectOptionScreen(subtotal = subTotal, options = flavours)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // And one option is selected
 | 
			
		||||
        composeTestRule.onNodeWithText("Vanilla").performClick()
 | 
			
		||||
 | 
			
		||||
        // Then the next button is disabled
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.next).assertIsEnabled()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When a OrderUiState is provided to Summary Screen, then the flavor, date and subtotal is
 | 
			
		||||
     * displayed on the screen.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    fun summaryScreen_verifyContentDisplay() {
 | 
			
		||||
        // When Summary Screen is loaded
 | 
			
		||||
        composeTestRule.setContent {
 | 
			
		||||
            OrderSummaryScreen(
 | 
			
		||||
                orderUiState = fakeOrderUiState,
 | 
			
		||||
                onCancelButtonClicked = {},
 | 
			
		||||
                onSendButtonClicked = { _, _ -> },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Then the UI is updated correctly.
 | 
			
		||||
        composeTestRule.onNodeWithText(fakeOrderUiState.flavor).assertIsDisplayed()
 | 
			
		||||
        composeTestRule.onNodeWithText(fakeOrderUiState.date).assertIsDisplayed()
 | 
			
		||||
        composeTestRule.onNodeWithText(
 | 
			
		||||
            composeTestRule.activity.getString(
 | 
			
		||||
                R.string.subtotal_price,
 | 
			
		||||
                fakeOrderUiState.price
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,163 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.test
 | 
			
		||||
 | 
			
		||||
import android.icu.util.Calendar
 | 
			
		||||
import androidx.activity.ComponentActivity
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
 | 
			
		||||
import androidx.compose.ui.test.onNodeWithContentDescription
 | 
			
		||||
import androidx.compose.ui.test.onNodeWithText
 | 
			
		||||
import androidx.compose.ui.test.performClick
 | 
			
		||||
import androidx.navigation.compose.ComposeNavigator
 | 
			
		||||
import androidx.navigation.testing.TestNavHostController
 | 
			
		||||
import com.example.cupcake.CupcakeApp
 | 
			
		||||
import com.example.cupcake.CupcakeScreen
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
import org.junit.Before
 | 
			
		||||
import org.junit.Rule
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
import java.text.SimpleDateFormat
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
 | 
			
		||||
class CupcakeScreenNavigationTest {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Note: To access to an empty activity, the code uses ComponentActivity instead of
 | 
			
		||||
     * MainActivity.
 | 
			
		||||
     */
 | 
			
		||||
    @get:Rule
 | 
			
		||||
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()
 | 
			
		||||
 | 
			
		||||
    private lateinit var navController: TestNavHostController
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    fun setupCupcakeNavHost() {
 | 
			
		||||
        composeTestRule.setContent {
 | 
			
		||||
            navController = TestNavHostController(LocalContext.current).apply {
 | 
			
		||||
                navigatorProvider.addNavigator(ComposeNavigator())
 | 
			
		||||
            }
 | 
			
		||||
            CupcakeApp(navController = navController)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_verifyStartDestination() {
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Start.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_verifyBackNavigationNotShownOnStartOrderScreen() {
 | 
			
		||||
        val backText = composeTestRule.activity.getString(R.string.back_button)
 | 
			
		||||
        composeTestRule.onNodeWithContentDescription(backText).assertDoesNotExist()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickOneCupcake_navigatesToSelectFlavorScreen() {
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.one_cupcake)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Flavor.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickNextOnFlavorScreen_navigatesToPickupScreen() {
 | 
			
		||||
        navigateToFlavorScreen()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.next)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Pickup.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickBackOnFlavorScreen_navigatesToStartOrderScreen() {
 | 
			
		||||
        navigateToFlavorScreen()
 | 
			
		||||
        performNavigateUp()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Start.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickCancelOnFlavorScreen_navigatesToStartOrderScreen() {
 | 
			
		||||
        navigateToFlavorScreen()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.cancel)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Start.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickNextOnPickupScreen_navigatesToSummaryScreen() {
 | 
			
		||||
        navigateToPickupScreen()
 | 
			
		||||
        composeTestRule.onNodeWithText(getFormattedDate())
 | 
			
		||||
            .performClick()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.next)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Summary.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickBackOnPickupScreen_navigatesToFlavorScreen() {
 | 
			
		||||
        navigateToPickupScreen()
 | 
			
		||||
        performNavigateUp()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Flavor.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickCancelOnPickupScreen_navigatesToStartOrderScreen() {
 | 
			
		||||
        navigateToPickupScreen()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.cancel)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Start.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun cupcakeNavHost_clickCancelOnSummaryScreen_navigatesToStartOrderScreen() {
 | 
			
		||||
        navigateToSummaryScreen()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.cancel)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        navController.assertCurrentRouteName(CupcakeScreen.Start.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun navigateToFlavorScreen() {
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.one_cupcake)
 | 
			
		||||
            .performClick()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.chocolate)
 | 
			
		||||
            .performClick()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun navigateToPickupScreen() {
 | 
			
		||||
        navigateToFlavorScreen()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.next)
 | 
			
		||||
            .performClick()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun navigateToSummaryScreen() {
 | 
			
		||||
        navigateToPickupScreen()
 | 
			
		||||
        composeTestRule.onNodeWithText(getFormattedDate())
 | 
			
		||||
            .performClick()
 | 
			
		||||
        composeTestRule.onNodeWithStringId(R.string.next)
 | 
			
		||||
            .performClick()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun performNavigateUp() {
 | 
			
		||||
        val backText = composeTestRule.activity.getString(R.string.back_button)
 | 
			
		||||
        composeTestRule.onNodeWithContentDescription(backText).performClick()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getFormattedDate(): String {
 | 
			
		||||
        val calendar = Calendar.getInstance()
 | 
			
		||||
        calendar.add(java.util.Calendar.DATE, 1)
 | 
			
		||||
        val formatter = SimpleDateFormat("E MMM d", Locale.getDefault())
 | 
			
		||||
        return formatter.format(calendar.time)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,23 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.test
 | 
			
		||||
 | 
			
		||||
import androidx.navigation.NavController
 | 
			
		||||
import org.junit.Assert
 | 
			
		||||
 | 
			
		||||
fun NavController.assertCurrentRouteName(expectedRouteName: String) {
 | 
			
		||||
    Assert.assertEquals(expectedRouteName, currentBackStackEntry?.destination?.route)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								app/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,38 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools">
 | 
			
		||||
 | 
			
		||||
    <application
 | 
			
		||||
        android:icon="@mipmap/ic_launcher"
 | 
			
		||||
        android:label="@string/app_name"
 | 
			
		||||
        android:roundIcon="@mipmap/ic_launcher_round"
 | 
			
		||||
        android:supportsRtl="true"
 | 
			
		||||
        android:theme="@style/Theme.Cupcake"
 | 
			
		||||
        tools:targetApi="33">
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".MainActivity"
 | 
			
		||||
            android:exported="true"
 | 
			
		||||
            android:theme="@style/Theme.Cupcake">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.MAIN" />
 | 
			
		||||
                <category android:name="android.intent.category.LAUNCHER" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
    </application>
 | 
			
		||||
 | 
			
		||||
</manifest>
 | 
			
		||||
							
								
								
									
										201
									
								
								app/src/main/java/com/example/cupcake/CupcakeScreen.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,201 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxHeight
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxSize
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.material.icons.Icons
 | 
			
		||||
import androidx.compose.material.icons.filled.ArrowBack
 | 
			
		||||
import androidx.compose.material3.Icon
 | 
			
		||||
import androidx.compose.material3.IconButton
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Scaffold
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.material3.TopAppBar
 | 
			
		||||
import androidx.compose.material3.TopAppBarDefaults
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.res.dimensionResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.lifecycle.viewmodel.compose.viewModel
 | 
			
		||||
import androidx.navigation.NavHostController
 | 
			
		||||
import androidx.navigation.compose.NavHost
 | 
			
		||||
import androidx.navigation.compose.composable
 | 
			
		||||
import androidx.navigation.compose.currentBackStackEntryAsState
 | 
			
		||||
import androidx.navigation.compose.rememberNavController
 | 
			
		||||
import com.example.cupcake.data.DataSource
 | 
			
		||||
import com.example.cupcake.data.OrderUiState
 | 
			
		||||
import com.example.cupcake.ui.OrderSummaryScreen
 | 
			
		||||
import com.example.cupcake.ui.OrderViewModel
 | 
			
		||||
import com.example.cupcake.ui.SelectOptionScreen
 | 
			
		||||
import com.example.cupcake.ui.StartOrderScreen
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum values that represent the screens in the app
 | 
			
		||||
 */
 | 
			
		||||
enum class CupcakeScreen(@StringRes val title: Int) {
 | 
			
		||||
    Start(title = R.string.app_name),
 | 
			
		||||
    Flavor(title = R.string.choose_flavor),
 | 
			
		||||
    Pickup(title = R.string.choose_pickup_date),
 | 
			
		||||
    Summary(title = R.string.order_summary)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Composable that displays the topBar and displays back button if back navigation is possible.
 | 
			
		||||
 */
 | 
			
		||||
@Composable
 | 
			
		||||
fun CupcakeAppBar(
 | 
			
		||||
    currentScreen: CupcakeScreen,
 | 
			
		||||
    canNavigateBack: Boolean,
 | 
			
		||||
    navigateUp: () -> Unit,
 | 
			
		||||
    modifier: Modifier = Modifier
 | 
			
		||||
) {
 | 
			
		||||
    TopAppBar(
 | 
			
		||||
        title = { Text(stringResource(currentScreen.title)) },
 | 
			
		||||
        colors = TopAppBarDefaults.mediumTopAppBarColors(
 | 
			
		||||
            containerColor = MaterialTheme.colorScheme.primaryContainer
 | 
			
		||||
        ),
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        navigationIcon = {
 | 
			
		||||
            if (canNavigateBack) {
 | 
			
		||||
                IconButton(onClick = navigateUp) {
 | 
			
		||||
                    Icon(
 | 
			
		||||
                        imageVector = Icons.Filled.ArrowBack,
 | 
			
		||||
                        contentDescription = stringResource(R.string.back_button)
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun CupcakeApp(
 | 
			
		||||
    viewModel: OrderViewModel = viewModel(),
 | 
			
		||||
    navController: NavHostController = rememberNavController()
 | 
			
		||||
) {
 | 
			
		||||
    // Get current back stack entry
 | 
			
		||||
    val backStackEntry by navController.currentBackStackEntryAsState()
 | 
			
		||||
    // Get the name of the current screen
 | 
			
		||||
    val currentScreen = CupcakeScreen.valueOf(
 | 
			
		||||
        backStackEntry?.destination?.route ?: CupcakeScreen.Start.name
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    Scaffold(
 | 
			
		||||
        topBar = {
 | 
			
		||||
            CupcakeAppBar(
 | 
			
		||||
                currentScreen = currentScreen,
 | 
			
		||||
                canNavigateBack = navController.previousBackStackEntry != null,
 | 
			
		||||
                navigateUp = { navController.navigateUp() }
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    ) { innerPadding ->
 | 
			
		||||
        val uiState by viewModel.uiState.collectAsState()
 | 
			
		||||
 | 
			
		||||
        NavHost(
 | 
			
		||||
            navController = navController,
 | 
			
		||||
            startDestination = CupcakeScreen.Start.name,
 | 
			
		||||
            modifier = Modifier.padding(innerPadding)
 | 
			
		||||
        ) {
 | 
			
		||||
            composable(route = CupcakeScreen.Start.name) {
 | 
			
		||||
                StartOrderScreen(
 | 
			
		||||
                    quantityOptions = DataSource.quantityOptions,
 | 
			
		||||
                    onNextButtonClicked = {
 | 
			
		||||
                        viewModel.setQuantity(it)
 | 
			
		||||
                        navController.navigate(CupcakeScreen.Flavor.name)
 | 
			
		||||
                    },
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .fillMaxSize()
 | 
			
		||||
                        .padding(dimensionResource(R.dimen.padding_medium))
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            composable(route = CupcakeScreen.Flavor.name) {
 | 
			
		||||
                val context = LocalContext.current
 | 
			
		||||
                SelectOptionScreen(
 | 
			
		||||
                    subtotal = uiState.price,
 | 
			
		||||
                    onNextButtonClicked = { navController.navigate(CupcakeScreen.Pickup.name) },
 | 
			
		||||
                    onCancelButtonClicked = {
 | 
			
		||||
                        cancelOrderAndNavigateToStart(viewModel, navController)
 | 
			
		||||
                    },
 | 
			
		||||
                    options = DataSource.flavors.map { id -> context.resources.getString(id) },
 | 
			
		||||
                    onSelectionChanged = { viewModel.setFlavor(it) },
 | 
			
		||||
                    modifier = Modifier.fillMaxHeight()
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            composable(route = CupcakeScreen.Pickup.name) {
 | 
			
		||||
                SelectOptionScreen(
 | 
			
		||||
                    subtotal = uiState.price,
 | 
			
		||||
                    onNextButtonClicked = { navController.navigate(CupcakeScreen.Summary.name) },
 | 
			
		||||
                    onCancelButtonClicked = {
 | 
			
		||||
                        cancelOrderAndNavigateToStart(viewModel, navController)
 | 
			
		||||
                    },
 | 
			
		||||
                    options = uiState.pickupOptions,
 | 
			
		||||
                    onSelectionChanged = { viewModel.setDate(it) },
 | 
			
		||||
                    modifier = Modifier.fillMaxHeight()
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
            composable(route = CupcakeScreen.Summary.name) {
 | 
			
		||||
                val context = LocalContext.current
 | 
			
		||||
                OrderSummaryScreen(
 | 
			
		||||
                    orderUiState = uiState,
 | 
			
		||||
                    onCancelButtonClicked = {
 | 
			
		||||
                        cancelOrderAndNavigateToStart(viewModel, navController)
 | 
			
		||||
                    },
 | 
			
		||||
                    onSendButtonClicked = { subject: String, summary: String ->
 | 
			
		||||
                        shareOrder(context, subject = subject, summary = summary)
 | 
			
		||||
                    },
 | 
			
		||||
                    modifier = Modifier.fillMaxHeight()
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Resets the [OrderUiState] and pops up to [CupcakeScreen.Start]
 | 
			
		||||
 */
 | 
			
		||||
private fun cancelOrderAndNavigateToStart(
 | 
			
		||||
    viewModel: OrderViewModel,
 | 
			
		||||
    navController: NavHostController
 | 
			
		||||
) {
 | 
			
		||||
    viewModel.resetOrder()
 | 
			
		||||
    navController.popBackStack(CupcakeScreen.Start.name, inclusive = false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates an intent to share order details
 | 
			
		||||
 */
 | 
			
		||||
private fun shareOrder(context: Context, subject: String, summary: String) {
 | 
			
		||||
    // Create an ACTION_SEND implicit intent with order details in the intent extras
 | 
			
		||||
    val intent = Intent(Intent.ACTION_SEND).apply {
 | 
			
		||||
        type = "text/plain"
 | 
			
		||||
        putExtra(Intent.EXTRA_SUBJECT, subject)
 | 
			
		||||
        putExtra(Intent.EXTRA_TEXT, summary)
 | 
			
		||||
    }
 | 
			
		||||
    context.startActivity(
 | 
			
		||||
        Intent.createChooser(
 | 
			
		||||
            intent,
 | 
			
		||||
            context.getString(R.string.new_cupcake_order)
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								app/src/main/java/com/example/cupcake/MainActivity.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.activity.ComponentActivity
 | 
			
		||||
import androidx.activity.compose.setContent
 | 
			
		||||
import androidx.core.view.WindowCompat
 | 
			
		||||
import com.example.cupcake.ui.theme.CupcakeTheme
 | 
			
		||||
 | 
			
		||||
class MainActivity : ComponentActivity() {
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
        WindowCompat.setDecorFitsSystemWindows(window, false)
 | 
			
		||||
        setContent {
 | 
			
		||||
            CupcakeTheme {
 | 
			
		||||
                CupcakeApp()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								app/src/main/java/com/example/cupcake/data/DataSource.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,34 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.data
 | 
			
		||||
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
 | 
			
		||||
object DataSource {
 | 
			
		||||
    val flavors = listOf(
 | 
			
		||||
        R.string.vanilla,
 | 
			
		||||
        R.string.chocolate,
 | 
			
		||||
        R.string.red_velvet,
 | 
			
		||||
        R.string.salted_caramel,
 | 
			
		||||
        R.string.coffee
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    val quantityOptions = listOf(
 | 
			
		||||
        Pair(R.string.one_cupcake, 1),
 | 
			
		||||
        Pair(R.string.six_cupcakes, 6),
 | 
			
		||||
        Pair(R.string.twelve_cupcakes, 12)
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								app/src/main/java/com/example/cupcake/data/OrderUiState.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,33 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.data
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Data class that represents the current UI state in terms of [quantity], [flavor],
 | 
			
		||||
 * [dateOptions], selected pickup [date] and [price]
 | 
			
		||||
 */
 | 
			
		||||
data class OrderUiState(
 | 
			
		||||
    /** Selected cupcake quantity (1, 6, 12) */
 | 
			
		||||
    val quantity: Int = 0,
 | 
			
		||||
    /** Flavor of the cupcakes in the order (such as "Chocolate", "Vanilla", etc..) */
 | 
			
		||||
    val flavor: String = "",
 | 
			
		||||
    /** Selected date for pickup (such as "Jan 1") */
 | 
			
		||||
    val date: String = "",
 | 
			
		||||
    /** Total price for the order */
 | 
			
		||||
    val price: String = "",
 | 
			
		||||
    /** Available pickup dates for the order*/
 | 
			
		||||
    val pickupOptions: List<String> = listOf()
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										118
									
								
								app/src/main/java/com/example/cupcake/ui/OrderViewModel.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui
 | 
			
		||||
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import com.example.cupcake.data.OrderUiState
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.asStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.update
 | 
			
		||||
import java.text.NumberFormat
 | 
			
		||||
import java.text.SimpleDateFormat
 | 
			
		||||
import java.util.Calendar
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
 | 
			
		||||
/** Price for a single cupcake */
 | 
			
		||||
private const val PRICE_PER_CUPCAKE = 2.00
 | 
			
		||||
 | 
			
		||||
/** Additional cost for same day pickup of an order */
 | 
			
		||||
private const val PRICE_FOR_SAME_DAY_PICKUP = 3.00
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * [OrderViewModel] holds information about a cupcake order in terms of quantity, flavor, and
 | 
			
		||||
 * pickup date. It also knows how to calculate the total price based on these order details.
 | 
			
		||||
 */
 | 
			
		||||
class OrderViewModel : ViewModel() {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cupcake state for this order
 | 
			
		||||
     */
 | 
			
		||||
    private val _uiState = MutableStateFlow(OrderUiState(pickupOptions = pickupOptions()))
 | 
			
		||||
    val uiState: StateFlow<OrderUiState> = _uiState.asStateFlow()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the quantity [numberCupcakes] of cupcakes for this order's state and update the price
 | 
			
		||||
     */
 | 
			
		||||
    fun setQuantity(numberCupcakes: Int) {
 | 
			
		||||
        _uiState.update { currentState ->
 | 
			
		||||
            currentState.copy(
 | 
			
		||||
                quantity = numberCupcakes,
 | 
			
		||||
                price = calculatePrice(quantity = numberCupcakes)
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the [desiredFlavor] of cupcakes for this order's state.
 | 
			
		||||
     * Only 1 flavor can be selected for the whole order.
 | 
			
		||||
     */
 | 
			
		||||
    fun setFlavor(desiredFlavor: String) {
 | 
			
		||||
        _uiState.update { currentState ->
 | 
			
		||||
            currentState.copy(flavor = desiredFlavor)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the [pickupDate] for this order's state and update the price
 | 
			
		||||
     */
 | 
			
		||||
    fun setDate(pickupDate: String) {
 | 
			
		||||
        _uiState.update { currentState ->
 | 
			
		||||
            currentState.copy(
 | 
			
		||||
                date = pickupDate,
 | 
			
		||||
                price = calculatePrice(pickupDate = pickupDate)
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reset the order state
 | 
			
		||||
     */
 | 
			
		||||
    fun resetOrder() {
 | 
			
		||||
        _uiState.value = OrderUiState(pickupOptions = pickupOptions())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the calculated price based on the order details.
 | 
			
		||||
     */
 | 
			
		||||
    private fun calculatePrice(
 | 
			
		||||
        quantity: Int = _uiState.value.quantity,
 | 
			
		||||
        pickupDate: String = _uiState.value.date
 | 
			
		||||
    ): String {
 | 
			
		||||
        var calculatedPrice = quantity * PRICE_PER_CUPCAKE
 | 
			
		||||
        // If the user selected the first option (today) for pickup, add the surcharge
 | 
			
		||||
        if (pickupOptions()[0] == pickupDate) {
 | 
			
		||||
            calculatedPrice += PRICE_FOR_SAME_DAY_PICKUP
 | 
			
		||||
        }
 | 
			
		||||
        val formattedPrice = NumberFormat.getCurrencyInstance().format(calculatedPrice)
 | 
			
		||||
        return formattedPrice
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a list of date options starting with the current date and the following 3 dates.
 | 
			
		||||
     */
 | 
			
		||||
    private fun pickupOptions(): List<String> {
 | 
			
		||||
        val dateOptions = mutableListOf<String>()
 | 
			
		||||
        val formatter = SimpleDateFormat("E MMM d", Locale.getDefault())
 | 
			
		||||
        val calendar = Calendar.getInstance()
 | 
			
		||||
        // add current date and the following 3 dates.
 | 
			
		||||
        repeat(4) {
 | 
			
		||||
            dateOptions.add(formatter.format(calendar.time))
 | 
			
		||||
            calendar.add(Calendar.DATE, 1)
 | 
			
		||||
        }
 | 
			
		||||
        return dateOptions
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,132 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxHeight
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.selection.selectable
 | 
			
		||||
import androidx.compose.material3.Button
 | 
			
		||||
import androidx.compose.material3.Divider
 | 
			
		||||
import androidx.compose.material3.OutlinedButton
 | 
			
		||||
import androidx.compose.material3.RadioButton
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.compose.runtime.saveable.rememberSaveable
 | 
			
		||||
import androidx.compose.runtime.setValue
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.dimensionResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
import com.example.cupcake.ui.components.FormattedPriceLabel
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Composable that displays the list of items as [RadioButton] options,
 | 
			
		||||
 * [onSelectionChanged] lambda that notifies the parent composable when a new value is selected,
 | 
			
		||||
 * [onCancelButtonClicked] lambda that cancels the order when user clicks cancel and
 | 
			
		||||
 * [onNextButtonClicked] lambda that triggers the navigation to next screen
 | 
			
		||||
 */
 | 
			
		||||
@Composable
 | 
			
		||||
fun SelectOptionScreen(
 | 
			
		||||
    subtotal: String,
 | 
			
		||||
    options: List<String>,
 | 
			
		||||
    onSelectionChanged: (String) -> Unit = {},
 | 
			
		||||
    onCancelButtonClicked: () -> Unit = {},
 | 
			
		||||
    onNextButtonClicked: () -> Unit = {},
 | 
			
		||||
    modifier: Modifier = Modifier
 | 
			
		||||
){
 | 
			
		||||
    var selectedValue by rememberSaveable { mutableStateOf("") }
 | 
			
		||||
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        verticalArrangement = Arrangement.SpaceBetween
 | 
			
		||||
    ) {
 | 
			
		||||
        Column(modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))){
 | 
			
		||||
            options.forEach { item ->
 | 
			
		||||
                Row(
 | 
			
		||||
                    modifier = Modifier.selectable(
 | 
			
		||||
                        selected = selectedValue == item,
 | 
			
		||||
                        onClick = {
 | 
			
		||||
                            selectedValue = item
 | 
			
		||||
                            onSelectionChanged(item)
 | 
			
		||||
                        }
 | 
			
		||||
                    ),
 | 
			
		||||
                    verticalAlignment = Alignment.CenterVertically
 | 
			
		||||
                ){
 | 
			
		||||
                    RadioButton(
 | 
			
		||||
                        selected = selectedValue == item,
 | 
			
		||||
                        onClick = {
 | 
			
		||||
                            selectedValue = item
 | 
			
		||||
                            onSelectionChanged(item)
 | 
			
		||||
                        }
 | 
			
		||||
                    )
 | 
			
		||||
                    Text(item)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Divider(
 | 
			
		||||
                thickness = dimensionResource(R.dimen.thickness_divider),
 | 
			
		||||
                modifier = Modifier.padding(bottom = dimensionResource(R.dimen.padding_medium))
 | 
			
		||||
            )
 | 
			
		||||
            FormattedPriceLabel(
 | 
			
		||||
                subtotal = subtotal,
 | 
			
		||||
                modifier = Modifier
 | 
			
		||||
                    .align(Alignment.End)
 | 
			
		||||
                    .padding(
 | 
			
		||||
                        top = dimensionResource(R.dimen.padding_medium),
 | 
			
		||||
                        bottom = dimensionResource(R.dimen.padding_medium)
 | 
			
		||||
                    )
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        Row(
 | 
			
		||||
            modifier = Modifier
 | 
			
		||||
                .fillMaxWidth()
 | 
			
		||||
                .padding(dimensionResource(R.dimen.padding_medium))
 | 
			
		||||
                .weight(1f, false),
 | 
			
		||||
            horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_medium)),
 | 
			
		||||
            verticalAlignment = Alignment.Bottom
 | 
			
		||||
        ){
 | 
			
		||||
            OutlinedButton(modifier = Modifier.weight(1f), onClick = onCancelButtonClicked) {
 | 
			
		||||
                Text(stringResource(R.string.cancel))
 | 
			
		||||
            }
 | 
			
		||||
            Button(
 | 
			
		||||
                modifier = Modifier.weight(1f),
 | 
			
		||||
                // the button is enabled when the user makes a selection
 | 
			
		||||
                enabled = selectedValue.isNotEmpty(),
 | 
			
		||||
                onClick = onNextButtonClicked
 | 
			
		||||
            ) {
 | 
			
		||||
                Text(stringResource(R.string.next))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun SelectOptionPreview(){
 | 
			
		||||
    SelectOptionScreen(
 | 
			
		||||
        subtotal = "299.99",
 | 
			
		||||
        options = listOf("Option 1", "Option 2", "Option 3", "Option 4"),
 | 
			
		||||
        modifier = Modifier.fillMaxHeight()
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										123
									
								
								app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,123 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.StringRes
 | 
			
		||||
import androidx.compose.foundation.Image
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.Spacer
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxHeight
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxSize
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.height
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.layout.width
 | 
			
		||||
import androidx.compose.foundation.layout.widthIn
 | 
			
		||||
import androidx.compose.material3.Button
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.dimensionResource
 | 
			
		||||
import androidx.compose.ui.res.painterResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
import com.example.cupcake.data.DataSource
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Composable that allows the user to select the desired cupcake quantity and expects
 | 
			
		||||
 * [onNextButtonClicked] lambda that expects the selected quantity and triggers the navigation to
 | 
			
		||||
 * next screen
 | 
			
		||||
 */
 | 
			
		||||
@Composable
 | 
			
		||||
fun StartOrderScreen(
 | 
			
		||||
    quantityOptions: List<Pair<Int, Int>>,
 | 
			
		||||
    onNextButtonClicked: (Int) -> Unit,
 | 
			
		||||
    modifier: Modifier = Modifier
 | 
			
		||||
){
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        verticalArrangement = Arrangement.SpaceBetween
 | 
			
		||||
    ) {
 | 
			
		||||
        Column(
 | 
			
		||||
            modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
            horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
            verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_small))
 | 
			
		||||
        ) {
 | 
			
		||||
            Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_medium)))
 | 
			
		||||
            Image(
 | 
			
		||||
                painter = painterResource(R.drawable.cupcake),
 | 
			
		||||
                contentDescription = null,
 | 
			
		||||
                modifier = Modifier.width(300.dp)
 | 
			
		||||
            )
 | 
			
		||||
            Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_medium)))
 | 
			
		||||
            Text(
 | 
			
		||||
                text = stringResource(R.string.order_cupcakes),
 | 
			
		||||
                style = MaterialTheme.typography.headlineSmall
 | 
			
		||||
            )
 | 
			
		||||
            Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
 | 
			
		||||
        }
 | 
			
		||||
        Row(modifier = Modifier.weight(1f, false)) {
 | 
			
		||||
            Column(
 | 
			
		||||
                modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                verticalArrangement = Arrangement.spacedBy(
 | 
			
		||||
                    dimensionResource(id = R.dimen.padding_medium)
 | 
			
		||||
                )
 | 
			
		||||
            ) {
 | 
			
		||||
                quantityOptions.forEach { item ->
 | 
			
		||||
                    SelectQuantityButton(
 | 
			
		||||
                        labelResourceId = item.first,
 | 
			
		||||
                        onClick = { onNextButtonClicked(item.second) }
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Customizable button composable that displays the [labelResourceId]
 | 
			
		||||
 * and triggers [onClick] lambda when this composable is clicked
 | 
			
		||||
 */
 | 
			
		||||
@Composable
 | 
			
		||||
fun SelectQuantityButton(
 | 
			
		||||
    @StringRes labelResourceId: Int,
 | 
			
		||||
    onClick: () -> Unit,
 | 
			
		||||
    modifier: Modifier = Modifier
 | 
			
		||||
){
 | 
			
		||||
    Button(
 | 
			
		||||
        onClick = onClick,
 | 
			
		||||
        modifier = modifier.widthIn(min = 250.dp)
 | 
			
		||||
    ) {
 | 
			
		||||
        Text(stringResource(labelResourceId))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun StartOrderPreview(){
 | 
			
		||||
    StartOrderScreen(
 | 
			
		||||
        quantityOptions = DataSource.quantityOptions,
 | 
			
		||||
        onNextButtonClicked = {},
 | 
			
		||||
        modifier = Modifier.fillMaxSize().padding(dimensionResource(R.dimen.padding_medium))
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										133
									
								
								app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,133 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.Spacer
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxHeight
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.height
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.material3.Button
 | 
			
		||||
import androidx.compose.material3.Divider
 | 
			
		||||
import androidx.compose.material3.OutlinedButton
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.res.dimensionResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.text.font.FontWeight
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
import com.example.cupcake.data.OrderUiState
 | 
			
		||||
import com.example.cupcake.ui.components.FormattedPriceLabel
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This composable expects [orderUiState] that represents the order state, [onCancelButtonClicked]
 | 
			
		||||
 * lambda that triggers canceling the order and passes the final order to [onSendButtonClicked]
 | 
			
		||||
 * lambda
 | 
			
		||||
 */
 | 
			
		||||
@Composable
 | 
			
		||||
fun OrderSummaryScreen(
 | 
			
		||||
    orderUiState: OrderUiState,
 | 
			
		||||
    onCancelButtonClicked: () -> Unit,
 | 
			
		||||
    onSendButtonClicked: (String, String) -> Unit,
 | 
			
		||||
    modifier: Modifier = Modifier
 | 
			
		||||
){
 | 
			
		||||
    val resources = LocalContext.current.resources
 | 
			
		||||
 | 
			
		||||
    val numberOfCupcakes = resources.getQuantityString(
 | 
			
		||||
        R.plurals.cupcakes,
 | 
			
		||||
        orderUiState.quantity,
 | 
			
		||||
        orderUiState.quantity
 | 
			
		||||
    )
 | 
			
		||||
    //Load and format a string resource with the parameters.
 | 
			
		||||
    val orderSummary = stringResource(
 | 
			
		||||
        R.string.order_details,
 | 
			
		||||
        numberOfCupcakes,
 | 
			
		||||
        orderUiState.flavor,
 | 
			
		||||
        orderUiState.date,
 | 
			
		||||
        orderUiState.quantity
 | 
			
		||||
    )
 | 
			
		||||
    val newOrder = stringResource(R.string.new_cupcake_order)
 | 
			
		||||
    //Create a list of order summary to display
 | 
			
		||||
    val items = listOf(
 | 
			
		||||
        // Summary line 1: display selected quantity
 | 
			
		||||
        Pair(stringResource(R.string.quantity), numberOfCupcakes),
 | 
			
		||||
        // Summary line 2: display selected flavor
 | 
			
		||||
        Pair(stringResource(R.string.flavor), orderUiState.flavor),
 | 
			
		||||
        // Summary line 3: display selected pickup date
 | 
			
		||||
        Pair(stringResource(R.string.pickup_date), orderUiState.date)
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        verticalArrangement = Arrangement.SpaceBetween
 | 
			
		||||
    ) {
 | 
			
		||||
        Column(
 | 
			
		||||
            modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium)),
 | 
			
		||||
            verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_small))
 | 
			
		||||
        ) {
 | 
			
		||||
            items.forEach { item ->
 | 
			
		||||
                Text(item.first.uppercase())
 | 
			
		||||
                Text(text = item.second, fontWeight = FontWeight.Bold)
 | 
			
		||||
                Divider(thickness = dimensionResource(R.dimen.thickness_divider))
 | 
			
		||||
            }
 | 
			
		||||
            Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small)))
 | 
			
		||||
            FormattedPriceLabel(
 | 
			
		||||
                subtotal = orderUiState.price,
 | 
			
		||||
                modifier = Modifier.align(Alignment.End)
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        Row(
 | 
			
		||||
            modifier = Modifier
 | 
			
		||||
                .weight(1f, false)
 | 
			
		||||
                .padding(dimensionResource(R.dimen.padding_medium))
 | 
			
		||||
        ) {
 | 
			
		||||
            Column(
 | 
			
		||||
                verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_small))
 | 
			
		||||
            ) {
 | 
			
		||||
                Button(
 | 
			
		||||
                    modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                    onClick = { onSendButtonClicked(newOrder, orderSummary) }
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(stringResource(R.string.send))
 | 
			
		||||
                }
 | 
			
		||||
                OutlinedButton(
 | 
			
		||||
                    modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                    onClick = onCancelButtonClicked
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(stringResource(R.string.cancel))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun OrderSummaryPreview(){
 | 
			
		||||
    OrderSummaryScreen(
 | 
			
		||||
        orderUiState = OrderUiState(0, "Test", "Test", "$300.00"),
 | 
			
		||||
        onSendButtonClicked = { subject: String, summary: String -> },
 | 
			
		||||
        onCancelButtonClicked = {},
 | 
			
		||||
        modifier = Modifier.fillMaxHeight()
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui.components
 | 
			
		||||
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import com.example.cupcake.R
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Composable that displays formatted [price] that will be formatted and displayed on screen
 | 
			
		||||
 */
 | 
			
		||||
@Composable
 | 
			
		||||
fun FormattedPriceLabel(subtotal: String, modifier: Modifier = Modifier) {
 | 
			
		||||
    Text(
 | 
			
		||||
        text = stringResource(R.string.subtotal_price, subtotal),
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        style = MaterialTheme.typography.headlineSmall
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										78
									
								
								app/src/main/java/com/example/cupcake/ui/theme/Color.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,78 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui.theme
 | 
			
		||||
 | 
			
		||||
import androidx.compose.ui.graphics.Color
 | 
			
		||||
 | 
			
		||||
val md_theme_light_primary = Color(0xFF984062)
 | 
			
		||||
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
 | 
			
		||||
val md_theme_light_primaryContainer = Color(0xFFFFD9E2)
 | 
			
		||||
val md_theme_light_onPrimaryContainer = Color(0xFF3E001E)
 | 
			
		||||
val md_theme_light_secondary = Color(0xFF74565F)
 | 
			
		||||
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
 | 
			
		||||
val md_theme_light_secondaryContainer = Color(0xFFFFD9E2)
 | 
			
		||||
val md_theme_light_onSecondaryContainer = Color(0xFF2B151C)
 | 
			
		||||
val md_theme_light_tertiary = Color(0xFF7C5635)
 | 
			
		||||
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
 | 
			
		||||
val md_theme_light_tertiaryContainer = Color(0xFFFFDCC2)
 | 
			
		||||
val md_theme_light_onTertiaryContainer = Color(0xFF2E1500)
 | 
			
		||||
val md_theme_light_error = Color(0xFFBA1A1A)
 | 
			
		||||
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
 | 
			
		||||
val md_theme_light_onError = Color(0xFFFFFFFF)
 | 
			
		||||
val md_theme_light_onErrorContainer = Color(0xFF410002)
 | 
			
		||||
val md_theme_light_background = Color(0xFFFFFBFF)
 | 
			
		||||
val md_theme_light_onBackground = Color(0xFF201A1B)
 | 
			
		||||
val md_theme_light_surface = Color(0xFFFFFBFF)
 | 
			
		||||
val md_theme_light_onSurface = Color(0xFF201A1B)
 | 
			
		||||
val md_theme_light_surfaceVariant = Color(0xFFF2DDE2)
 | 
			
		||||
val md_theme_light_onSurfaceVariant = Color(0xFF514347)
 | 
			
		||||
val md_theme_light_outline = Color(0xFF837377)
 | 
			
		||||
val md_theme_light_inverseOnSurface = Color(0xFFFAEEEF)
 | 
			
		||||
val md_theme_light_inverseSurface = Color(0xFF352F30)
 | 
			
		||||
val md_theme_light_inversePrimary = Color(0xFFFFB0C9)
 | 
			
		||||
val md_theme_light_surfaceTint = Color(0xFF984062)
 | 
			
		||||
val md_theme_light_outlineVariant = Color(0xFFD5C2C6)
 | 
			
		||||
val md_theme_light_scrim = Color(0xFF000000)
 | 
			
		||||
 | 
			
		||||
val md_theme_dark_primary = Color(0xFFFFB0C9)
 | 
			
		||||
val md_theme_dark_onPrimary = Color(0xFF5E1133)
 | 
			
		||||
val md_theme_dark_primaryContainer = Color(0xFF7B294A)
 | 
			
		||||
val md_theme_dark_onPrimaryContainer = Color(0xFFFFD9E2)
 | 
			
		||||
val md_theme_dark_secondary = Color(0xFFE2BDC7)
 | 
			
		||||
val md_theme_dark_onSecondary = Color(0xFF422931)
 | 
			
		||||
val md_theme_dark_secondaryContainer = Color(0xFF5A3F47)
 | 
			
		||||
val md_theme_dark_onSecondaryContainer = Color(0xFFFFD9E2)
 | 
			
		||||
val md_theme_dark_tertiary = Color(0xFFEFBD94)
 | 
			
		||||
val md_theme_dark_onTertiary = Color(0xFF48290C)
 | 
			
		||||
val md_theme_dark_tertiaryContainer = Color(0xFF623F20)
 | 
			
		||||
val md_theme_dark_onTertiaryContainer = Color(0xFFFFDCC2)
 | 
			
		||||
val md_theme_dark_error = Color(0xFFFFB4AB)
 | 
			
		||||
val md_theme_dark_errorContainer = Color(0xFF93000A)
 | 
			
		||||
val md_theme_dark_onError = Color(0xFF690005)
 | 
			
		||||
val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6)
 | 
			
		||||
val md_theme_dark_background = Color(0xFF201A1B)
 | 
			
		||||
val md_theme_dark_onBackground = Color(0xFFEBE0E1)
 | 
			
		||||
val md_theme_dark_surface = Color(0xFF201A1B)
 | 
			
		||||
val md_theme_dark_onSurface = Color(0xFFEBE0E1)
 | 
			
		||||
val md_theme_dark_surfaceVariant = Color(0xFF514347)
 | 
			
		||||
val md_theme_dark_onSurfaceVariant = Color(0xFFD5C2C6)
 | 
			
		||||
val md_theme_dark_outline = Color(0xFF9E8C90)
 | 
			
		||||
val md_theme_dark_inverseOnSurface = Color(0xFF201A1B)
 | 
			
		||||
val md_theme_dark_inverseSurface = Color(0xFFEBE0E1)
 | 
			
		||||
val md_theme_dark_inversePrimary = Color(0xFF984062)
 | 
			
		||||
val md_theme_dark_surfaceTint = Color(0xFFFFB0C9)
 | 
			
		||||
val md_theme_dark_outlineVariant = Color(0xFF514347)
 | 
			
		||||
val md_theme_dark_scrim = Color(0xFF000000)
 | 
			
		||||
							
								
								
									
										127
									
								
								app/src/main/java/com/example/cupcake/ui/theme/Theme.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,127 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui.theme
 | 
			
		||||
 | 
			
		||||
import android.app.Activity
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import androidx.compose.foundation.isSystemInDarkTheme
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.darkColorScheme
 | 
			
		||||
import androidx.compose.material3.dynamicDarkColorScheme
 | 
			
		||||
import androidx.compose.material3.dynamicLightColorScheme
 | 
			
		||||
import androidx.compose.material3.lightColorScheme
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.SideEffect
 | 
			
		||||
import androidx.compose.ui.graphics.toArgb
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.platform.LocalView
 | 
			
		||||
import androidx.core.view.WindowCompat
 | 
			
		||||
 | 
			
		||||
private val LightColors = lightColorScheme(
 | 
			
		||||
    primary = md_theme_light_primary,
 | 
			
		||||
    onPrimary = md_theme_light_onPrimary,
 | 
			
		||||
    primaryContainer = md_theme_light_primaryContainer,
 | 
			
		||||
    onPrimaryContainer = md_theme_light_onPrimaryContainer,
 | 
			
		||||
    secondary = md_theme_light_secondary,
 | 
			
		||||
    onSecondary = md_theme_light_onSecondary,
 | 
			
		||||
    secondaryContainer = md_theme_light_secondaryContainer,
 | 
			
		||||
    onSecondaryContainer = md_theme_light_onSecondaryContainer,
 | 
			
		||||
    tertiary = md_theme_light_tertiary,
 | 
			
		||||
    onTertiary = md_theme_light_onTertiary,
 | 
			
		||||
    tertiaryContainer = md_theme_light_tertiaryContainer,
 | 
			
		||||
    onTertiaryContainer = md_theme_light_onTertiaryContainer,
 | 
			
		||||
    error = md_theme_light_error,
 | 
			
		||||
    errorContainer = md_theme_light_errorContainer,
 | 
			
		||||
    onError = md_theme_light_onError,
 | 
			
		||||
    onErrorContainer = md_theme_light_onErrorContainer,
 | 
			
		||||
    background = md_theme_light_background,
 | 
			
		||||
    onBackground = md_theme_light_onBackground,
 | 
			
		||||
    surface = md_theme_light_surface,
 | 
			
		||||
    onSurface = md_theme_light_onSurface,
 | 
			
		||||
    surfaceVariant = md_theme_light_surfaceVariant,
 | 
			
		||||
    onSurfaceVariant = md_theme_light_onSurfaceVariant,
 | 
			
		||||
    outline = md_theme_light_outline,
 | 
			
		||||
    inverseOnSurface = md_theme_light_inverseOnSurface,
 | 
			
		||||
    inverseSurface = md_theme_light_inverseSurface,
 | 
			
		||||
    inversePrimary = md_theme_light_inversePrimary,
 | 
			
		||||
    surfaceTint = md_theme_light_surfaceTint,
 | 
			
		||||
    outlineVariant = md_theme_light_outlineVariant,
 | 
			
		||||
    scrim = md_theme_light_scrim,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
private val DarkColors = darkColorScheme(
 | 
			
		||||
    primary = md_theme_dark_primary,
 | 
			
		||||
    onPrimary = md_theme_dark_onPrimary,
 | 
			
		||||
    primaryContainer = md_theme_dark_primaryContainer,
 | 
			
		||||
    onPrimaryContainer = md_theme_dark_onPrimaryContainer,
 | 
			
		||||
    secondary = md_theme_dark_secondary,
 | 
			
		||||
    onSecondary = md_theme_dark_onSecondary,
 | 
			
		||||
    secondaryContainer = md_theme_dark_secondaryContainer,
 | 
			
		||||
    onSecondaryContainer = md_theme_dark_onSecondaryContainer,
 | 
			
		||||
    tertiary = md_theme_dark_tertiary,
 | 
			
		||||
    onTertiary = md_theme_dark_onTertiary,
 | 
			
		||||
    tertiaryContainer = md_theme_dark_tertiaryContainer,
 | 
			
		||||
    onTertiaryContainer = md_theme_dark_onTertiaryContainer,
 | 
			
		||||
    error = md_theme_dark_error,
 | 
			
		||||
    errorContainer = md_theme_dark_errorContainer,
 | 
			
		||||
    onError = md_theme_dark_onError,
 | 
			
		||||
    onErrorContainer = md_theme_dark_onErrorContainer,
 | 
			
		||||
    background = md_theme_dark_background,
 | 
			
		||||
    onBackground = md_theme_dark_onBackground,
 | 
			
		||||
    surface = md_theme_dark_surface,
 | 
			
		||||
    onSurface = md_theme_dark_onSurface,
 | 
			
		||||
    surfaceVariant = md_theme_dark_surfaceVariant,
 | 
			
		||||
    onSurfaceVariant = md_theme_dark_onSurfaceVariant,
 | 
			
		||||
    outline = md_theme_dark_outline,
 | 
			
		||||
    inverseOnSurface = md_theme_dark_inverseOnSurface,
 | 
			
		||||
    inverseSurface = md_theme_dark_inverseSurface,
 | 
			
		||||
    inversePrimary = md_theme_dark_inversePrimary,
 | 
			
		||||
    surfaceTint = md_theme_dark_surfaceTint,
 | 
			
		||||
    outlineVariant = md_theme_dark_outlineVariant,
 | 
			
		||||
    scrim = md_theme_dark_scrim,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun CupcakeTheme(
 | 
			
		||||
    darkTheme: Boolean = isSystemInDarkTheme(),
 | 
			
		||||
    // Dynamic color is available on Android 12+ but turned off for training purposes
 | 
			
		||||
    dynamicColor: Boolean = false,
 | 
			
		||||
    content: @Composable () -> Unit
 | 
			
		||||
) {
 | 
			
		||||
    val colorScheme = when {
 | 
			
		||||
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
 | 
			
		||||
            val context = LocalContext.current
 | 
			
		||||
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        darkTheme -> DarkColors
 | 
			
		||||
        else -> LightColors
 | 
			
		||||
    }
 | 
			
		||||
    val view = LocalView.current
 | 
			
		||||
    if (!view.isInEditMode) {
 | 
			
		||||
        SideEffect {
 | 
			
		||||
            val window = (view.context as Activity).window
 | 
			
		||||
            window.statusBarColor = colorScheme.primary.toArgb()
 | 
			
		||||
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MaterialTheme(
 | 
			
		||||
        colorScheme = colorScheme,
 | 
			
		||||
        typography = Typography,
 | 
			
		||||
        content = content
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								app/src/main/java/com/example/cupcake/ui/theme/Type.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,33 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package com.example.cupcake.ui.theme
 | 
			
		||||
 | 
			
		||||
import androidx.compose.material3.Typography
 | 
			
		||||
import androidx.compose.ui.text.TextStyle
 | 
			
		||||
import androidx.compose.ui.text.font.FontFamily
 | 
			
		||||
import androidx.compose.ui.text.font.FontWeight
 | 
			
		||||
import androidx.compose.ui.unit.sp
 | 
			
		||||
 | 
			
		||||
// Set of Material typography styles to start with
 | 
			
		||||
val Typography = Typography(
 | 
			
		||||
    bodyLarge = TextStyle(
 | 
			
		||||
        fontFamily = FontFamily.Default,
 | 
			
		||||
        fontWeight = FontWeight.Normal,
 | 
			
		||||
        fontSize = 16.sp,
 | 
			
		||||
        lineHeight = 24.sp,
 | 
			
		||||
        letterSpacing = 0.5.sp
 | 
			
		||||
    )
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										45
									
								
								app/src/main/res/drawable-v24/ic_launcher_foreground.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,45 @@
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:aapt="http://schemas.android.com/aapt"
 | 
			
		||||
    android:width="108dp"
 | 
			
		||||
    android:height="108dp"
 | 
			
		||||
    android:viewportWidth="108"
 | 
			
		||||
    android:viewportHeight="108">
 | 
			
		||||
    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
 | 
			
		||||
        <aapt:attr name="android:fillColor">
 | 
			
		||||
            <gradient
 | 
			
		||||
                android:endX="85.84757"
 | 
			
		||||
                android:endY="92.4963"
 | 
			
		||||
                android:startX="42.9492"
 | 
			
		||||
                android:startY="49.59793"
 | 
			
		||||
                android:type="linear">
 | 
			
		||||
                <item
 | 
			
		||||
                    android:color="#44000000"
 | 
			
		||||
                    android:offset="0.0" />
 | 
			
		||||
                <item
 | 
			
		||||
                    android:color="#00000000"
 | 
			
		||||
                    android:offset="1.0" />
 | 
			
		||||
            </gradient>
 | 
			
		||||
        </aapt:attr>
 | 
			
		||||
    </path>
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#FFFFFF"
 | 
			
		||||
        android:fillType="nonZero"
 | 
			
		||||
        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
 | 
			
		||||
        android:strokeWidth="1"
 | 
			
		||||
        android:strokeColor="#00000000" />
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										44
									
								
								app/src/main/res/drawable/cupcake.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,44 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<!-- Cupcake icon for the start fragment -->
 | 
			
		||||
<vector android:height="200dp" android:viewportHeight="413.71"
 | 
			
		||||
    android:viewportWidth="308.15" android:width="148.96909dp" xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <path android:fillColor="#4fc3f7" android:pathData="M34.33,218.79l-27.63,-11.72l-6.7,27.68l34.33,-15.96z"/>
 | 
			
		||||
    <path android:fillColor="#4fc3f7" android:pathData="M273.75,218.79l27.63,-11.72l6.69,27.68l-34.32,-15.96z"/>
 | 
			
		||||
    <path android:fillColor="#4fc3f7" android:pathData="M27.22,225.91l20.35,-30.56l29.24,22.58l24.1,-27.94l27.32,24.84l25.84,-26.36l25.85,26.36l27.32,-24.84l24.1,27.94l29.24,-22.58l20.35,30.56"/>
 | 
			
		||||
    <path android:fillColor="#03a9f4" android:pathData="M280.93,233.84l-20.35,30.57l-29.24,-22.59l-24.1,27.95l-27.32,-24.84l-25.85,26.36l-25.84,-26.36l-27.32,24.84l-24.1,-27.95l-29.24,22.59l-20.35,-30.57"/>
 | 
			
		||||
    <path android:fillColor="#ffe0b2" android:pathData="M6.72,245.77a147.35,49.81 0,1 0,294.7 0a147.35,49.81 0,1 0,-294.7 0z"/>
 | 
			
		||||
    <path android:fillColor="#81d4fa" android:pathData="M308.15,234.77 L289.5,219.22l-21.58,31L237.06,228l-25.52,28.14 -28.88,-24.72L155.3,257.8 128,231.41 99.07,256.13 73.54,228 42.68,250.25l-21.58,-31L0,234.75 29.3,380.43C41,424.8 268.46,424.8 281,380.43Z"/>
 | 
			
		||||
    <path android:fillColor="#4fc3f7" android:pathData="M296.79,290a177.71,177.71 0,0 1,-14.08 22.93c-6.49,8.8 -12.95,17.78 -20.38,25.84 -7.2,7.83 -16.18,14 -24.61,20.32 -26.6,19.82 -63.2,26.79 -95.82,20.47C119.55,377.93 101.2,373 81.14,362c-27.72,-15.16 -49.54,-41.31 -65.72,-67.86 -1.86,-3.05 -3.63,-6.14 -5.34,-9.27L29.3,380.43C41,424.8 268.46,424.8 281,380.43l17.45,-93.7C297.92,287.82 297.36,288.91 296.79,290Z"/>
 | 
			
		||||
    <path android:fillColor="#29b6f6" android:pathData="M58.88,378.74a2,2 0,0 1,-2 -1.74L42.39,263.14a2,2 0,1 1,4 -0.51L60.87,376.49a2,2 0,0 1,-1.73 2.24Z"/>
 | 
			
		||||
    <path android:fillColor="#29b6f6" android:pathData="M104.17,385.44a2,2 0,0 1,-2 -1.92l-4.5,-116.09a2,2 0,1 1,4 -0.16l4.51,116.09a2,2 0,0 1,-1.92 2.08Z"/>
 | 
			
		||||
    <path android:fillColor="#29b6f6" android:pathData="M252.08,378.74h-0.26a2,2 0,0 1,-1.73 -2.24L264.6,262.63a2,2 0,1 1,4 0.51L254.06,377A2,2 0,0 1,252.08 378.74Z"/>
 | 
			
		||||
    <path android:fillColor="#29b6f6" android:pathData="M206.79,385.44h-0.08a2,2 0,0 1,-1.92 -2.08l4.5,-116.09a2,2 0,0 1,4 0.16l-4.5,116.09A2,2 0,0 1,206.79 385.44Z"/>
 | 
			
		||||
    <path android:fillColor="#29b6f6" android:pathData="M155.18,388.79a2,2 0,0 1,-2 -2V270.14a2,2 0,0 1,4 0V386.79A2,2 0,0 1,155.18 388.79Z"/>
 | 
			
		||||
    <path android:fillColor="#f06292" android:pathData="M174.42,0.11S186.94,47.44 104,57.92c0,0 -48.29,5.29 -33.19,37.35a21.64,21.64 0,0 1,-5.47 25.88C47.92,135.74 24.89,164.84 46.08,207a13.44,13.44 0,0 0,7.28 6.57c20.12,7.53 101.54,33.31 201.88,1.32a13.21,13.21 0,0 0,6.3 -4.34c6.57,-8.21 20.38,-31.37 -2.24,-60.91A26.16,26.16 0,0 1,254 135.12c-0.51,-9.9 -4.73,-27.17 -25.88,-39.45a13.57,13.57 0,0 1,-5.69 -16.92c4,-9.75 7.66,-24.1 2,-36.44C214.6,21.28 174.42,0.11 174.42,0.11Z"/>
 | 
			
		||||
    <path android:fillColor="#ec407a" android:pathData="M256,204.18c-18.82,3.85 -38.66,6.32 -58,5.56a342.08,342.08 0,0 1,-54.75 -7,191.23 191.23,0 0,1 -31,-9 372.7,372.7 0,0 1,-43.43 -19.84c-9.64,-5.25 -19.52,-11.32 -28.07,-18.59 -4.75,14.09 -4.81,31.38 5.4,51.71a13.44,13.44 0,0 0,7.28 6.57c20.12,7.53 101.54,33.31 201.88,1.31a13.12,13.12 0,0 0,6.3 -4.33,48.91 48.91,0 0,0 5.89,-9.43A105.18,105.18 0,0 1,256 204.18Z"/>
 | 
			
		||||
    <path android:fillColor="#f48fb1" android:pathData="M222.18,89c-28,24.79 -65.43,27.57 -102.41,21.79 -15.62,-2.44 -28.25,-11.48 -42.54,-4.72 -2.93,1.38 -6,4 -5.48,7.19 15.75,0.68 27.44,6.57 42.6,10.88 22.47,6.38 43.32,17.56 65.72,24.18s48,8.13 67.88,-4.07c2.46,-1.51 4.94,-3.39 5.87,-6.13a12.71,12.71 0,0 0,0.06 -6.31c-3.28,-18.77 -15,-33 -31.43,-42.81"/>
 | 
			
		||||
    <path android:fillColor="#673ab7" android:pathData="M108.057,137.999L141.83,124.422A3.105,3.11 68.099,0 1,145.874 126.143L145.874,126.143A3.105,3.11 68.099,0 1,144.146 130.184L110.373,143.761A3.105,3.11 68.099,0 1,106.329 142.04L106.329,142.04A3.105,3.11 68.099,0 1,108.057 137.999z"/>
 | 
			
		||||
    <path android:fillColor="#ffee58" android:pathData="M63.656,78.785L63.656,78.785A3.105,3.11 110.731,0 1,67.664 76.982L101.707,89.866A3.105,3.11 110.731,0 1,103.517 93.871L103.517,93.871A3.105,3.11 110.731,0 1,99.509 95.674L65.466,82.79A3.105,3.11 110.731,0 1,63.656 78.785z"/>
 | 
			
		||||
    <path android:fillColor="#80deea" android:pathData="M223.715,131.605L241.916,99.937A3.121,3.116 119.885,0 1,246.172 98.784L246.172,98.784A3.121,3.116 119.885,0 1,247.318 103.042L229.118,134.71A3.121,3.116 119.885,0 1,224.862 135.864L224.862,135.864A3.121,3.116 119.885,0 1,223.715 131.605z"/>
 | 
			
		||||
    <path android:fillColor="#8bc34a" android:pathData="M158.163,63.484L158.163,63.484A3.105,3.11 107.861,0 1,162.076 61.482L196.722,72.646A3.105,3.11 107.861,0 1,198.729 76.555L198.729,76.555A3.105,3.11 107.861,0 1,194.817 78.557L160.171,67.393A3.105,3.11 107.861,0 1,158.163 63.484z"/>
 | 
			
		||||
    <path android:fillColor="#673ab7" android:pathData="M181.372,45.493L201.621,15.246A3.11,3.105 123.799,0 1,205.931 14.389L205.931,14.389A3.11,3.105 123.799,0 1,206.781 18.7L186.532,48.948A3.11,3.105 123.799,0 1,182.222 49.805L182.222,49.805A3.11,3.105 123.799,0 1,181.372 45.493z"/>
 | 
			
		||||
    <path android:fillColor="#8bc34a" android:pathData="M132.014,205.938L152.263,175.691A3.11,3.105 123.799,0 1,156.574 174.834L156.574,174.834A3.11,3.105 123.799,0 1,157.424 179.145L137.175,209.393A3.11,3.105 123.799,0 1,132.864 210.25L132.864,210.25A3.11,3.105 123.799,0 1,132.014 205.938z"/>
 | 
			
		||||
    <path android:fillColor="#ffee58" android:pathData="M203.177,166.031L203.177,166.031A3.105,3.11 104.521,0 1,206.966 163.805L242.204,172.931A3.105,3.11 104.521,0 1,244.436 176.716L244.436,176.716A3.105,3.11 104.521,0 1,240.647 178.942L205.409,169.816A3.105,3.11 104.521,0 1,203.177 166.031z"/>
 | 
			
		||||
    <path android:fillColor="#80deea" android:pathData="M34.294,179.55L56.164,150.453A3.11,3.105 126.929,0 1,60.515 149.832L60.515,149.832A3.11,3.105 126.929,0 1,61.128 154.184L39.258,183.281A3.11,3.105 126.929,0 1,34.907 183.902L34.907,183.902A3.11,3.105 126.929,0 1,34.294 179.55z"/>
 | 
			
		||||
    <path android:fillColor="#f48fb1" android:pathData="M174.6,0.19c5.85,5.93 5.7,15.41 2.45,23.08a51.17,51.17 0,0 1,-16 20c-22,16.43 -49.79,24.94 -77.21,24.27 -1.61,0 -3.64,-0.43 -4,-2 1.47,-2.29 4.27,-3.29 6.89,-4 12.66,-3.58 26,-5.8 38.46,-10.07C148.61,43.36 169,33.86 174.42,0"/>
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										185
									
								
								app/src/main/res/drawable/ic_launcher_background.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,185 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:width="108dp"
 | 
			
		||||
    android:height="108dp"
 | 
			
		||||
    android:viewportWidth="108"
 | 
			
		||||
    android:viewportHeight="108">
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#3DDC84"
 | 
			
		||||
        android:pathData="M0,0h108v108h-108z" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M9,0L9,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,0L19,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M29,0L29,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M39,0L39,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M49,0L49,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M59,0L59,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M69,0L69,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M79,0L79,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M89,0L89,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M99,0L99,108"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,9L108,9"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,19L108,19"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,29L108,29"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,39L108,39"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,49L108,49"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,59L108,59"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,69L108,69"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,79L108,79"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,89L108,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M0,99L108,99"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,29L89,29"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,39L89,39"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,49L89,49"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,59L89,59"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,69L89,69"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M19,79L89,79"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M29,19L29,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M39,19L39,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M49,19L49,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M59,19L59,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M69,19L69,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
    <path
 | 
			
		||||
        android:fillColor="#00000000"
 | 
			
		||||
        android:pathData="M79,19L79,89"
 | 
			
		||||
        android:strokeWidth="0.8"
 | 
			
		||||
        android:strokeColor="#33FFFFFF" />
 | 
			
		||||
</vector>
 | 
			
		||||
							
								
								
									
										21
									
								
								app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <background android:drawable="@drawable/ic_launcher_background" />
 | 
			
		||||
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
 | 
			
		||||
    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
 | 
			
		||||
</adaptive-icon>
 | 
			
		||||
							
								
								
									
										21
									
								
								app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <background android:drawable="@drawable/ic_launcher_background" />
 | 
			
		||||
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
 | 
			
		||||
    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
 | 
			
		||||
</adaptive-icon>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_launcher.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 982 B  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_launcher.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 7.6 KiB  | 
							
								
								
									
										21
									
								
								app/src/main/res/values/dimens.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<resources>
 | 
			
		||||
    <dimen name="padding_small">8dp</dimen>
 | 
			
		||||
    <dimen name="padding_medium">16dp</dimen>
 | 
			
		||||
    <dimen name="thickness_divider">1dp</dimen>
 | 
			
		||||
</resources>
 | 
			
		||||
							
								
								
									
										46
									
								
								app/src/main/res/values/strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,46 @@
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<resources>
 | 
			
		||||
    <string name="app_name">Cupcake</string>
 | 
			
		||||
    <string name="order_cupcakes">Order Cupcakes</string>
 | 
			
		||||
    <string name="one_cupcake">One Cupcake</string>
 | 
			
		||||
    <string name="six_cupcakes">Six Cupcakes</string>
 | 
			
		||||
    <string name="twelve_cupcakes">Twelve Cupcakes</string>
 | 
			
		||||
    <string name="choose_flavor">Choose Flavor</string>
 | 
			
		||||
    <string name="vanilla">Vanilla</string>
 | 
			
		||||
    <string name="chocolate">Chocolate</string>
 | 
			
		||||
    <string name="red_velvet">Red Velvet</string>
 | 
			
		||||
    <string name="salted_caramel">Salted Caramel</string>
 | 
			
		||||
    <string name="coffee">Coffee</string>
 | 
			
		||||
    <string name="special_flavor">Special Flavor</string>
 | 
			
		||||
    <string name="cancel">Cancel</string>
 | 
			
		||||
    <string name="next">Next</string>
 | 
			
		||||
    <string name="choose_pickup_date">Choose Pickup Date</string>
 | 
			
		||||
    <string name="order_summary">Order Summary</string>
 | 
			
		||||
    <string name="send">Send Order to Another App</string>
 | 
			
		||||
    <string name="quantity">Quantity</string>
 | 
			
		||||
    <string name="flavor">Flavor</string>
 | 
			
		||||
    <string name="pickup_date">Pickup date</string>
 | 
			
		||||
    <string name="subtotal_price">Subtotal %s</string>
 | 
			
		||||
    <string name="total_price">Total %s</string>
 | 
			
		||||
    <string name="new_cupcake_order">New Cupcake Order</string>
 | 
			
		||||
    <string name="order_details">Quantity: %1$s \nFlavor: %2$s \nPickup date: %3$s \nTotal: %4$s \n\nThank you!</string>
 | 
			
		||||
    <string name="back_button">Back</string>
 | 
			
		||||
    <plurals name="cupcakes">
 | 
			
		||||
        <item quantity="one">%d cupcake</item>
 | 
			
		||||
        <item quantity="other">%d cupcakes</item>
 | 
			
		||||
    </plurals>
 | 
			
		||||
</resources>
 | 
			
		||||
							
								
								
									
										19
									
								
								app/src/main/res/values/themes.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,19 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
     Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
     Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
     you may not use this file except in compliance with the License.
 | 
			
		||||
     You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
          https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
     Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
     distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
     See the License for the specific language governing permissions and
 | 
			
		||||
     limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
<resources>
 | 
			
		||||
    <style name="Theme.Cupcake" parent="android:Theme.Material.Light.NoActionBar" />
 | 
			
		||||
</resources>
 | 
			
		||||
							
								
								
									
										26
									
								
								build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,26 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
 | 
			
		||||
buildscript {
 | 
			
		||||
    ext {
 | 
			
		||||
        lifecycle_version = "2.6.1"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
plugins {
 | 
			
		||||
    id 'com.android.application' version '8.0.1' apply false
 | 
			
		||||
    id 'com.android.library' version '8.0.1' apply false
 | 
			
		||||
    id 'org.jetbrains.kotlin.android' version '1.8.21' apply false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,23 @@
 | 
			
		||||
# Project-wide Gradle settings.
 | 
			
		||||
# IDE (e.g. Android Studio) users:
 | 
			
		||||
# Gradle settings configured through the IDE *will override*
 | 
			
		||||
# any settings specified in this file.
 | 
			
		||||
# For more details on how to configure your build environment visit
 | 
			
		||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
 | 
			
		||||
# Specifies the JVM arguments used for the daemon process.
 | 
			
		||||
# The setting is particularly useful for tweaking memory settings.
 | 
			
		||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
 | 
			
		||||
# When configured, Gradle will run in incubating parallel mode.
 | 
			
		||||
# This option should only be used with decoupled projects. More details, visit
 | 
			
		||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
 | 
			
		||||
# org.gradle.parallel=true
 | 
			
		||||
# AndroidX package structure to make it clearer which packages are bundled with the
 | 
			
		||||
# Android operating system, and which are packaged with your app's APK
 | 
			
		||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
 | 
			
		||||
android.useAndroidX=true
 | 
			
		||||
# Kotlin code style for this project: "official" or "obsolete":
 | 
			
		||||
kotlin.code.style=official
 | 
			
		||||
# Enables namespacing of each library's R class so that its R class includes only the
 | 
			
		||||
# resources declared in the library itself and none from the library's dependencies,
 | 
			
		||||
# thereby reducing the size of the R class for that library
 | 
			
		||||
android.nonTransitiveRClass=true
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,6 @@
 | 
			
		||||
#Sun Mar 19 17:30:22 PDT 2023
 | 
			
		||||
distributionBase=GRADLE_USER_HOME
 | 
			
		||||
distributionPath=wrapper/dists
 | 
			
		||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
 | 
			
		||||
zipStoreBase=GRADLE_USER_HOME
 | 
			
		||||
zipStorePath=wrapper/dists
 | 
			
		||||
							
								
								
									
										185
									
								
								gradlew
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,185 @@
 | 
			
		||||
#!/usr/bin/env sh
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2015 the original author or authors.
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
# Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
##############################################################################
 | 
			
		||||
##
 | 
			
		||||
##  Gradle start up script for UN*X
 | 
			
		||||
##
 | 
			
		||||
##############################################################################
 | 
			
		||||
 | 
			
		||||
# Attempt to set APP_HOME
 | 
			
		||||
# Resolve links: $0 may be a link
 | 
			
		||||
PRG="$0"
 | 
			
		||||
# Need this for relative symlinks.
 | 
			
		||||
while [ -h "$PRG" ] ; do
 | 
			
		||||
    ls=`ls -ld "$PRG"`
 | 
			
		||||
    link=`expr "$ls" : '.*-> \(.*\)$'`
 | 
			
		||||
    if expr "$link" : '/.*' > /dev/null; then
 | 
			
		||||
        PRG="$link"
 | 
			
		||||
    else
 | 
			
		||||
        PRG=`dirname "$PRG"`"/$link"
 | 
			
		||||
    fi
 | 
			
		||||
done
 | 
			
		||||
SAVED="`pwd`"
 | 
			
		||||
cd "`dirname \"$PRG\"`/" >/dev/null
 | 
			
		||||
APP_HOME="`pwd -P`"
 | 
			
		||||
cd "$SAVED" >/dev/null
 | 
			
		||||
 | 
			
		||||
APP_NAME="Gradle"
 | 
			
		||||
APP_BASE_NAME=`basename "$0"`
 | 
			
		||||
 | 
			
		||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 | 
			
		||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
 | 
			
		||||
 | 
			
		||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
 | 
			
		||||
MAX_FD="maximum"
 | 
			
		||||
 | 
			
		||||
warn () {
 | 
			
		||||
    echo "$*"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
die () {
 | 
			
		||||
    echo
 | 
			
		||||
    echo "$*"
 | 
			
		||||
    echo
 | 
			
		||||
    exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# OS specific support (must be 'true' or 'false').
 | 
			
		||||
cygwin=false
 | 
			
		||||
msys=false
 | 
			
		||||
darwin=false
 | 
			
		||||
nonstop=false
 | 
			
		||||
case "`uname`" in
 | 
			
		||||
  CYGWIN* )
 | 
			
		||||
    cygwin=true
 | 
			
		||||
    ;;
 | 
			
		||||
  Darwin* )
 | 
			
		||||
    darwin=true
 | 
			
		||||
    ;;
 | 
			
		||||
  MINGW* )
 | 
			
		||||
    msys=true
 | 
			
		||||
    ;;
 | 
			
		||||
  NONSTOP* )
 | 
			
		||||
    nonstop=true
 | 
			
		||||
    ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Determine the Java command to use to start the JVM.
 | 
			
		||||
if [ -n "$JAVA_HOME" ] ; then
 | 
			
		||||
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
 | 
			
		||||
        # IBM's JDK on AIX uses strange locations for the executables
 | 
			
		||||
        JAVACMD="$JAVA_HOME/jre/sh/java"
 | 
			
		||||
    else
 | 
			
		||||
        JAVACMD="$JAVA_HOME/bin/java"
 | 
			
		||||
    fi
 | 
			
		||||
    if [ ! -x "$JAVACMD" ] ; then
 | 
			
		||||
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
 | 
			
		||||
 | 
			
		||||
Please set the JAVA_HOME variable in your environment to match the
 | 
			
		||||
location of your Java installation."
 | 
			
		||||
    fi
 | 
			
		||||
else
 | 
			
		||||
    JAVACMD="java"
 | 
			
		||||
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 | 
			
		||||
 | 
			
		||||
Please set the JAVA_HOME variable in your environment to match the
 | 
			
		||||
location of your Java installation."
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Increase the maximum file descriptors if we can.
 | 
			
		||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
 | 
			
		||||
    MAX_FD_LIMIT=`ulimit -H -n`
 | 
			
		||||
    if [ $? -eq 0 ] ; then
 | 
			
		||||
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
 | 
			
		||||
            MAX_FD="$MAX_FD_LIMIT"
 | 
			
		||||
        fi
 | 
			
		||||
        ulimit -n $MAX_FD
 | 
			
		||||
        if [ $? -ne 0 ] ; then
 | 
			
		||||
            warn "Could not set maximum file descriptor limit: $MAX_FD"
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
 | 
			
		||||
    fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# For Darwin, add options to specify how the application appears in the dock
 | 
			
		||||
if $darwin; then
 | 
			
		||||
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# For Cygwin or MSYS, switch paths to Windows format before running java
 | 
			
		||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
 | 
			
		||||
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
 | 
			
		||||
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
 | 
			
		||||
 | 
			
		||||
    JAVACMD=`cygpath --unix "$JAVACMD"`
 | 
			
		||||
 | 
			
		||||
    # We build the pattern for arguments to be converted via cygpath
 | 
			
		||||
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
 | 
			
		||||
    SEP=""
 | 
			
		||||
    for dir in $ROOTDIRSRAW ; do
 | 
			
		||||
        ROOTDIRS="$ROOTDIRS$SEP$dir"
 | 
			
		||||
        SEP="|"
 | 
			
		||||
    done
 | 
			
		||||
    OURCYGPATTERN="(^($ROOTDIRS))"
 | 
			
		||||
    # Add a user-defined pattern to the cygpath arguments
 | 
			
		||||
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
 | 
			
		||||
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
 | 
			
		||||
    fi
 | 
			
		||||
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
 | 
			
		||||
    i=0
 | 
			
		||||
    for arg in "$@" ; do
 | 
			
		||||
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
 | 
			
		||||
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
 | 
			
		||||
 | 
			
		||||
        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
 | 
			
		||||
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
 | 
			
		||||
        else
 | 
			
		||||
            eval `echo args$i`="\"$arg\""
 | 
			
		||||
        fi
 | 
			
		||||
        i=`expr $i + 1`
 | 
			
		||||
    done
 | 
			
		||||
    case $i in
 | 
			
		||||
        0) set -- ;;
 | 
			
		||||
        1) set -- "$args0" ;;
 | 
			
		||||
        2) set -- "$args0" "$args1" ;;
 | 
			
		||||
        3) set -- "$args0" "$args1" "$args2" ;;
 | 
			
		||||
        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
 | 
			
		||||
        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
 | 
			
		||||
        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
 | 
			
		||||
        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
 | 
			
		||||
        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
 | 
			
		||||
        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
 | 
			
		||||
    esac
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Escape application args
 | 
			
		||||
save () {
 | 
			
		||||
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
 | 
			
		||||
    echo " "
 | 
			
		||||
}
 | 
			
		||||
APP_ARGS=`save "$@"`
 | 
			
		||||
 | 
			
		||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
 | 
			
		||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
 | 
			
		||||
 | 
			
		||||
exec "$JAVACMD" "$@"
 | 
			
		||||
							
								
								
									
										89
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,89 @@
 | 
			
		||||
@rem
 | 
			
		||||
@rem Copyright 2015 the original author or authors.
 | 
			
		||||
@rem
 | 
			
		||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
@rem you may not use this file except in compliance with the License.
 | 
			
		||||
@rem You may obtain a copy of the License at
 | 
			
		||||
@rem
 | 
			
		||||
@rem      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
@rem
 | 
			
		||||
@rem Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
@rem See the License for the specific language governing permissions and
 | 
			
		||||
@rem limitations under the License.
 | 
			
		||||
@rem
 | 
			
		||||
 | 
			
		||||
@if "%DEBUG%" == "" @echo off
 | 
			
		||||
@rem ##########################################################################
 | 
			
		||||
@rem
 | 
			
		||||
@rem  Gradle startup script for Windows
 | 
			
		||||
@rem
 | 
			
		||||
@rem ##########################################################################
 | 
			
		||||
 | 
			
		||||
@rem Set local scope for the variables with windows NT shell
 | 
			
		||||
if "%OS%"=="Windows_NT" setlocal
 | 
			
		||||
 | 
			
		||||
set DIRNAME=%~dp0
 | 
			
		||||
if "%DIRNAME%" == "" set DIRNAME=.
 | 
			
		||||
set APP_BASE_NAME=%~n0
 | 
			
		||||
set APP_HOME=%DIRNAME%
 | 
			
		||||
 | 
			
		||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
 | 
			
		||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
 | 
			
		||||
 | 
			
		||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 | 
			
		||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
 | 
			
		||||
 | 
			
		||||
@rem Find java.exe
 | 
			
		||||
if defined JAVA_HOME goto findJavaFromJavaHome
 | 
			
		||||
 | 
			
		||||
set JAVA_EXE=java.exe
 | 
			
		||||
%JAVA_EXE% -version >NUL 2>&1
 | 
			
		||||
if "%ERRORLEVEL%" == "0" goto execute
 | 
			
		||||
 | 
			
		||||
echo.
 | 
			
		||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 | 
			
		||||
echo.
 | 
			
		||||
echo Please set the JAVA_HOME variable in your environment to match the
 | 
			
		||||
echo location of your Java installation.
 | 
			
		||||
 | 
			
		||||
goto fail
 | 
			
		||||
 | 
			
		||||
:findJavaFromJavaHome
 | 
			
		||||
set JAVA_HOME=%JAVA_HOME:"=%
 | 
			
		||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
 | 
			
		||||
 | 
			
		||||
if exist "%JAVA_EXE%" goto execute
 | 
			
		||||
 | 
			
		||||
echo.
 | 
			
		||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
 | 
			
		||||
echo.
 | 
			
		||||
echo Please set the JAVA_HOME variable in your environment to match the
 | 
			
		||||
echo location of your Java installation.
 | 
			
		||||
 | 
			
		||||
goto fail
 | 
			
		||||
 | 
			
		||||
:execute
 | 
			
		||||
@rem Setup the command line
 | 
			
		||||
 | 
			
		||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@rem Execute Gradle
 | 
			
		||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
 | 
			
		||||
 | 
			
		||||
:end
 | 
			
		||||
@rem End local scope for the variables with windows NT shell
 | 
			
		||||
if "%ERRORLEVEL%"=="0" goto mainEnd
 | 
			
		||||
 | 
			
		||||
:fail
 | 
			
		||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
 | 
			
		||||
rem the _cmd.exe /c_ return code!
 | 
			
		||||
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
 | 
			
		||||
exit /b 1
 | 
			
		||||
 | 
			
		||||
:mainEnd
 | 
			
		||||
if "%OS%"=="Windows_NT" endlocal
 | 
			
		||||
 | 
			
		||||
:omega
 | 
			
		||||
							
								
								
									
										31
									
								
								settings.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,31 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2023 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      https://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
pluginManagement {
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        gradlePluginPortal()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
dependencyResolutionManagement {
 | 
			
		||||
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
rootProject.name = "Cupcake"
 | 
			
		||||
include ':app'
 | 
			
		||||