diff --git a/docs/generated-code/component-gen-code.md b/docs/generated-code/component-gen-code.md index 6aa23223..58f447db 100644 --- a/docs/generated-code/component-gen-code.md +++ b/docs/generated-code/component-gen-code.md @@ -1,7 +1,7 @@ --- -title: Components +title: Component Model slug: /generated-code/component-model -sidebar_position: 6 +sidebar_position: 5 --- # Generated Code: Components diff --git a/docs/generated-code/ff-app-state.md b/docs/generated-code/ff-app-state.md index a54c8137..74159da2 100644 --- a/docs/generated-code/ff-app-state.md +++ b/docs/generated-code/ff-app-state.md @@ -1,6 +1,6 @@ --- title: FFAppState -sidebar_position: 2 +sidebar_position: 4 --- # FFAppState diff --git a/docs/generated-code/pages-generated-code.md b/docs/generated-code/pages-generated-code.md index 7a607ece..0c1aa571 100644 --- a/docs/generated-code/pages-generated-code.md +++ b/docs/generated-code/pages-generated-code.md @@ -1,5 +1,5 @@ --- -title: Pages +title: Page Model slug: /generated-code/page-model sidebar_position: 5 --- diff --git a/docs/ff-concepts/state-management/generated-code.md b/docs/generated-code/state-mgmt-gen-code.md similarity index 58% rename from docs/ff-concepts/state-management/generated-code.md rename to docs/generated-code/state-mgmt-gen-code.md index c755e912..c8f20237 100644 --- a/docs/ff-concepts/state-management/generated-code.md +++ b/docs/generated-code/state-mgmt-gen-code.md @@ -1,20 +1,24 @@ --- -slug: /concepts/state-management/generated-code -title: Generated Code +slug: /generated-code/state-management +title: FlutterFlow State Management description: Learn about the state management used in FlutterFlow's generated code. tags: [Generated Code, Concepts, State Management] -toc_max_heading_level: 5 -sidebar_position: 2 +toc_max_heading_level: 4 +sidebar_position: 3 keywords: [FlutterFlow, Generated Code, State Management, Concepts] --- -# State Management +# FlutterFlow State Management + +:::warning[Correct topic?] +This document explains the generated code behind the state management approaches used in FlutterFlow. If you're looking for guidance on adding state variables in FlutterFlow, refer to the **[State Variables](../ff-concepts/state-management/state-variables.md)** documentation. +::: FlutterFlow manages state in several ways, depending on the scope. -Generally, state management is handled using the Provider package, which facilitates the provisioning of data models for components, pages, and the overall app state. +Generally, state management is handled using the [Provider](https://pub.dev/packages/provider) package, which facilitates the provisioning of data models for components, pages, and the overall app state. -![state-management.avif](../../../static/img/state-management.avif) +![state-management.avif](../../static/img/state-management.avif) ## Page & Component Models @@ -24,13 +28,13 @@ Additionally, they provide space for action blocks, which are a set of actions t ## Page State -[Variables](../../resources/ui/pages/page-lifecycle.md) used exclusively within a page — such as a text field validator or the value of a checkbox — are stored in the `Model` of each page. These variables can be accessed by other component children on the same page. For instance, on a page with a form, tapping a button in one component may need to access the value of a text field in a different component. +[Variables](../resources/ui/pages/page-lifecycle.md) used exclusively within a page — such as a text field validator or the value of a checkbox — are stored in the `Model` of each page. These variables can be accessed by other component children on the same page. For instance, on a page with a form, tapping a button in one component may need to access the value of a text field in a different component. Variables within a page are tracked through `StatefulWidget` and are encapsulated into that page’s Model. ## Component State -Similar to page state, [**Component State variables**](../../resources/ui/components/component-lifecycle.md) are accessible within the component where they are defined. Each component has a corresponding `Model` and `Widget` class. Variables may be passed in from their parent as parameters. Additionally, you can access component state values from its parent Page widget. +Similar to page state, [**Component State variables**](../resources/ui/components/component-lifecycle.md) are accessible within the component where they are defined. Each component has a corresponding `Model` and `Widget` class. Variables may be passed in from their parent as parameters. Additionally, you can access component state values from its parent Page widget. This accessibility is possible because the Model of a component is instantiated within the parent Page model. It utilizes the Provider method `context.read()`, which returns any existing model in the tree before instantiating a new one. Thus, any updates to the state in the component model will reflect in the parent’s instance of that component model. @@ -40,6 +44,13 @@ For example, if a page includes a component with a text field and later on the p It’s important to note that components cannot directly access variables of other components on the same page. However, you can pass a variable from ComponentA as a parameter to ComponentB in their parent Page. This ensures that ComponentB receives all updates from ComponentA as expected. +## App State + +:::info[FFAppState] +The generated code behind FlutterFlow's App State class is explained in the **[FFAppState](ff-app-state.md)** documentation. + +::: + ## Variables Variables required across multiple pages of the app, such as a username, should be added to the App State. Refer to `lib/app_state.dart`. @@ -50,9 +61,18 @@ On each page that requires access to app state variables, the method ```context. ## Persisting App State -When an app state variable is created, selecting the "Persisted" option enables FlutterFlow to save it on the device using the [shared_preferences package](https://pub.dev/packages/shared_preferences). This ensures the variable remains available even after the app is restarted, making it ideal for persisting settings such as login status or a user's choice between light and dark modes. +When an app state variable is created, selecting the "Persisted" option enables FlutterFlow to save it on the device using the [**Shared Preferences**](https://pub.dev/packages/shared_preferences) package. This ensures the variable remains available even after the app is restarted, making it ideal for persisting settings such as login status or a user's choice between light and dark modes. + +If the "**Secure Persisted Fields**" option is enabled in the app state settings, FlutterFlow utilizes the [**Flutter Secure Storage**](https://pub.dev/packages/flutter_secure_storage) package to encrypt the data. + +:::tip[Platform Differences] +If the platform is **Android**, then `flutter_secure_storage` stores data in [**`encryptedSharedPreference`**](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences), which are shared preferences that encrypt keys and values. It handles [**AES Encryption**](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) to generate a secret key encrypted with [**RSA**](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) and stored in [**KeyStore**](https://developer.android.com/reference/java/security/KeyStore). + +For the **iOS** platform, it uses the [**KeyChain**](https://developer.apple.com/documentation/security/keychain_services) which is an iOS-specific secure storage used to store and access cryptographic keys only in your app. + +In the case of the **Web**, it uses the [**Web Cryptography**](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) (Web Crypto) API. +::: -If the "Secure Persisted Fields" option is enabled in the app state settings, FlutterFlow utilizes the [flutter_secure_storage package](https://pub.dev/packages/flutter_secure_storage) to encrypt the data. This package leverages platform-specific implementations for data encryption, utilizing Keychain on iOS, KeyStore on Android, and libsecret on Linux. ## Global State diff --git a/docs/marketplace/creators-hub/submission-criteria.md b/docs/marketplace/creators-hub/submission-criteria.md index c80fc256..51c62d91 100644 --- a/docs/marketplace/creators-hub/submission-criteria.md +++ b/docs/marketplace/creators-hub/submission-criteria.md @@ -334,7 +334,7 @@ Building a solid app template goes beyond surface-level design. It's about creat - **Criteria:** Implement state management effectively to ensure data is updated and reflected correctly across your application. - **Why it Matters:** Proper state management is crucial for building responsive and dynamic Flutter apps. It helps prevent data inconsistencies, improves performance, and makes your code easier to maintain. - **What To Do:** - - **Choose the right state management scope:** FlutterFlow supports (1) [App State](../../resources/data-representation/app-state.md) (2) [Page State](../../resources/ui/pages/page-lifecycle.md#page-state) and (3) [Component State](../../ff-concepts/state-management/generated-code.md#component-state) variables. Familiarize yourself with these options and scope any state variables to where they are needed. For instance, do not use App State to control the value of a checkbox within a component. + - **Choose the right state management scope:** FlutterFlow supports (1) [App State](../../resources/data-representation/app-state.md) (2) [Page State](../../resources/ui/pages/page-lifecycle.md#page-state) and (3) [Component State](../../resources/ui/components/component-lifecycle.md#creating-a-component-state) variables. Familiarize yourself with these options and scope any state variables to where they are needed. For instance, do not use App State to control the value of a checkbox within a component. - **Rebuild efficiently:** Ensure changes to state rebuild only the necessary scope for efficiency. #### 5.10 Organized Widget Tree diff --git a/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md b/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md index 485f5e4e..b88148f4 100644 --- a/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md +++ b/docs/resources/control-flow/backend-logic/api/create-test-api-calls.md @@ -122,7 +122,7 @@ The PUT and PATCH API calls can be defined similarly; make sure you enter a vali You can create a group of API calls that share the same base URL. Grouping the API calls helps you add all request headers (e.g., auth token) at once, and they will be automatically added for all the API calls inside the group. :::warning -For [**private APIs**](rest-api.md#making-an-api-call-private), headers defined within the group will not be automatically included. You'll need to manually add headers for APIs marked as private. +For [**private APIs**](rest-api.md#private-api-calls), headers defined within the group will not be automatically included. You'll need to manually add headers for APIs marked as private. ::: To create the API Group: diff --git a/docs/resources/control-flow/backend-logic/api/imgs/private-cloud-func.png b/docs/resources/control-flow/backend-logic/api/imgs/private-cloud-func.png new file mode 100644 index 00000000..cc8984f9 Binary files /dev/null and b/docs/resources/control-flow/backend-logic/api/imgs/private-cloud-func.png differ diff --git a/docs/resources/control-flow/backend-logic/api/rest-api.md b/docs/resources/control-flow/backend-logic/api/rest-api.md index ced6bb43..649d0d86 100644 --- a/docs/resources/control-flow/backend-logic/api/rest-api.md +++ b/docs/resources/control-flow/backend-logic/api/rest-api.md @@ -639,16 +639,16 @@ To use a predefined JSON Path, first, select your API response. Then, set the ** You can make the API call private and change the proxy settings using advanced settings. -### Making an API call private +### Private API Calls Making an API call private is helpful if it uses tokens or secrets you don't want to expose in your app. Enabling this setting will route this API call securely via the Firebase Cloud Functions. -To make the API call private, open the **Advanced Settings** tab, turn on the **Make Private** toggle, Click **Save,** and then **Deploy APIs**. +![private-cloud-func.png](imgs/private-cloud-func.png) -Optionally, you can force a user to be authenticated via the Firebase authentication to make this API call. To do so, turn on the **Require Authentication** toggle. +To make an API Call Private, open the **Advanced Settings** tab, turn on the **Make Private** toggle, Click **Save,** and then **Deploy APIs**. +Optionally, you can force a user to be authenticated via the Firebase authentication to make this API call. To do so, turn on the **Require Authentication** toggle. -:::info Private APIs are deployed as [**Cloud Functions**](https://firebase.google.com/docs/functions) within your Firebase project. While deploying, you can configure the following options: @@ -659,7 +659,7 @@ Private APIs are deployed as [**Cloud Functions**](https://firebase.google.com/d **Note**: To minimize costs, you can set the **Min Instances** value to 0. For detailed pricing information, refer to the [**Cloud Functions Pricing page**](https://cloud.google.com/functions/pricing-overview). -::: +
Project Setup >

:::tip -For different [**development environments**](../../testing-deployment-publishing/development-environments/development-environments.md) (e.g., development vs. production), you can bind Library Values to [**environment values**](../../testing-deployment-publishing/development-environments/development-environments.md#use-environment-values). For instance, you could have two different Library Values for an API key, such as `DEV_OPENAI_API_KEY` and `PROD_OPENAI_API_KEY`, and bind them to the development and production environments to track API usage separately. +For different [**development environments**](../../testing-deployment-publishing/development-environments/development-environments.md) (e.g., development vs. production), you can bind Library Values to [**environment values**](../../testing-deployment-publishing/development-environments/development-environments.md#environment-values). For instance, you could have two different Library Values for an API key, such as `DEV_OPENAI_API_KEY` and `PROD_OPENAI_API_KEY`, and bind them to the development and production environments to track API usage separately. ::: ## Libraries with Firebase diff --git a/docs/testing-deployment-publishing/development-environments/development-environments.md b/docs/testing-deployment-publishing/development-environments/development-environments.md index 9fcedd63..e5a2b307 100644 --- a/docs/testing-deployment-publishing/development-environments/development-environments.md +++ b/docs/testing-deployment-publishing/development-environments/development-environments.md @@ -4,6 +4,7 @@ title: Development Environments description: Learn how to create and leverage development environments in FlutterFlow. tags: [Dev Environments, Backend, Testing] sidebar_position: 2 +toc_max_heading_level: 4 keywords: [Dev, Development, Environments, FlutterFlow, Backend] --- @@ -54,14 +55,15 @@ You can create and switch environments in the **Dev Environments** page in **App

-The selected environment is used to generate the proper app code when you run, test, deploy or export your app. The only things that change between environment are the [Firebase Project](#configuring-firebase-or-supabase-for-each-environment) or variables that are tied to [Environment Values](#use-environment-values) +The selected environment is used to generate the proper app code when you run, test, deploy or export your app. The only things that change between environment are the [Firebase Project](#configuring-firebase-or-supabase-for-each-environment) or variables that are tied to [Environment Values](#environment-values) -### Use Environment Values +### Environment Values Environment Values can be used to dynamically change parts of your app's code based on the environment that is being used. For example, in an e-commerce app, you might define an `apiUrl` Environment Value that points to different API URLs for Development, Staging, and Production. This allows you to test new features without affecting the live production environment, where real customer orders are processed. +#### Use Environment Value Let's see an example of creating and using `apiUrl`:

-:::info -After switching to an environment, FlutterFlow generates code specific to that environment, for any of the following interactions: +:::tip[Generated Code] +When you switch to an environment, FlutterFlow generates code specific to that environment, for any of the following interactions: - Test / Run mode sessions - Local Run - Code export - Deployment -You also may see different project errors depending on which environment you have selected. +You may also encounter different project errors depending on the selected environment. + +In the generated code, FlutterFlow creates two files: + +- `environment.json` – Stores the environment values defined by the user in FlutterFlow. +- `FFDevEnvironmentValues` class – A singleton class that holds a single instance of the `FFDevEnvironmentValues` object. It includes initialization logic and getters for accessing these environment values. They can also be referenced in your custom code resources. See **[Common Custom Code Examples](../../ff-concepts/adding-customization/common-examples.md)**. ::: +#### Private Environment Values + +You can mark environment values as private when they contain sensitive information that should not be exposed in the client-side code. **Private** environment values are not included in the generated code. + +Currently, the only way to use a private environment value is as a variable in a private API call. Since private API calls are routed through a Cloud Function, the variable value remains hidden from any client-side requests made by the app. + +:::tip[Generated Code] +For private environment values, the generated code does not include these values in the `environment.json` file, and no getter logic is created in the `FFDevEnvironmentValues` class. +::: + + ### Configuring Firebase or Supabase for each Environment A single FlutterFlow project can have **multiple environments**, each mapped to its **own Firebase or Supabase project**. This ensures that environments like `Development`, `Staging`, and `Production` remain independent, giving you better control over your app's data and behavior throughout different stages of development. @@ -159,6 +177,8 @@ It's recommended that you keep schemas consistent between the different Supabase + + ### FAQ
diff --git a/firebase.json b/firebase.json index 785a40e1..cb86d7da 100644 --- a/firebase.json +++ b/firebase.json @@ -2322,6 +2322,11 @@ "source": "/firebase-content-manager", "destination": "/integrations/database/cloud-firestore/firestore-content-manager/", "type": 301 + }, + { + "source": "/concepts/state-management/generated-code", + "destination": "/generated-code/state-management", + "type": 301 } ] }