Skip to content

Commit d44a7aa

Browse files
authored
Merge branch 'main' into fix/permission-ai-agent
2 parents 9a0f199 + 0183b5f commit d44a7aa

File tree

5 files changed

+859
-42
lines changed

5 files changed

+859
-42
lines changed

docs/ff-concepts/navigation-routing/deep-dynamic-linking.md

Lines changed: 134 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -698,22 +698,26 @@ To add it to a specific project, go to **Settings > Project Dependencies**, clic
698698
699699
### Branch Setup
700700
701-
You’ll need two values from your Branch dashboard:
701+
You’ll need three values from your Branch dashboard:
702702
703-
- **Branch Live Key** – your production API key from the Branch dashboard.
704-
- **Custom Domain** – your configured link domain (e.g., yourapp.app.link)
705-
This is the domain used to generate and handle smart links for your app.
703+
- **Branch Key**: Your production or test key from the Branch dashboard.
704+
705+
- **Custom Link Domain**: Your primary Branch link domain (e.g., yourapp.app.link). This is used to generate and handle smart links.
706+
707+
- **Alternate Link Domain**: An additional Branch domain (e.g., yourapp-alternate.app.link) that points to the same link data and behavior.
708+
This is recommended for ensuring better deliverability across platforms and channels, and must be included in your platform configuration.
706709
707710
We recommend storing these values in Environment Variables so you can:
708711
- Manage them per environment (e.g., dev vs prod Branch keys).
709712
- Easily assign them to the library’s configuration when adding it to a project.
710713
711714
**Adding Library Values**
712715
713-
When you add the Branch Deep Linking Library to your project, it will prompt you to provide three values:
716+
When you add the **Branch Deep Linking Library** to your project (ensure you are on +0.0.7 and above), it will prompt you to provide four values:
714717
715718
- `branchApiKey`
716-
- `branchHostUrl`
719+
- `branchLinkDomain`
720+
- `branchAlternateLinkDomain`
717721
- `isTestMode`
718722
719723
Use the environment variables you created to populate these values.
@@ -787,11 +791,12 @@ Open your `main.dart` file in FlutterFlow and add the `initBranch` custom action
787791
788792
To receive and act on deep link data, go to your **Entry Page** or **Logged-In Page** and add the `handleBranchDeeplink` action as the first action in the page flow.
789793
790-
This `handleBranchDeeplink` action listens for incoming Branch Deeplinks and handles routing logic. This action should be added to your Entry Page or Logged-In Page under the **onPageLoad** trigger. It initializes a stream listener that waits
791-
for Branch links to be opened (either deferred or direct).
794+
This `handleBranchDeeplink` action listens for incoming Branch Deeplinks and handles routing logic. This action should be added to your **Entry Page** or **Logged-In Page** under the **onPageLoad** trigger. It initializes a stream listener that waits for Branch links to be opened (either deferred or direct). Ensure this is the first action of your **on Page Load** action trigger.
795+
796+
**`onLinkOpened` Action Callback**
792797
793798
When a link is received, the `onLinkOpened` callback is triggered with
794-
the link data, allowing you to perform custom navigation or logic. You can perform your navigation logic in this action callback.
799+
the [**link data**](#linkdata-action-parameter), allowing you to perform custom navigation or logic. You can perform your navigation logic in this action callback.
795800
796801
<div style={{
797802
position: 'relative',
@@ -821,19 +826,56 @@ the link data, allowing you to perform custom navigation or logic. You can perfo
821826
822827
<p></p>
823828
824-
**`linkData` Action Parameter**
829+
#### `linkData` Action Parameter
830+
831+
The `handleBranchDeeplink` action receives a `linkData` object that contains all the metadata sent with the link. The `linkData` parameter is a Map containing useful information from the Branch link.
832+
833+
In the Dreambrush app example, we get the following link data:
834+
835+
```jsx
836+
{
837+
"$og_title": "Check out my Ai Image on DreamBrush!",
838+
"$publicly_indexable": true,
839+
"imageId": "QiC94EaGNoonEKzln07A",
840+
"~creation_source": 4,
841+
"$og_description": "This image was created with DreamBrush app. You can check it out here.",
842+
"+click_timestamp": 1750099254,
843+
"$match_duration": 100000,
844+
"~feature": "Ai Image Creation",
845+
"$tags[0]": "generation",
846+
"+match_guaranteed": true,
847+
"$alias": "",
848+
"$canonical_identifier": "/imageDetails/QiC94EaGNoonEKzln07A",
849+
"+clicked_branch_link": true,
850+
"~id": "1461141612502859827",
851+
"+is_first_session": false,
852+
"~campaign": "Image Generation",
853+
"~referring_link": "https://dreambrush.app.link/DZ9liDTc6Tb",
854+
"~channel": "Share"
855+
}
856+
857+
```
858+
859+
:::warning[Link Structure]
860+
Your link data might not look *exactly* like the example shown above. However, it will follow a **similar structure** with comparable keys and values.
861+
:::
825862
826-
The `handleBranchDeeplink` action receives a `linkData` object that contains all the metadata sent with the link. The `linkData` parameter is a Map containing useful information from the Branch link:
863+
Some of the important keys we should know about:
827864
828-
- **`$canonical_identifier`:** The original route path used when the link was generated (e.g., `/imageDetails/:id`).
865+
- **`$canonical_identifier`:** The original route path used when the link was generated (e.g., `/imageDetails/:id`). You can explicitly set this value when creating a link through the **[Generate Link](#generate-link-custom-action)** action. If you don’t set it, Branch will infer it based on the link's destination or content metadata.
829866
830867
- **`~referring_link`:** The full Branch URL that was clicked.
831868
832-
- **`page`:** The target page or screen the link is meant to open (e.g., paywall). This is a custom parameter set by the user when generating the link.
869+
- **`$og_title`:** This is the headline that will appear in the link preview. This is set by the user through the **[Generate Link](#generate-link-custom-action)** action.
870+
- **`$og_description`:** This is the description text shown below the title in the link preview. This is set by the user through the **[Generate Link](#generate-link-custom-action)** action.
871+
872+
- **`~channel`**, **`~feature`**, **`~campaign`** and **`$tags[0]`** are part of Branch’s user-defined analytics and attribution metadata. These fields are explicitly set by users when creating a link (e.g., via the **[Generate Link](#generate-link-custom-action)** action), and they help organize and analyze your link performance across platforms and campaigns.
833873
834-
- Any custom parameters added during link creation (e.g., `campaign`, `productId`, `referrer`, etc.). Ensure the key and value is both `String` and `String`.
874+
- **`page`:** This is a suggested custom key that can be set by the user when generating the link. It typically defines the target page or screen the app should navigate to when the link is opened (e.g., "paywall", "productPage", "onboardingStep2"). While not a reserved Branch key, it's a commonly used naming convention for handling deep links and routing logic within the app.
835875
836-
This lets you write flexible, conditional navigation logic based on what was shared.
876+
- Any other custom parameters added during link creation (e.g., `productId`, `referrer`, etc.). Ensure the key and value are both `String`.
877+
878+
This lets you write flexible, conditional navigation logic based on what was shared. For example, in the following example, we can even show a bottom sheet based on the page value.
837879
838880
839881
<div style={{
@@ -864,18 +906,19 @@ This lets you write flexible, conditional navigation logic based on what was sha
864906
865907
<p></p>
866908
867-
:::tip
868-
Keep **"Allow Navigate Back"** checked when navigating from the Home Page to ensure it stays in the stack. This is applicable to any navigation from the Home Page, not limited to deeplinking navigation logic.
869-
This allows the user to return to the Home Page at any time and ensures that deep link logic defined there continues to work.
870-
:::
871-
872909
873910
Use the link data from this callback to:
874911
- Navigate to a page.
875912
- Show a bottom sheet.
876913
- Load content from Firestore using a referenced ID.
877914
915+
#### Using Global Context to Navigate
916+
917+
In certain app structures, especially when the home page is removed from the navigation stack early, standard navigation using the local context may fail. To ensure deep linking and routing continue to work reliably in these scenarios, you can override the local context with the global navigator context.
878918
919+
This approach ensures that navigation logic is not tied to the widget hierarchy at the time of execution, making it more robust and flexible.
920+
921+
See a **[detailed example](#dreambrush-example)** using the DreamBrush app.
879922
880923
881924
:::danger[Testing Deeplinks]
@@ -917,30 +960,34 @@ Incorrect structure may cause the Link Generation action to fail silently.
917960
918961
These functions help you safely work with deep link data, extract values, and conditionally navigate based on link metadata.
919962
920-
- **`isTargetingPage(linkData, targetPage)`** - Checks whether the page value in the link data matches a specific screen name. The `page` parameter is set by the user when generating the link from Branch dashboard or FlutterFlow.
963+
- **`isTargetingPage(linkData, targetPage)`** - Checks whether the page value in the link data matches a specific screen name. The `page` parameter is set by the user when generating the link from Branch dashboard or FlutterFlow. For example, if the target page value in your deep link is "paywall", you can use this function to check for this value and navigate accordingly.
964+
965+
- **`getCanonicalIdentifierFromLink(linkData)`**: Helper function that returns the canonical path (e.g., `/imageDetails/abc123`) that was originally attached to the smart link. Useful for extracting the base route or content reference associated with the shared link.
921966
922-
- **`getCanonicalIdentifierFromLink(linkData)`** - Returns the canonical path (e.g., `/imageDetails/abc123`) that was originally attached to the smart link. Useful for extracting the base route or content reference associated with the shared link.
967+
- **`getReferringLinkFromLink(linkData)`**: Helper function that retrieves the full Branch smart link URL from the data (typically under the `~referring_link` key). Useful for tracking, analytics, or verifying the source of the link.
923968
924-
- **`getReferringLinkFromLink(linkData)`** - Retrieves the full Branch smart link URL from the data (typically under the `~referring_link` key). Useful for tracking, analytics, or verifying the source of the link.
969+
- **`getLastPathSegmentFromMap(linkData, key)`**: Extracts the last path segment (e.g., `abc123`) from a URI stored inside a link data field (e.g., `/imageDetails/abc123`). This is especially useful when your deep link contains a structured path, like `/imageDetails/abc123` and you want to retrieve just the ID (`abc123`).
925970
926-
- **`getLastPathSegmentFromMap(linkData, key)`** - Extracts the last path segment (e.g., `abc123`) from a URI stored inside a link data field (e.g., `/imageDetails/abc123`). Useful for extracting the ID from a link.
971+
- **`getLinkValue(linkData, key)`**: Safely retrieves any single value from the link data Map. Returns null if not found. (e.g., retrieving `showPromo` attribute value from the `linkData`).
927972
928-
- **`getLinkValue(linkData, key)`** - Safely retrieves any single value from the link data Map. Returns null if not found. (e.g., retrieving `showPromo` attribute value from the `linkData`).
973+
:::warning
974+
If you're trying to retrieve default Branch keys like `~channel` or `$canonical_identifier`, make sure to include the special character (e.g., `~` or `$`) as part of the key string.
975+
:::
929976
930-
- **`createLinkProperties(...)`** - Returns a Branch Link Properties map used when generating a smart link. You can define values like: feature, campaign, stage, channel, alias or tags or custom fallback URLs. Useful for organizing and tracking generated links for marketing or referrals.
977+
- **`createLinkProperties(...)`**: Returns a Branch Link Properties map used when generating a smart link. You can define values like: feature, campaign, stage, channel, alias or tags or custom fallback URLs. Useful for organizing and tracking generated links for marketing or referrals.
931978
932979
933980
934-
### DreamBrush Link Generation Example
981+
### DreamBrush Example
935982
936-
In the DreamBrush app, we can use `generateLink` after a user finishes generating an image.
937-
The link could include:
938-
- **page**: Current Page Route that is `/imageDetails/:imageRef`.
983+
In the DreamBrush app, we can use `generateLink` after a user finishes generating an image. The link could include:
984+
- **canonicalIdentifier**: Current Page Route that is `/imageDetails/:imageRef`.
985+
- **page**: Target page name `imageDetails`.
939986
- **title**: "Check out my AI image!"
940987
941988
This link can then be shared via WhatsApp, email, or social media — and when clicked, it brings the recipient directly to that content inside the app.
942989
943-
Here's a quick example of generating a Branch link from a page that uses a Firebase Document ID as a route parameter.
990+
Here's a quick example of generating a Branch link from a page that uses a **Firebase Document ID** as a route parameter.
944991
945992
<div style={{
946993
position: 'relative',
@@ -999,21 +1046,72 @@ Now in your `handleBranchDeeplink` action callback, add the additional logic to
9991046
</iframe>
10001047
</div>
10011048
1049+
<p>
1050+
</p>
1051+
1052+
To demonstrate how to use the global context for navigation, add a new **Execute Custom Code** Action just before the **Navigate To** Action, and insert the following code.
1053+
1054+
```jsx
1055+
final context = appNavigatorKey.currentContext!;
1056+
```
1057+
1058+
This ensures that the navigation logic uses the global navigator context, which is essential if your app structure removes the home page early in the lifecycle. In such cases, relying on a local context may cause deep linking to fail—using a global context guarantees that navigation still works reliably.
1059+
1060+
:::warning[Paid Plans]
1061+
Note: The **Execute Custom Code** Action is available only on paid plans.
1062+
:::
1063+
1064+
<div style={{
1065+
position: 'relative',
1066+
paddingBottom: 'calc(56.67989417989418% + 41px)', // Keeps the aspect ratio and additional padding
1067+
height: 0,
1068+
width: '100%'
1069+
}}>
1070+
<iframe
1071+
src="https://demo.arcade.software/90ZeqJ3Zp0UQo1H0cdl8?embed&show_copy_link=true"
1072+
title=""
1073+
style={{
1074+
position: 'absolute',
1075+
top: 0,
1076+
left: 0,
1077+
width: '100%',
1078+
height: '100%',
1079+
colorScheme: 'light'
1080+
}}
1081+
frameborder="0"
1082+
loading="lazy"
1083+
webkitAllowFullScreen
1084+
mozAllowFullScreen
1085+
allowFullScreen
1086+
allow="clipboard-write">
1087+
</iframe>
1088+
</div>
1089+
10021090
10031091
### FAQs
10041092
10051093
<details>
10061094
<summary>Why isn't my deep link working when I navigate to another page from the home page?</summary>
10071095
1008-
It's likely because you're navigating in a way that removes the Home Page from the stack for example, disabling "**Allow Navigate Back**" in the Navigate Actions.
1096+
This often happens because the Home Page gets removed from the navigation stack, especially when **Allow Navigate Back** is disabled in the **Navigate To** Action.
1097+
1098+
Since the deep link handler is typically defined on the Home Page, it gets disposed once the page is removed, causing deep links to stop working when triggered later.
1099+
1100+
✅ Preferred Solution: **Use Global Context for Navigation**
1101+
1102+
Instead of relying on the Home Page's presence to handle deep links, configure your navigation logic to use the global navigator context. This ensures navigation will work even if the Home Page has been removed from the stack.
1103+
1104+
You can do this by adding an **Execute Custom Code** Action before the **Navigate To** Action.
1105+
1106+
See the **[complete example](#using-global-context-to-navigate)**.
10091107
1010-
Since the deep link handler is defined on the Home Page, it gets disposed and can’t respond when a deep link is triggered.
1108+
✅ Alternative (but limited) Solution: **Keep the Home Page in Stack**
10111109
1012-
✅ Solution:
1110+
If you're not using global context, you can prevent this issue by keeping the Home Page in memory:
10131111
1014-
Keep the Home Page in the stack by enabling "**Allow Navigate Back**" on any navigation actions from your home page (not limited to navigation logic in onLinkOpened action callback).
1112+
Enable "Allow Navigate Back" on any navigation actions from your Home Page, even if the navigation isn't triggered from deep links directly.
10151113
1016-
This ensures the Home Page stays active and can continue handling deep links.
1114+
This keeps the Home Page alive so it can continue listening for deep link events.
10171115
10181116
</details>
10191117

docs/ff-integrations/payments/stripe.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Integrating the Stripe Payments in your app comprises the following steps:
5858
4. [Testing](#4-testing)
5959
5. [Releasing to production](#5-releasing-to-production)
6060

61-
### 1. Setup Stripe payment
61+
### 1. Setup Stripe Payment
6262

6363
Setting up the Stripe payment includes acquiring the keys from your Stripe account and adding them to FlutterFlow.
6464

@@ -76,7 +76,7 @@ Follow the steps below to set up payment using Stripe:
7676
6. Copy the **Publishable Key** and **Secret Key** from the Stripe API keys page and paste them into the respective fields inside FlutterFlow. If you are using Stripe in test mode, make sure you paste them inside the **Test Credentials** section.
7777
7. Under the **Additional Settings**, you need to specify the following:
7878
1. **Merchant Display Name** (*Required*): Enter a name for the merchant (you) that the user will see while performing the payment.
79-
2. **Merchant Country Code** (*Required*): Enter your country code. This must be the 3-digit ISO country code, such as USA, IND, and NGA.
79+
2. **Merchant Country Code** (*Required*): Enter your country code. This must be the 2 digit ISO country code, such as US, IN, and AU.
8080
3. **Apple Merchant ID** (*Optional*): You need to enter this if you want to accept payments through Apple Pay as well. The instructions for using Apple Pay are in [this section](#2-apple-pay-setup-optional).
8181
8. Click **Deploy**.
8282

@@ -86,7 +86,7 @@ Follow the steps below to set up payment using Stripe:
8686
height: 0,
8787
width: '100%'}}>
8888
<iframe
89-
src="https://www.loom.com/embed/0e4ba1f7f055433e96a7fa6cede2c127?sid=400ef912-1580-44ad-81a9-25051bed0256"
89+
src="https://demo.arcade.software/PcikYUtB8cSug9CyUAOv?embed&show_copy_link=true"
9090
title=""
9191
style={{
9292
position: 'absolute',
@@ -108,7 +108,7 @@ Follow the steps below to set up payment using Stripe:
108108

109109
This would deploy the Stripe payment service as a Firebase Cloud Function. Now, you are ready to trigger payments inside your app.
110110

111-
### 2. Apple Pay setup (optional)
111+
### 2. Apple Pay Setup (optional)
112112

113113
Setting up Apple Pay comprises the following steps:
114114

@@ -185,7 +185,7 @@ To add Apple Merchant ID in FlutterFlow:
185185

186186
![Adding Apple Merchant ID in FlutterFlow](imgs/adding-apple-merchant-id.png)
187187

188-
### 3. Trigger Stripe payment [Action]
188+
### 3. Trigger Stripe Payment [Action]
189189

190190
In order to initiate a payment using Stripe, you have to use the **Stripe Payment** action.
191191

@@ -244,7 +244,7 @@ You can test Stripe payments on mobile and the Web before deployment. To do that
244244
4. [Download](../../testing-deployment-publishing/exporting-code/ff-cli.md) and [run](../../testing-deployment-publishing/running-your-app/run-your-app.md) your project..
245245
5. To test the purchase, you can use any of these [basic test card numbers](https://stripe.com/docs/testing#cards).
246246

247-
### 5. Releasing to production
247+
### 5. Releasing to Production
248248

249249
Before you release the app to production, complete the following steps:
250250

docs/resources/projects/libraries.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,14 @@ We're working on Library Values, which will allow users to set specific values w
430430
Projects can import libraries that themselves have imported other Libraries as dependencies. However, if the project and the library share the same dependency, the version must match exactly to avoid conflicts.
431431
</p>
432432
</details>
433+
434+
<details>
435+
<summary>Why do I get collision errors when importing a duplicated project as a library?</summary>
436+
<p>
437+
When you duplicate a project and publish it as a library, the unique identifiers (keys) for components and other resources are not automatically changed. If you then import this library back into the original project, it causes key collisions between the original and duplicated resources.
438+
439+
To help with this, FlutterFlow shows a dialog that offers to automatically delete the original resources in your base project and update all references to point to the library versions.
440+
441+
If you prefer to resolve this manually, you can duplicate individual components within the library after importing, this will generate new keys and avoid the collision.
442+
</p>
443+
</details>

0 commit comments

Comments
 (0)