diff --git a/docs/ff-concepts/file-handling/audio/_category_.json b/docs/ff-concepts/file-handling/audio/_category_.json
deleted file mode 100644
index 23edcfe2..00000000
--- a/docs/ff-concepts/file-handling/audio/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "Audio",
- "position": 0
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/audio/audio-player.md b/docs/ff-concepts/file-handling/audio/audio-player.md
deleted file mode 100644
index f5645ca4..00000000
--- a/docs/ff-concepts/file-handling/audio/audio-player.md
+++ /dev/null
@@ -1,194 +0,0 @@
----
-title: AudioPlayer
-slug: /concepts/file-handling/audio-player
-sidebar_position: 0
-tags: [Media, Widget]
-keywords: [Media, AudioPlayer, Play Audio File]
----
-
-# AudioPlayer
-
-The AudioPlayer widget plays audio from uploaded assets or the URL link.
-
-## Adding AudioPlayer Widget
-
-Here's how you can add the AudioPlayer widget to your project:
-
-1. Drag the **AudioPlayer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Options** section.
-3. Find the **Title** property and enter the value to display the audio title. You can also set this from the variable, such as the app state variable, API response variable, Firestore document, and more. To do so, click on the **Set from Variable**.
-4. Find the **Path** property and enter the **URL** for the new audio file.
-5. By default, the audio stops when you move to another page using the **Pause on Forward Navigation** property.
-6. When an app goes in the background while the audio player is running, you can control the audio player's behavior using the **Play in Background** property, which has following options:
- 1. **Enabled**: This keeps the audio player running.
- 2. **Disabled, restore on foreground**: This pauses the audio player and starts playing again as soon as the app is visible.
- 3. **Disabled, pause**: This stops the audio player as soon as the app goes in the background.
-
-:::info
-By default, every AudioPlayer widget added to the project will play a sample audio file from a network URL.
-:::
-
-
-
-
-
-
-## Use Audio from assets
-
-By default, the widget is set to play audio from the internet. However, you can change this to use the audio uploaded directly to your app.
-
-Here's how you can change the audio type:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Options** section.
-3. Find the **Audio Type** dropdown and select **Asset**.
-4. Now, find the **Asset Audio** property, click the **Upload Audio** button, select the audio and upload it.
-
-
-
-
-
-
-:::info
-Once you upload the audio, you can use it throughout your app. You can manage your uploaded audio files with the Project Media Asset Manager.
-:::
-
-To use the uploaded audio:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Options** section.
-3. Find the **Audio Type** dropdown and select **Asset**.
-4. Click on **No asset select** (inside the dropdown) and choose the audio.
-
-
-
-
-
-
-
-## Customization
-
-You can customize the appearance of this widget using the various properties available under the properties panel.
-
-### Changing colors
-
-To change the audio tile colors:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Player Properties** section.
-3. To change the background color of the tile, Find the **Fill Color** property click on the box next to the already selected color, select the color, and then click **Use Color** or click on an already selected color and enter a Hex Code directly. You can also choose the color by clicking the **Palette** and **Simple** button.
-4. Similarly, you can change the **Playback Button Color** (play and pause button) and **Active Track Color** (the bar color that shows the progress of the currently playing audio).
-
-### Changing elevation
-
-To change the elevation (depth or Z-axis) of the audio tile:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Audio Player Properties** section.
-3. Find the **Elevation** input box and enter the value to see the drop shadow effect below the badge. The Higher value sets the bigger size of the shadow, whereas the 0 value removes the shadow.
-
-
-
-
-
-
-### Styling title text
-
-To change the title text style:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Title Text Style** section.
-3. Find the **Theme Text Style** property and change the style as per instructions [here](../../../resources/ui/widgets/basic-widgets/text.md#common-text-styling-properties).
-
-
-### Styling playback duration text
-
-To change the playback duration text style:
-
-1. Select the **AudioPlayer** widget from the widget tree or the canvas area.
-2. Move to the properties panel (on the right side of your screen) and scroll down to the **Playback Duration Text Style** section.
-3. Find the **Theme Text Style** property and change the style as per instructions [here](../../../resources/ui/widgets/basic-widgets/text.md#common-text-styling-properties).
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/audio/audio-recroding.md b/docs/ff-concepts/file-handling/audio/audio-recroding.md
deleted file mode 100644
index bcf959c6..00000000
--- a/docs/ff-concepts/file-handling/audio/audio-recroding.md
+++ /dev/null
@@ -1,165 +0,0 @@
----
-title: Audio Recording
-slug: /concepts/file-handling/audio-recording
-sidebar_position: 1
-tags: [Media, Action]
-keywords: [Media, Audio Recording, Action, File Handling]
----
-
-# Audio Recording
-
-This action allows users to record audio. Using this action, you can add functionalities like recording voice notes in a note-taking app or practicing pronunciation in a language app.
-
-
-
-
-
-
-## Types of audio recording action
-
-Following are the types of audio recording actions you can trigger:
-
-1. [**Start Audio Recording**](#start-audio-recording-action): This starts the recording. It also provides a name to the recording, which you can use later to stop the recording using the "Stop Audio Recording" **action*.*
-2. [**Stop Audio Recording**](#stop-audio-recording-action): This halts the ongoing recording using the name from the "Start Audio Recording" action. To capture and play the recorded audio, make sure to specify the *Action Output Variable Name*, which can be used with the audio player.
-
-## Start Audio Recording [Action]
-
-Follow the steps below to start the recording:
-
-1. Select the widget (e.g., Button, Page, etc.) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-3. Click on the **+ Add Action**.
-4. First, [request permission](../../../resources/projects/settings/project-setup.md#request-permission-action) for the microphone.
-5. Inside the **TRUE** section, add the **Start Audio Recording** (under *Utilities*) action.
-6. By default, the **Name** is set to any random string. However, you can change it to any friendly name.
-7. Optional: After starting recording, you might want to update the state variables to reflect changes on UI. For instance, you can enable/disable buttons or start recording animations to provide a visual cue of the ongoing process. This step allows you to enhance the user experience and provide real-time feedback during the recording.
-
-
-
-
-
-
-## Stop Audio Recording [Action]
-
-Follow the steps below to stop the recording:
-
-1. Select the widget (e.g., Button, Page, etc.) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-3. Click on the **+ Add Action**.
-4. Search and select the **Stop Audio Recording** (under *Utilities*) action.
-5. Choose the **Recorder Name** from the dropdown. This will be the name you provided in the "Start Audio Recording" action.
-6. Specify the **Action Output Variable Name**. This will store the actual audio recording, which you can use with any audio player. It stores recording in an **Audio Path** data type.
-7. To upload the audio recording to Firebase or Supabase, you can use the [Upload file](../upload-save-file.md) action. When you add this action:
- 1. Set the **Upload Type** to the preferred one.
- 2. Set **File Type** to **Uploaded File** because the *Stop Audio Recording* action internally stores recorded audio bytes (inside widget state).
- 3. Set the **File to Upload** to **Widget State > [action_output_variable_name]Bytes**.
-8. For uploading via API, *you don't need to add the Upload file action*. Just directly add the [**API call**](../../../resources/control-flow/backend-logic/api/rest-api.md) and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. You can pass the audio recording via **Widget State > [action_output_variable_name]Bytes** in the API variable. See how to [configure an API for the multipart request body](../../../resources/control-flow/backend-logic/api/rest-api.md#multipart-format).
-9. Optional: After stopping the recording, you might want to update the state variables to reflect changes on the UI. For instance, you can enable/disable buttons or stop recording animations.
-
-:::tip
-It's always a good idea to have a fail-safe mechanism to ensure recordings are properly stopped, even if the user forgets to do so manually. For instance, you can trigger this action when the user closes the app without explicitly stopping it.
-:::
-
-
-
-
-
-
-## Playing audio recording
-
-After you have stopped the recording, you can simply provide the *Action Output Variable Name* to the [Audio Player](audio-player.md) widget to start playing the recorded audio.
-
-:::warning
-Currently, recording audio isn't supported in Run or Test modes due to certain limitations. However, for Android and iOS platforms, you can test by downloading the code and following the instructions provided [here](../../../testing-deployment-publishing/exporting-code/ff-cli.md).
-:::
-
-Here's how you do it.
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/audio/play-stop-sound.md b/docs/ff-concepts/file-handling/audio/play-stop-sound.md
deleted file mode 100644
index b9cbc8e5..00000000
--- a/docs/ff-concepts/file-handling/audio/play-stop-sound.md
+++ /dev/null
@@ -1,78 +0,0 @@
----
-title: Play / Stop Sound
-slug: /concepts/file-handling/play-stop-sound
-sidebar_position: 2
-tags: [Media, Action]
-keywords: [Media, Play Sound, Stop Sound, Action]
----
-# Play / Stop Sound
-The Play and Stop Sound actions allow you to enhance your app with audio effects.
-
-## Play Sound
-
-Using this action, you play a sound that notifies users about the action they have taken—for example, playing a sound after refreshing a list or sending a message.
-
-:::tip
-It is advisable to use this action only for short audio. To play the more extended audio, consider adding the [**AudioPlayer**](audio-player.md) widget.
-:::
-
-### Adding Play Sound [Action]
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the properties panel, If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile (inside *Action Flow Editor*) and select **Add Action**.
-3. Search and select the **Play Sound** (under *Alerts/Notifications*) action.
-4. By default, this action will be given a random **Name** so it can be stopped by the [Stop Sound](#adding-stop-sound-action) action.
-5. Find the **Audio Type** dropdown and select **Network** or **Asset**.
-6. If you choose *Network*:
- 1. Inside the **Network Path** section,
- 1. To set the static audio, select the **Value Source > Specific** **Value** and enter the **Value** as a URL that will play the sound.
- 2. To set the dynamic audio, select the **Value Source > From Variable** > click **UNSET** and set the URL from a variable.
-7. If you choose *Asset,* click the **Upload Audio** button, select the sound and upload it.
-8. You can also control the sound volume using the **Volume** slider. It ranges from 0.0 to 1.0, where 0 is mute and 1 is full volume.
-9. By default, this action is 'non-blocking'**,** meaning it will trigger the following/next action (if any) as soon as this one is triggered. If you want to wait until the sound playing is finished before triggering any further action, enable **Await Playback** option.
-
-
-
-
-
-
-## Stop sound
-
-Using this action, you can stop a sound that is currently playing, which was started by the [Play Sound](#play-sound) action. For example, If your app is playing any sound effects, you may need to stop them when the app is paused or stopped.
-
-:::info
-This action only works if you have added a [**Play Sound**](#adding-play-sound-action) action on a page.
-:::
-
-### Adding Stop Sound [Action]
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the properties panel (the right menu), If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile (inside *Action Flow Editor*) and select **Add Action**.
-3. Search and select the **Stop Sound** (under *Alerts/Notifications*) action, and then choose the sound *Name* that you want to stop.
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/clear-delete-media.md b/docs/ff-concepts/file-handling/clear-delete-media.md
index 15438d4e..245b67e2 100644
--- a/docs/ff-concepts/file-handling/clear-delete-media.md
+++ b/docs/ff-concepts/file-handling/clear-delete-media.md
@@ -1,125 +1,34 @@
---
-title: Clear or Delete Media
slug: /concepts/file-handling/clear-delete-media
-sidebar_position: 7
-tags: [Media, Action]
-keywords: [Media, Clear Data, Delete Data Firebase Storage, Supabase Storage]
+title: Clear or Delete Media
+description: Learn how to add clear and delete file actions into your FlutterFlow app.
+sidebar_position: 4
+tags: [Media Files, Clear Delete Data]
+keywords: [Media Files, Clear Data, Delete Data, Firebase Storage, Supabase Storage]
---
# Clear or Delete Media
-The Clear and Delete Media actions provide essential functionalities for managing media files efficiently.
-
-## Clear Uploaded Data
+The **Clear** and **Delete** **Media** actions provide essential functionalities for managing media files efficiently.
-By utilizing this action, you can clear the *Uploaded File URL*. This functionality is handy when you want to offer users a straightforward method to remove any uploaded media, such as images or recordings, by providing them with an explicit option to do so.
+## Clear Uploaded Data [Action]
-
-
-
-
+When users upload media files, these files are first stored in a local state variable, i.e., *Uploaded File URL* for immediate access and display. This action is helpful when you want to offer users a straightforward method to remove any uploaded media, such as images or recordings.
:::info
-Before you use this action, you must have the [**Upload Data**](upload-save-media.md) action already added.
-:::
-
-### Adding Clear Uploaded Data action
-
-Follow the steps below to add this type of action to any widget:
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **+ Add Action**.
-3. Search and select the **Clear Uploaded Data** (under *Utilities*) **> [Name of uploaded data]** (given in the [Upload Data](upload-save-media.md)) action.
+For this action to work, the [**Upload or Save Media**](uploading-files.md#upload-or-save-media-action) action must already be added to the actions workflow.
-
-
-## Delete Data
-
-Using this action, you can delete the uploaded media, such as photos, videos, and PDF files, from the [Firebase Storage](https://firebase.google.com/docs/storage) or [Supabase Storage](https://supabase.com/storage).
+:::
-
-
-
-
+## Delete Data [Action]
-:::info
-Before you add this action, ensure you can access the *Uploaded File URL* of the media. Check out the [**upload media**](upload-data.md) section to see how to get it.
-:::
+The **Delete Data** action permanently removes uploaded media—such as images, videos, and PDF files—from external storage platforms like [Firebase Storage](https://firebase.google.com/docs/storage) and [Supabase Storage](https://supabase.com/storage).
-### Adding Delete Media action
+Inside the **URL** section, provide a valid media URL. This must be either the direct **Uploaded File URL** or a variable that holds the URL.
-Follow the steps below to add this action to any widget.
+:::tip
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **+ Add Action**.
-3. Search and select the **Delete Media** (under *Utilities*) action.
-4. Inside the **URL** section, provide a valid media URL. This must be either the direct **Uploaded File URL** or a variable that holds the URL.
-5. To let users know about the successful deletion of the media, you can [add the snackbar message](../../resources/ui/pages/page-elements.md#snackbar).
+Always prompt users for confirmation before deleting media files to prevent accidental loss of data.
-
-
-
-
\ No newline at end of file
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/displaying-media.md b/docs/ff-concepts/file-handling/displaying-media.md
new file mode 100644
index 00000000..7adef3fb
--- /dev/null
+++ b/docs/ff-concepts/file-handling/displaying-media.md
@@ -0,0 +1,321 @@
+---
+slug: /concepts/file-handling/displaying-media
+title: Displaying Media
+description: Learn how to display media in FlutterFlow.
+tags: [Media Files, Widget]
+sidebar_position: 2
+keywords: [Media Files, Media Management, Assets, Network, Display Media, Media Widgets]
+---
+
+# Displaying Media
+
+Displaying media efficiently is crucial for enhancing user experience in your FlutterFlow app. Whether you're working with images, audio, video, or PDFs, FlutterFlow provides flexible options for integrating and managing media. This guide covers how to set media sources, customize playback settings, and implement best practices like lazy loading, caching, and BlurHash to optimize performance.
+
+## Media Types
+To display media on widgets, navigate to the **Properties Panel** and specify the media source under the **[Media] Type** option (e.g., ImageType, AudioType, VideoType). Here are the available options:
+
+### Network
+
+Enter the URL of the media directly into the **Path** input field. This is for media hosted online.
+
+
+
+If your media is uploaded to Firebase or Supabase, click **Set from Variable** on the **Path** input field, and select **Source** as **Widget State > Uploaded File URL**.
+
+
+
+For media uploaded via an API, choose **Source** as **Action Outputs > [Action Output Variable Name] (API Response)**. Ensure that the API response contains the URL of the uploaded file. Learn how to extract the URL using [JSON path](../../resources/control-flow/backend-logic/api/rest-api.md#json-path).
+
+
+
+:::info
+
+To handle scenarios where media takes time to load or fails to load, you can set a placeholder. Click **Set from Variable** on the **Path** field and specify a placeholder URL under the **Default Value** property.
+
+:::
+
+### Asset
+
+You can also display media files uploaded to your **Assets**. Assets are resources such as images, videos, documents, fonts, and other files that you include locally in your project. To upload assets, click on **Media Assets** in the left-side navigation menu and add files directly from your device. Alternatively, you can directly upload and display files when configuring media widgets by clicking the upload icon.
+
+:::tip
+For more details on how assets are stored in your project, see the directory [**Assets**](../../generated-code/directory-structure.md#assets) in the generated code.
+:::
+
+
+
+
+
+### Uploaded File
+
+You can also access media files within your app that are stored temporarily in your application. For example, if you'd like to preview an image before sending it to cloud storage, you can do so by setting the source to **Widget State -> Uploaded Local File**.
+
+
+
+## AudioPlayer
+
+The **AudioPlayer** widget allows you to integrate audio playback into your apps. You can play audio from both uploaded assets and external URLs. Refer to the [**Displaying Media**](#media-types) section for more details on accessing media.
+
+:::tip[Generated Code]
+The AudioPlayer widget in FlutterFlow uses the [**assets_audio_player**](https://pub.dev/packages/assets_audio_player) package for audio playback.
+:::
+
+**Customization Options**
+
+- **Title:** Specify the audio title in the **Title** property. You can set this directly or bind it to a variable, such as an app state variable, API response, or Firestore document.
+- **Pause on Forward Navigation:** By default, the audio stops when navigating to another page.
+- **Play in Background:** Define how the audio behaves when the app moves to the background:
+ - **Enabled:** The audio continues to play.
+ - **Disabled, restore on foreground:** The audio pauses and resumes when the app becomes active again.
+ - **Disabled, pause:** The audio stops immediately when the app goes into the background.
+- **Colors:**
+ - **Background Color:** Customize the background using the **Fill Color** property.
+ - **Playback Button Color:** Adjust the colors of the play and pause buttons.
+ - **Active/Inactive Track Color:** Change the progress bar color that indicates the current playback position.
+- **Elevation:** Use the **Elevation** property to modify the shadow beneath the audio tile. A higher value increases the shadow size, while setting it to 0 removes the shadow.
+- **Text Styling:**
+ - **Title Text:** Personalize the title’s font, size, and color in the **Title Text Style** section.
+ - **Playback Duration Text:** Adjust the style of the playback duration text in the **Playback Duration Text Style** section.
+
+## Audio Recording
+
+You can implement audio recording functionality using the **Start Audio Recording** and **Stop Audio Recording** actions.
+
+:::warning
+
+Currently, audio recording is not supported in **Run** or **Test** modes due to certain limitations.
+
+:::
+
+### Start Audio Recording [Action]
+
+This action starts the recording. It also provides a name to the recording, which you can use later to stop the recording using the [Stop Audio Recording](#stop-audio-recording-action) *action.*
+
+Before adding this action, ensure you [request microphone permission](../../resources/projects/settings/project-setup.md#request-permission-action). Within the **TRUE** block of the permission condition check, add the **Start Audio Recording** action. By default, the **Name** field value is a randomly generated string. You can change it to a more descriptive name for easier identification.
+
+:::tip
+
+After starting recording, you might want to update the state variables to reflect changes on the UI. For instance, you can enable/disable buttons or start recording animations to provide a visual cue of the ongoing process. This step allows you to enhance the user experience and provide real-time feedback during the recording.
+
+:::
+
+
+
+
+### Stop Audio Recording [Action]
+
+If you have multiple audio recording actions, all the Recorder object names (either auto-generated by FlutterFlow or manually set by the user) are listed under the Recorder Name dropdown. Choose the recorder object you want to stop, and it will stop the ongoing recording.
+
+ To capture and play the recorded audio, make sure to specify the *Action Output Variable Name*, which can be used with the audio player.
+
+Here’s how you can setup this action:
+
+1. When you add this action, choose the **Recorder Name** from the dropdown. This will be the name you provided in the Start Audio Recording action.
+2. Specify the **Action Output Variable Name**. This will store the actual audio recording, which you can use with any audio player. It stores recording in an **Audio Path** data type.
+3. If you want to upload the audio recording to Firebase or Supabase, you can use the [Upload file](uploading-files.md#upload-or-save-media-action) action. When you add this action:
+ 1. Set the **Upload Type** to the preferred one.
+ 2. Set **File Type** to **Uploaded File** because the *Stop Audio Recording* action internally stores recorded audio bytes (inside widget state).
+ 3. Set the **File to Upload** to **Widget State > Recorded File**.
+4. For uploading via API, *you don't need to add the Upload file action*. Just directly add the [**API call**](../../resources/control-flow/backend-logic/api/rest-api.md) and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. You can pass the audio recording via **Widget State > Recorded File** in the API variable. See how to [configure an API for the multipart request body](../../resources/control-flow/backend-logic/api/rest-api.md#multipart-format).
+
+:::tip
+
+- After stopping the recording, you might want to update the state variables to reflect changes on the UI. For instance, you can enable/disable buttons or stop recording animations.
+- It's always a good idea to have a fail-safe mechanism to ensure recordings are properly stopped, even if the user forgets to do so manually. For example, you can use the [**On Dispose**](../../resources/ui/pages/page-lifecycle.md#on-dispose-action-trigger) action trigger to stop recording when a user closes the app without manually stopping it.
+
+:::
+
+
+
+
+
+
+
+### Playing audio recording
+
+After you have stopped the recording, you can simply provide the *Action Output Variable Name* to the [Audio Player](#audioplayer) widget to start playing the recorded audio.
+
+## Play or Stop Sound
+
+The **Play Sound** and **Stop Sound** actions offer flexibility for enhancing the user experience with audio effects or background sounds.
+
+### Play Sound [Action]
+
+The **Play Sound Action** allows you to play a sound that notifies users about the action they have taken—for example, playing a sound after refreshing a list or sending a message.
+
+:::tip
+
+It is advisable to use this action only for short audio. To play the more extended audio, consider adding the [**AudioPlayer**](#audioplayer) widget.
+
+:::
+
+By default, this action is assigned a random **Name** to be stopped later using the [Stop Sound](#stop-sound-action) action. You can adjust the volume using the **Volume** slider (0.0 = mute, 1.0 = full volume). The action is non-blocking by default, allowing subsequent actions to trigger immediately. To wait until playback finishes before proceeding, enable the **Await Playback** option.
+
+:::info[Use cases]
+
+- **Feedback Sounds:** Play sounds for button clicks, form submissions, or error alerts to improve user interaction and feedback.
+- **Notifications:** Play sound alerts for reminders, messages, or task completion.
+- **Gamification:** Enhance gaming experiences with sound effects for achievements, levels, or interactions.
+
+:::
+
+### Stop Sound [Action]
+
+You can stop a sound that is currently playing, which was started by the [Play Sound](#play-sound-action) action. For example, If your app is playing any sound effects, you may need to stop them when the app is paused or stopped.
+
+:::info
+
+This action is enabled only when you have added a [**Play Sound**](#play-sound-action) action on a page.
+
+:::
+
+## VideoPlayer
+
+The **VideoPlayer** widget is used to show a video from uploaded assets or the URL link. The VideoPlayer widget can play various video formats such as MP4, MOV, WAV, MPEG, and JPEG motion photos. Refer to the [**Displaying Media**](#media-types) section for more details on accessing media.
+
+:::tip[Generated Code]
+The VideoPlayer uses the [**video_player**](https://pub.dev/packages/video_player) package for reliable video playback across different platforms.
+:::
+
+**Customization Options**
+
+The **VideoPlayer** widget includes several options to align with your app's design and functionality:
+
+- **Aspect Ratio:** Set the desired aspect ratio (e.g., 1.7 for a 16:9 ratio) to ensure the video displays correctly.
+- **AutoPlay:** Enable this option to automatically start playing the video when the page loads.
+- **Loop Video:** Choose whether the video should replay automatically after it ends.
+- **Show Controls:** Display playback controls, including play/pause buttons and the seek bar.
+- **Allow Full Screen:** Enable users to expand the video to full-screen mode.
+- **Playback Speed Menu:** Let users adjust the video playback speed.
+- **Load on Page Load:** When enabled, the video will preload when the page loads, reducing buffering time when the user starts playback.
+- **Pause on Forward Navigation:** If enabled, the video will pause automatically when the user navigates away from the page.
+
+## YoutubePlayer
+
+The **YouTubePlayer** widget in FlutterFlow allows you to integrate and play YouTube videos within your app. It offers customizable playback options and an intuitive interface for enhancing the user experience.
+
+:::tip[Generated Code]
+The YoutubePlayer uses a custom version of the [**youtube_player_iframe**](https://pub.dev/packages/youtube_player_iframe) package, hosted on FlutterFlow's GitHub repository.
+:::
+
+**Customization Options**
+
+- **Loop Video:** When enabled, the video will automatically replay after it finishes.
+- **Mute Video:** Starts the video in a muted state.
+- **Show Controls:** Displays playback controls such as play/pause, volume, subtitles, and fullscreen options.
+- **Show Full Screen Control:** This specifically displays the fullscreen toggle button among the controls.
+- **Pause on Forward Navigation:** Automatically pauses the video when the user navigates away from the page.
+- **Strict Related Videos:** Ensures that related videos shown at the end of playback come from the same channel as the currently played video.
+
+## PdfViewer
+
+In FlutterFlow, the **PdfViewer** widget enables you to display PDF files within your app, supporting both network URLs and locally uploaded assets. Refer to the [**Displaying Media**](#media-types) section for more details.
+
+:::tip[Generated Code]
+The PdfViewer in FlutterFlow uses the [**pdfx**](https://pub.dev/packages/pdfx) package for rendering PDFs.
+:::
+
+**Customization Options**
+
+- **Horizontal Scroll:** By default, the PdfViewer allows vertical scrolling through pages. Enable this option to allow horizontal scrolling.
+- **Use Proxy:** By default, FlutterFlow routes PDF fetching through a proxy in **Run Mode** and **Test Mode** to avoid CORS (Cross-Origin Resource Sharing) issues. **Switch this off** if you do not want the PDF request to be routed through the proxy.
+- **Use Custom Proxy URL:** If you need a specific proxy, enable this option and provide your own proxy URL instead of using FlutterFlow’s default proxy.
+
+## Web Access for PDFs and Other Files
+
+Some types of files require additional configuration to be accessed on the web. In particular, the PDF Viewer requires network-hosted files (such as uploaded PDFs) to allow Cross-Origin Resource Sharing (CORS). For a deeper understanding of Cross-Origin Resource Sharing (CORS), you can refer to this guide.
+
+The key takeaway is that to allow users to upload and view PDFs using Firebase Storage, follow the steps below.
+
+
+You'll need to run a few commands to enable CORS for your Firebase project. No programming experience is required, but if you're comfortable with Firebase, you can refer to the official guide here: [Firebase CORS Configuration](https://firebase.google.com/docs/storage/web/download-files#cors_configuration).
+
+**Step 1: Find Your Firebase Project ID**
+
+You can find the Firebase project ID from **FlutterFlow > Settings and Integrations > Firebase**. Copy your **Firebase** **Project ID**.
+
+
+
+**Step 2: Open Cloud Shell in Google Cloud Console**
+
+1. Go to the following link, replacing **FIREBASE_PROJECT_ID** with your actual project ID:
+
+```jsx
+https://console.cloud.google.com/home/dashboard?cloudshell=true&project=FIREBASE_PROJECT_ID
+```
+
+1. If prompted, click **Continue**.
+2. You should see a terminal at the bottom of the screen. If your project ID is not displayed in yellow, click the **down arrow** (🔽) next to the project name and select the correct Firebase project.
+
+
+
+**Step 3: Run the CORS Configuration Command**
+
+1. Click on the **Cloud Shell terminal** (the black screen).
+2. Copy and paste the following command and replace `` with your actual storage bucket. To locate your Firebase Storage bucket name, navigate to Firebase Console > Storage > at top left side, you'll see your bucket's URL, which typically follows the format `your-project-id.appspot.com`.
+
+```jsx
+touch cors.json && \
+echo '[{"origin": ["*"], "method": ["GET"], "maxAgeSeconds": 3600}]' > cors.json && \
+gsutil cors set cors.json gs://
+```
+
+
+
+3. Press **Enter** (or **Return**) to execute the command.
+4. If prompted, click **Authorize** to allow Cloud Shell to access your Firebase project.
+5. Once the command executes successfully, you should see a confirmation message.
+
+
+
+
+## BlurHash
+
+In FlutterFlow, **BlurHash** is a technique used to enhance the user experience by displaying visually appealing placeholders while images are loading. Instead of showing empty spaces or generic loading indicators, BlurHash generates a blurred preview that resembles the actual image, providing users with a smoother and more engaging experience.
+
+
+
+Here are the steps to generate and use the BlurHash:
+
+1. When using the [**Upload/Save Media**](uploading-files.md#upload-or-save-media-action) action to upload images, you can enable the **Include Blur Hash** option. This setting automatically generates a BlurHash string for the uploaded image.
+
+
+
+1. After generating the BlurHash, it's advisable to store it alongside the image URL in your database (e.g., Firestore). The generated BlurHash is accessible via the **Widget State > Uploaded Local File > Media Blur Hash**. This approach ensures that both the image URL and its corresponding BlurHash are readily accessible when needed.
+
+
+
+1. To utilize the BlurHash as a placeholder, in the Image widget's properties, enable the **Use Blur Hash** option and then set the **Blur Hash String** value from a variable.
+
+
+
+## Best Practices
+
+- Enable [infinite scrolling](../../resources/ui/widgets/composing-widgets/list-grid.md#adding-infinite-scroll) (lazy loading) in list views to load additional content as users scroll, rather than loading all data at once.
+- Leverage FlutterFlow's built-in cache manager, which automatically handles image caching.
+- Implement [local caching](../../resources/control-flow/backend-logic/backend-query/backend-query.md#backend-query-caching) to store frequently accessed data on the device, reducing the need for repeated network requests.
+- Reduce the number of network calls by fetching only necessary data and utilizing caching strategies.
+- Ensure that database queries are efficient and retrieve only the data required for display.
+- Use [BlurHash](#blurhash) to display a blurred preview of images while they load, enhancing the user experience.
+- Display loading indicators to inform users that data is being fetched, improving perceived performance.
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/download-file.md b/docs/ff-concepts/file-handling/download-file.md
index 7ed9ca01..81412103 100644
--- a/docs/ff-concepts/file-handling/download-file.md
+++ b/docs/ff-concepts/file-handling/download-file.md
@@ -1,12 +1,13 @@
---
-title: Download File
slug: /concepts/file-handling/download-file
-sidebar_position: 6
-tags: [Media, Download Data, File Management]
-keywords: [Media, Download Data, Firebase Storage, Supabase Storage]
+title: Download File
description: Learn how to add download file action into your FlutterFlow app.
+tags: [Media Files, Download Data]
+sidebar_position: 3
+keywords: [Media Files, Download Data, Firebase Storage, Supabase Storage]
---
+
# Download File
The **Download File** action allows you to enable users to download or save files locally on their devices.
@@ -49,7 +50,7 @@ The **Download File** action allows you to enable users to download or save file
To add a Download File action, select the **Widget** (e.g., button or any interactive widget) where you want users to initiate the file download and set the **Source** to one of the following.
- **From URL**: Use this option for downloading files that are accessible through a direct link and specify the URL of the file that should be downloaded.
-- **From File (Bytes)**: Use this option when the file is uploaded to the device using the [Local Upload (Widget State)](upload-data.md#local-upload-widget-state). You can access the file via ***Widget State > Uploaded Local File***.
+- **From File (Bytes)**: Use this option when the file is uploaded to the device using the [Local Upload (Widget State)](uploading-files.md#local-upload-widget-state). You can access the file via ***Widget State > Uploaded Local File***.
Optionally, you can specify a **Filename** to be used when the file is downloaded.
diff --git a/docs/ff-concepts/file-handling/file-handling.md b/docs/ff-concepts/file-handling/file-handling.md
new file mode 100644
index 00000000..86aaa671
--- /dev/null
+++ b/docs/ff-concepts/file-handling/file-handling.md
@@ -0,0 +1,25 @@
+---
+slug: /concepts/file-handling
+title: File Handling
+description: Learn how to handle media files in FlutterFlow.
+tags: [Media Files, Upload Data, Download Data, Clear Delete Data]
+sidebar_position: 0
+keywords: [File Handling, Media Files, Upload Data, Download Data, Clear Delete Data, Media Management, Assets, Display Media, Media Widgets]
+---
+
+# File Handling
+
+FlutterFlow makes it easy to manage, upload, download, and display files within your app. It supports a variety of file types, including images, videos, and documents, and integrates seamlessly with popular storage solutions. Using built-in widgets and actions, you can effectively manage your app's media. This guide covers the following key aspects of file handling in FlutterFlow.
+
+- **Media Assets**: Upload any assets you want to use in your app from the Navigation Menu > Media Assets. This also shows the media assets of the [Team](../../accounts-billing/subscriptions/flutterflow-for-teams.md).
+- [**Uploading Files**](uploading-files.md): Upload and save different file types, including images, audio, videos, and PDFs to cloud storage.
+- [**Displaying Media**](displaying-media.md): Fetch files from cloud storage or external URLs and display them in your app.
+- [**Download Files**](download-file.md): Allow users to download files directly to their devices.
+- [**Clear or Delete Media**](clear-delete-media.md): Allow users to delete uploaded files from their devices and cloud storage.
+
+:::info[Also see]
+
+- **Stream Media with Mux**: [**Integrate Mux's broadcasting**](../../ff-integrations/streaming/mux/initial-setup.md) services in FlutterFlow by using the MuxBroadcast widget for live streaming.
+- **Request Permissions**: [**Request user permissions**](../../resources/projects/settings/project-setup.md#request-permission-action) when implementing custom widgets or actions that access personal information, such as capturing photos or selecting images, especially if no built-in permission mechanism is available.
+
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/imgs/adding-clear-uploaded-data-action.avif b/docs/ff-concepts/file-handling/imgs/adding-clear-uploaded-data-action.avif
deleted file mode 100644
index f31a208b..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/adding-clear-uploaded-data-action.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/blurhash.avif b/docs/ff-concepts/file-handling/imgs/blurhash.avif
new file mode 100644
index 00000000..7ef74437
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/cloud-shell.avif b/docs/ff-concepts/file-handling/imgs/cloud-shell.avif
new file mode 100644
index 00000000..75704ced
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/cloud-shell.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/compress-image.avif b/docs/ff-concepts/file-handling/imgs/compress-image.avif
new file mode 100644
index 00000000..827a7918
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/compress-image.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/configure-upload-media-action.avif b/docs/ff-concepts/file-handling/imgs/configure-upload-media-action.avif
new file mode 100644
index 00000000..05cb8a05
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/configure-upload-media-action.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/copy-firebase-project-id.avif b/docs/ff-concepts/file-handling/imgs/copy-firebase-project-id.avif
new file mode 100644
index 00000000..247e4f4d
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/copy-firebase-project-id.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/cors-2.png b/docs/ff-concepts/file-handling/imgs/cors-2.png
new file mode 100644
index 00000000..c4375f34
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/cors-2.png differ
diff --git a/docs/ff-concepts/file-handling/imgs/cors-3.png b/docs/ff-concepts/file-handling/imgs/cors-3.png
new file mode 100644
index 00000000..2aa773ff
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/cors-3.png differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-api.avif b/docs/ff-concepts/file-handling/imgs/dm-api.avif
new file mode 100644
index 00000000..c8ae9731
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-api.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-local-upload.avif b/docs/ff-concepts/file-handling/imgs/dm-local-upload.avif
new file mode 100644
index 00000000..e1342a24
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-local-upload.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-network-path.avif b/docs/ff-concepts/file-handling/imgs/dm-network-path.avif
new file mode 100644
index 00000000..1cdc25d4
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-network-path.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/dm-uploaded-file.avif b/docs/ff-concepts/file-handling/imgs/dm-uploaded-file.avif
new file mode 100644
index 00000000..65081f59
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/dm-uploaded-file.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/enable-blurhash.avif b/docs/ff-concepts/file-handling/imgs/enable-blurhash.avif
new file mode 100644
index 00000000..07f7b361
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/enable-blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/full-screen-control-disabled.avif b/docs/ff-concepts/file-handling/imgs/full-screen-control-disabled.avif
deleted file mode 100644
index bf11b98a..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/full-screen-control-disabled.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_1.png b/docs/ff-concepts/file-handling/imgs/img_1.png
deleted file mode 100644
index 01e7719f..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_1.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_10.png b/docs/ff-concepts/file-handling/imgs/img_10.png
deleted file mode 100644
index e46055e0..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_10.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_11.png b/docs/ff-concepts/file-handling/imgs/img_11.png
deleted file mode 100644
index 21d5c2ec..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_11.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_12.png b/docs/ff-concepts/file-handling/imgs/img_12.png
deleted file mode 100644
index f9e1adab..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_12.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_13.png b/docs/ff-concepts/file-handling/imgs/img_13.png
deleted file mode 100644
index 87d14cd2..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_13.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_2.png b/docs/ff-concepts/file-handling/imgs/img_2.png
deleted file mode 100644
index f4712e83..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_2.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_3.png b/docs/ff-concepts/file-handling/imgs/img_3.png
deleted file mode 100644
index d1be800f..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_3.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_4.png b/docs/ff-concepts/file-handling/imgs/img_4.png
deleted file mode 100644
index 75b84083..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_4.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_5.png b/docs/ff-concepts/file-handling/imgs/img_5.png
deleted file mode 100644
index ec8e4a7d..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_5.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_6.png b/docs/ff-concepts/file-handling/imgs/img_6.png
deleted file mode 100644
index 672bd56c..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_6.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_7.png b/docs/ff-concepts/file-handling/imgs/img_7.png
deleted file mode 100644
index 28730fb3..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_7.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_8.png b/docs/ff-concepts/file-handling/imgs/img_8.png
deleted file mode 100644
index af99faf3..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_8.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/img_9.png b/docs/ff-concepts/file-handling/imgs/img_9.png
deleted file mode 100644
index c2be9a3e..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/img_9.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/local-upload-to-firebase-supabase.avif b/docs/ff-concepts/file-handling/imgs/local-upload-to-firebase-supabase.avif
new file mode 100644
index 00000000..4610439d
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/local-upload-to-firebase-supabase.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/save-blurhash.avif b/docs/ff-concepts/file-handling/imgs/save-blurhash.avif
new file mode 100644
index 00000000..54f0e38f
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/save-blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/select-from-assets.avif b/docs/ff-concepts/file-handling/imgs/select-from-assets.avif
new file mode 100644
index 00000000..55bc4839
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/select-from-assets.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/show-controls-disabled.avif b/docs/ff-concepts/file-handling/imgs/show-controls-disabled.avif
deleted file mode 100644
index e53279e7..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/show-controls-disabled.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/show-controls-enabled.avif b/docs/ff-concepts/file-handling/imgs/show-controls-enabled.avif
deleted file mode 100644
index e1a94f20..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/show-controls-enabled.avif and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/start-audio-recording.avif b/docs/ff-concepts/file-handling/imgs/start-audio-recording.avif
new file mode 100644
index 00000000..762877dc
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/start-audio-recording.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/stop-action.png b/docs/ff-concepts/file-handling/imgs/stop-action.png
deleted file mode 100644
index 0d1dea3a..00000000
Binary files a/docs/ff-concepts/file-handling/imgs/stop-action.png and /dev/null differ
diff --git a/docs/ff-concepts/file-handling/imgs/storage-bucket.avif b/docs/ff-concepts/file-handling/imgs/storage-bucket.avif
new file mode 100644
index 00000000..b5e6b36d
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/storage-bucket.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/img.png b/docs/ff-concepts/file-handling/imgs/supabase-storage-bucket.png
similarity index 100%
rename from docs/ff-concepts/file-handling/imgs/img.png
rename to docs/ff-concepts/file-handling/imgs/supabase-storage-bucket.png
diff --git a/docs/ff-concepts/file-handling/imgs/upload-type-firebase.avif b/docs/ff-concepts/file-handling/imgs/upload-type-firebase.avif
new file mode 100644
index 00000000..b02f44be
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/upload-type-firebase.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/upload-type-local-and-api.avif b/docs/ff-concepts/file-handling/imgs/upload-type-local-and-api.avif
new file mode 100644
index 00000000..3edc5b0a
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/upload-type-local-and-api.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/upload-type-supabase.avif b/docs/ff-concepts/file-handling/imgs/upload-type-supabase.avif
new file mode 100644
index 00000000..551c1b28
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/upload-type-supabase.avif differ
diff --git a/docs/ff-concepts/file-handling/imgs/use-blurhash.avif b/docs/ff-concepts/file-handling/imgs/use-blurhash.avif
new file mode 100644
index 00000000..22075461
Binary files /dev/null and b/docs/ff-concepts/file-handling/imgs/use-blurhash.avif differ
diff --git a/docs/ff-concepts/file-handling/pdf/_category_.json b/docs/ff-concepts/file-handling/pdf/_category_.json
deleted file mode 100644
index b9a86169..00000000
--- a/docs/ff-concepts/file-handling/pdf/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "PDF",
- "position": 2
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/pdf/pdf-viewer.md b/docs/ff-concepts/file-handling/pdf/pdf-viewer.md
deleted file mode 100644
index 044294f2..00000000
--- a/docs/ff-concepts/file-handling/pdf/pdf-viewer.md
+++ /dev/null
@@ -1,161 +0,0 @@
----
-title: PdfViewer
-slug: /concepts/file-handling/pdf-viewer
-sidebar_position: 1
-tags: [Media, Widget]
-keywords: [Media, PdfViewer, Display PDF File]
----
-# PdfViewer
-The PdfViewer widget allows you to show the PDF file from uploaded assets or the URL link.
-
-## Adding PdfViewer Widget
-
-Here's how you can add the PdfViewer widget to your project:
-
-1. Drag the **PdfViewer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **Network Path** property and enter the **URL** for the pdf file.
-
-:::info
-Every PdfViewer widget added to the project shows a default PDf from an online source.
-:::
-
-
-
-
-
-
-## Changing PDF Source
-
-By default, the widget is set to show the PDF file from Network. However, you can change this to use the PDF file uploaded directly to your app.
-
-Here's how you can change the PDF source:
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **PDF Source** dropdown. Change it to **Asset**.
-4. Now, find the **PDF Asset** property, Click on the **Upload Pdf** button, select the pdf file and upload it.
-
-
-
-
-
-
-:::tip
-Once you upload the pdf file, you can use it throughout your app. You can manage your uploaded pdfs with the Project Media/Asset Manager.
-:::
-
-To use an uploaded pdf:
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **PDF Source** dropdown. Change it to **Asset**.
-4. Click on **No asset selected** (inside the dropdown) and choose the pdf file.
-
-
-
-
-
-
-## Customizing
-
-You can customize the appearance and behavior of this widget using the various properties available under the properties panel.
-
-### Changing Scroll Direction
-
-By default, the PdfViewer allows you to scroll to the next pages in the vertical direction. However, you can change this behavior to allow scrolling in the horizontal direction.
-
-To change the scroll direction:
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Enable the **Horizontal Scroll**.
-
-
-
-
-
diff --git a/docs/ff-concepts/file-handling/upload-data.md b/docs/ff-concepts/file-handling/upload-data.md
deleted file mode 100644
index 28e59367..00000000
--- a/docs/ff-concepts/file-handling/upload-data.md
+++ /dev/null
@@ -1,81 +0,0 @@
----
-title: Upload Data
-slug: /concepts/file-handling/upload-data
-sidebar_position: 3
-tags: [Media, Upload Data]
-keywords: [Media, Upload Data, Firebase Storage, Supabase Storage]
----
-
-
-# Upload Data
-
-This section covers actions for uploading media such as photos, videos, PDFs, and Audio files.
-
-You can learn about adding each action by visiting the following pages.
-
-- [Upload/Save Media](upload-save-media.md)
-- [Upload/Save File](upload-save-file.md)
-
-## Types of upload
-
-To upload media, you have two options:
-
-### Firebase
-
-This will upload your media to [Firebase Storage](https://firebase.google.com/docs/storage). Once uploaded, you can directly use the ***Widget State > Uploaded File URL*** to preview media or save the URL.
-
-
-
-### Supabase
-
-Similar to Firebase, this will upload your media to the Supabase bucket (at a specific location that you specify). Once uploaded, you can directly use the ***Widget State > Uploaded File URL*** to preview media or save the URL.
-
-### Local Upload (Widget State)
-
-This will save your media to the device first. You can access it via ***Widget State > Uploaded Local File***. Then, make an API call to transfer the file to your server. **Note** that this API call must return the URL of the uploaded file, which you can later use to preview the media or store it somewhere in your database.
-
-
-## Web Access for PDFs and Other Files
-
-Some types of files require additional configuration to be accessed on the web. In particular, the PDF Viewer requires network files (such as uploaded PDFs) to allow what is called Cross-Origin Resource Sharing (CORS). Without diving too deep into that, the important part is that if you want users to be able to upload and view PDFs using Firebase Storage, follow the instructions below:
-
-**Put On Your Developer Hat**
-
-You'll need to run a few commands to get started. Don't worry though! No programming experience is required for this part, but you'll get to see how it's done 🙂
-
-:::note
-If you *do* have programming experience, you may find it easier to follow this guide instead: https://firebase.google.com/docs/storage/web/download-files#cors_configuration
-:::
-
-Start by finding the Project ID of your Firebase project. You can find that in the Firebase settings tab as seen below.
-
-
-
-Once you have that, follow these steps. Anywhere you see `*FIREBASE_PROJECT_ID*` , replace it with the project ID you found above:
-
-**Step 1**
-
-Go to the following link (remember to use your project ID): `https://console.cloud.google.com/home/dashboard?cloudshell=true&project=FIREBASE_PROJECT_ID`
-
-You'll see a view at the bottom that looks like this (you may have to hit "Continue"):
-
-
-
-Your Project ID should appear in yellow. If not, or if a different project is selected, you may have to tap on the down arrow (circled in red above) and select your project.
-
-**Step 2**
-
-Tap on the terminal (black screen), paste in the following command (again, replacing it with your Project ID ****in the last line), and hit *Enter* (or *Return*)**:**
-
-
-```
-touch cors.json && \
-echo [{\"origin\": [\"*\"], \"method\": [\"GET\"], \"maxAgeSeconds\": 3600}] > cors.json && \
-gsutil cors set cors.json gs://FIREBASE_PROJECT_ID.appspot.com
-```
-
-If you get a message to "Authorize Cloud Shell" make sure to hit "Authorize". Once the command runs it should give you an output similar to below. If so, it worked!
-
-
-
-And with that you are done! PDFs and other uploaded files will now load in the web with no issues!
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/upload-save-file.md b/docs/ff-concepts/file-handling/upload-save-file.md
deleted file mode 100644
index 9e703441..00000000
--- a/docs/ff-concepts/file-handling/upload-save-file.md
+++ /dev/null
@@ -1,139 +0,0 @@
----
-title: Upload or Save File
-slug: /concepts/file-handling/upload-save-file
-sidebar_position: 4
-tags: [Media, Upload Data, File Management]
-keywords: [Media, Upload Data, Firebase Storage, Supabase Storage]
----
-
-
-
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-# Upload or Save File
-
-Using this action, you can upload any type of file to your app (e.g., PDF, MP3, etc.). You can store the file on [Firebase](https://firebase.google.com/docs/storage), [Supabase](https://supabase.com/docs/guides/storage) storage, or your own server using an API. Once uploaded, you can access the file through its generated URL. This URL can be used to display the content immediately or store it in a database for future retrieval.
-
-
-
-:::info[Prerequisites for Firebase]
-1. **Firebase** should be connected to your project. Follow the instructions on [**this page**](../../ff-integrations/database/cloud-firestore/getting-started.md) for integrating Firebase with FlutterFlow.
-2. **Firebase Authentication** must be properly configured. Check out [**this page**](../../ff-integrations/authentication/firebase-auth/auth-initial-setup.md) for setting up authentication.
-3. **Firebase Storage** must be set up and properly configured. It takes just a second! Follow the instructions on [**this page**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
-4. At least one **Firebase Collection** should be configured for the project so that you can store the generated URL.
- :::
-
-
-:::info[Prerequisites for Supabase]
-
-1. Make sure to [**integrate Supabase**](../../ff-integrations/supabase/supabase-setup.md) into your app.
-2. [**Create a storage bucket**](https://supabase.com/docs/guides/storage/quickstart#create-a-bucket) in Supabase.
- **Tip**: To let anyone download the uploaded media, you can enable the 'Public bucket.'
-
-
-
-
-
-3. Apply additional [**security rules**](https://supabase.com/docs/guides/storage/quickstart#add-security-rules) which determine who can access the bucket. **Tip**: If you are uploading to a folder structure like this '*pics/uploads*,' here is how you can add a policy that allows only authenticated users to upload their profile picture.
-
-
-
-
-:::
-
-## Upload File: Tutorial
-
-Let's build a simple example that allows you to upload the PDF file. Here's how it looks:
-
-
-
-Building the upload file feature comprises the following steps:
-
-1. [Firebase only: deploying Firebase Storage rules](#1-firebase-only-deploying-firebase-storage-rules)
-2. [Optional: enabling Web access](#2-optional-enabling-web-access)
-3. [Adding Upload/Save File action](#3-adding-uploadsave-file-action)
-4. [Preview uploaded file](#4-preview-uploaded-file)
-
-### 1. Firebase only: deploying Firebase Storage rules
-
-Firebase storage rules define who can access the uploaded file. It is essential to set up and deploy the rules before getting started. First, you must enable the *Firebase Storage* on the *Firebase Console* and then deploy its security rules. You can do this from right inside *FlutterFlow*.
-
-Check [**how to deploy the Firebase Storage rules**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
-
-### 2. Optional: enabling Web access
-
-If you plan to support the web version of your app or want to test the PDF upload feature in the *Run* Mode, you need to complete an additional configuration that is required for some file types, such as PDF, to work. Learn how to [enable web access](upload-data.md#web-access-for-pdfs-and-other-files).
-
-### 3. Adding Upload/Save File action
-
-Go to your project page on FlutterFlow and follow the steps below to define the action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the Properties panel (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window.
-3. Click on the **+ Add Action**.
-4. Search and select the **Upload/Save File** (under *Utilities > Upload Data*) action.
-5. If you haven't integrated Firebase or Supabase yet, the default upload type will be **[Store media for upload](upload-data.md#local-upload-widget-state)**. However, once integrated, you can choose the **Upload Type** as [Firebase](upload-data.md#firebase), [Supabase](upload-data.md#supabase) or [Local (Widget State)](upload-data.md#local-upload-widget-state).
-6. Use the **File Type** dropdown to specify whether you want to upload a **PDF**, **Audio (MP3),** **ANY,** or **Uploaded Media**. The *Uploaded Media* option is there for uploading the media stored on the device. If you choose **Uploaded Media**, ensure you add one more same action (before this action) with **Upload Type** set to [**Local Upload (Widget State)**](upload-data.md#local-upload-widget-state).
-7. You can **Allow multiple Files** to be uploaded. After the multiple files are uploaded, you can access them via *Set from Variable menu > Widget State > Uploaded File URLs (`List `).*
-8. To let users know whether the file is still being uploaded, you can enable the 'Show Snackbar' option.
-9. In *Upload Type*,
- 1. If you selected ***Firebase***, you must [deploy the storage rules](../../ff-integrations/storage/firebase-storage/storage-rules.md).
- 2. If you selected **Supabase**, provide the **Bucket Name** and set the **Uploaded Folder Path** (e.g., attachments/pdfs). This is the path where the files will be uploaded.
- 3. If you selected ***Local Upload (Widget State)**,* you probably want to store the file on the device first and then upload it to your backend server via API. To do so, add the next action as an [**API call**](../../resources/control-flow/backend-logic/api/create-test-api-calls.md) and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. See how to [configure an API for the multipart request body](../../resources/control-flow/backend-logic/api/rest-api.md). **Tip**: When this type is selected, you have an option to directly display the PDF before it gets uploaded to your server; see [here](#41-access-file-from-bytes-in-memorynot-yet-uploaded).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### 4. Preview uploaded file
-
-Once the file is uploaded, you get the uploaded file URL. You can use it to display the content inside the supported widget.
-
-Here is an example showing a PDF file in a PdfView widget.
-
-1. Select the **PdfViewer** widget from the widget tree or from the canvas area.
-2. Move to the **Properties Panel** (on the right side of your screen) and scroll down to the **PDF Viewer** section.
-3. Find the **Network Path** and click on the **Set from Variable**.
-4. For media uploaded on **Firebase** or **Supabase**, select the **Source** as ***Widget State*** > ***Uploaded File URL***.
-5. For media uploaded via **API**, select the **Source** as **Action Outputs > [Action Output Variable Name] (Api Response)**. This should be the response of the API that was used to upload the file, and it must contain the URL of the uploaded file. To retrieve the url from API response, see how to [use JSON path](../../resources/control-flow/backend-logic/api/rest-api.md).
-6. You can display the placeholder until the current file is uploaded. To do so, click the **Set from Variable** and specify a placeholder URL under the **Default Value** property.
-7. Click on **Confirm**.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#### 4.1 Access file from bytes (in memory/not yet uploaded)
-
-If you simply wish to display a PDF within your app without uploading it anywhere, or if you'd like to preview the PDF before sending it to your server through an API, you can achieve this by configuring the **PDF Source** as **Uploaded File** and specifying the **Uploaded File** source as **Widget State -> Uploaded Local File**.
-
-
-
diff --git a/docs/ff-concepts/file-handling/upload-save-media.md b/docs/ff-concepts/file-handling/upload-save-media.md
deleted file mode 100644
index ac45fb2e..00000000
--- a/docs/ff-concepts/file-handling/upload-save-media.md
+++ /dev/null
@@ -1,382 +0,0 @@
----
-title: Upload or Save Media
-slug: /concepts/file-handling/upload-save-media
-sidebar_position: 5
-tags: [Media, Upload Data, File Management]
-keywords: [Media, Upload Data, Firebase Storage, Supabase Storage]
----
-
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-
-# Upload or Save Media
-
-This action allows you to easily upload a photo or video to your app. You have the flexibility to store the file on [Firebase](https://firebase.google.com/docs/storage), [Supabase](https://supabase.com/docs/guides/storage) storage, or your own server using an API. Once uploaded, you can access the file through its generated URL. This URL can be used to display the content immediately or store it in a database for future retrieval.
-
-
-
-
-
-
-
-:::info[Prerequisites for Firebase]
-1. **Firebase** should be connected to your project. Follow the instructions on [**this page**](../../ff-integrations/database/cloud-firestore/getting-started.md) for integrating Firebase with FlutterFlow.
-2. **Firebase Authentication** must be properly configured. Check out [**this page**](../../ff-integrations/authentication/firebase-auth/auth-initial-setup.md) for setting up authentication.
-3. **Firebase Storage** must be set up and properly configured. It takes just a second! Follow the instructions on [**this page**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
-4. At least one **Firebase Collection** should be configured for the project so that you can store the generated URL.
- :::
-
-
-:::info[Prerequisites for Supabase]
-
-1. Make sure to [**integrate Supabase**](../../ff-integrations/supabase/supabase-setup.md) into your app.
-2. [**Create a storage bucket**](https://supabase.com/docs/guides/storage/quickstart#create-a-bucket) in Supabase.
- **Tip**: To let anyone download the uploaded media, you can enable the 'Public bucket.'
-
-
-
-
-
-3. Apply additional [**security rules**](https://supabase.com/docs/guides/storage/quickstart#add-security-rules) which determine who can access the bucket. **Tip**: If you are uploading to a folder structure like this '*pics/uploads*,' here is how you can add a policy that allows only authenticated users to upload their profile picture.
-
-
-
-
-:::
-
-
-## Adding Upload/Save Media action
-
-Follow the steps below to add this action to any widget.
-
-1. Select the **Widget** (e.g., Button) on which you want to add the action.
-2. Select **Actions** from the **Properties Panel** (the right menu), and click **Open**. This will open an **Action Flow Editor** in a new popup window. If it's the first action, click **+ Add Action** button. Otherwise, click the "**+**" button below the previous action tile and select **Add Action**.
-3. Search and select the **Upload/Save Media** (under *Utilities > Upload Data*) action.
-4. If you haven't integrated Firebase or Supabase yet, the default upload type will be **[Store media for upload](upload-data.md#local-upload-widget-state)**. However, once integrated, you can choose the **Upload Type** as [Firebase](upload-data.md#firebase), [Supabase](upload-data.md#supabase) or [Local (Widget State)](upload-data.md#local-upload-widget-state).
-5. Use the **Media Type/Source** to specify whether you want to upload a photo or a video, or both using this action.
-6. Using **Media Source** dropdown, you can choose between ***Camera***, ***Gallery**,* and ***Either Camera or Gallery*** (this option will bring up a bottom sheet from where the user can choose the media source as Camera or Gallery) and **Uploaded Media**. If you choose **Uploaded Media**, ensure you add one more same action (before this action) with **Upload Type** set to **Local Upload (Widget State)**.
-7. If you are uploading a photo, you can set a maximum width and height for it by using the **Max Width** and **Max Height** properties, respectively. This will modify the image dimension by maintaining the photo's aspect ratio.
-8. You can control the **Image Quality** by using the slider or directly entering the value. The value must be 0 to 100, where 100 is the original quality.
-9. To retrieve the uploaded media's dimensions, i.e., width and height, enable **Include Media Dimension**. This computation is expensive, so be sure before you enable it.
-10. Use the **Source Picker Style** to tailor the appearance of the bottom sheet UI that opens when selecting either *Camera* or *Gallery*.
-11. You can **Allow multiple images**. Note that for this to work, the *Media Source* must be set to only *Gallery*. After the multiple images are uploaded, you can access them via *Set from Variable menu > Widget State > Uploaded File URLs (`List `).*
-12. To let users know whether the image is still uploading, you can enable the **Show Snack bar**.
-13. If you selected *Either Camera or Gallery*, you would be presented with a few more properties to define the **Source Picker Style** (the bottom sheet design). You can specify the ***Font Family***, ***Text Color***, and ***Background Color*** of the bottom sheet.
-14. In *Upload Type*:
- 1. If you selected ***Firebase***, you must [deploy the storage rules](../../ff-integrations/storage/firebase-storage/storage-rules.md).
- 2. If you selected **Supabase**, provide the **Bucket Name** and set the **Uploaded Folder Path** (e.g., pics/uploaded). This is the path where the media will be uploaded.
- 3. if you selected ***Local (Widget State)**,* you probably want to upload the media to your backend server via API. To do so, add the next action as an **API call** and select the API that will upload the file to your server. **Note** that the request body for this API must be in *Multipart* format. See how to [configure an API for the multipart request body](../../resources/control-flow/backend-logic/api/rest-api.md). **Tip**: When this type is selected, you have an option to directly display the image before it gets uploaded to your server; see [here](#display-images-from-bytes-in-memorynot-yet-uploaded).
-15. Once you have uploaded the media, see how to display it on a widget in the [next section](#showing-uploaded-media).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### Showing uploaded media
-
-For displaying the media on the same page from where the **Upload/Save Media Action** is called, follow the steps below:
-
-1. Drag and drop the appropriate widget that can display the uploaded media. For example, to display uploaded photo, you can use the **Image** widget. Similarly, for video, use the **VideoPlayer** widget.
-2. Move to the properties panel, set its **Type** to **Network**, and click **Set from Variable**.
-3. For media uploaded on **Firebase** or **Supabase**, select the **Source** as ***Widget State*** > ***Uploaded File URL***.
-4. For media uploaded via **API**, select the **Source** as **Action Outputs > [Action Output Variable Name] (Api Response)**. This should be the response of the API that was used to upload the media, and it must contain the URL of the uploaded media. To retrieve the URL from API response, see how to [use JSON path](../../resources/control-flow/backend-logic/api/rest-api.md).
-5. To show the placeholder image/video until the current one is uploaded, click the **Set from Variable** and specify a placeholder image/video URL under the **Default Value** property.
-6. Click on **Confirm**.
-
-:::tip
-To ensure smooth functionality, it's important to provide a **Default Value** when displaying media on the same page as the upload action. Without it, you may encounter errors during app runtime due to an initially empty URL. Once this action is triggered and the media is successfully stored on Firebase/Supabase Storage, the URL becomes accessible.
-:::
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#### Display images from bytes (in memory/not yet uploaded)
-
-If you simply wish to display an image within your app without uploading it anywhere, or if you'd like to preview the image before sending it to your server through an API, you can achieve this by configuring the **Image Type** as **Uploaded File** and specifying the **Uploaded File** source as **Widget State -> Uploaded Local File**.
-
-
-
-
-### Storing the uploaded media URL
-
-You should store the uploaded media URL in your database (Firebase collection or database table) so that you can easily access it later inside the app.
-
-#### Save URL in Firebase collection
-
-To save URL in a Firebase collection:
-
-1. Ensure you have a **field** that can store a photo or video path, for example, `photo_url (Data Type: Image Path)` or `video_url (Data Type: Video Path)`.
-2. Now use the Firebase [Create](../../ff-integrations/database/cloud-firestore/firestore-actions.md#create-document-action)/[Update](../../ff-integrations/database/cloud-firestore/firestore-actions.md#update-document-action) document action to store the URL in a field.
-
-:::note
-While choosing *Value Source*, you can set either *Widget State > Uploaded File URL* or directly choose *Uploaded Photo/Video*.
-:::
-
-
-
- 
- Saving uploaded URL in Firestore document
-
-
-
- 
- Saving uploaded URL in Firestore document
-
-
-
- 
- Saving uploaded URL in Firestore document
-
-
-#### Save URL via backend API
-
-You can use your backend AP to store the URL, like you would do for any other data.
-
-
-
-### Adding BlurHash
-
-BlurHash is a new and innovative way of generating image placeholders that are both compact and visually appealing. When you're scrolling through a web or mobile app, you may have noticed that some images take longer to load. This can be frustrating and disrupt the user experience. That's where BlurHash comes in - it provides a way to display a blurred version of the image that looks similar to the original while the real image is loading in the background.
-
-With BlurHash, you can create more visually appealing and contextually relevant placeholders that better reflect the content of the image being loaded. It can be used in a variety of contexts, from photo galleries and social media apps to e-commerce and news apps.
-
-Here's how it looks when images are loaded with BlurHash:
-
-
- 
- Using BlurHash to display cat images
-
-
-Here are the steps to generate and use the BlurHash:
-
-1. [Generate BlurHash](#generate-blurhash)
-2. [Save BlurHash](#save-blurhash)
-3. [Use BlurHash](#use-blurhash)
-
-#### Generate BlurHash
-
-There is no separate action to generate the Blurhash. Instead, you can generate it using the **Upload/Save Media** action. From the page where you upload the image, use this action and simply enable the **Include Blur Hash** option. This will automatically create a Blurhash for the image being uploaded.
-
-
-
-
-
-#### Save BlurHash
-
-The generated BlurHash is accessible via the **Widget State > Uploaded Local File > Media Blur Hash**. Before you use the BlurHash, It is recommended to store it in the same collection or table where you save the image URL for convenient access.
-
-
- 
- Collection schema to store BlurHash
-
-
-Here's how you access and save the BlurHash in a Firebase collection using [**create document**](../../ff-integrations/database/cloud-firestore/firestore-actions.md#create-document-action) action:
-
-
-
-
-
-
-
-:::tip
-You can also create a [**custom data type**](../../resources/data-representation/custom-data-types.md) called 'image' and then add two fields such as 'image_url' and 'image_blurhash' like this:
-
-
- 
- Custom data type to store image URL and BlurHash
-
-:::
-
-#### Use BlurHash
-
-To use BlurHash, select the **Image** widget, move to the **properties panel**, enable the **Use Blur Hash** option, and then set the **Blur Hash String** value from a variable.
-
-
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/uploading-files.md b/docs/ff-concepts/file-handling/uploading-files.md
new file mode 100644
index 00000000..ccc3e743
--- /dev/null
+++ b/docs/ff-concepts/file-handling/uploading-files.md
@@ -0,0 +1,223 @@
+---
+slug: /concepts/file-handling/uploading-files
+title: Uploading Files
+description: Learn how to upload media in FlutterFlow.
+tags: [Media Files, Upload Data]
+sidebar_position: 1
+keywords: [Media Files, Upload Data, Media Management, Firebase, Supabase, Upload Actions]
+---
+
+# Uploading Files
+
+Uploading files is an essential feature for many apps, enabling users to share images, videos, documents, and more. FlutterFlow offers flexible actions to handle file uploads, whether you’re using Firebase, Supabase, or your own backend server. You can customize the upload process to suit your app’s needs, such as resizing media, setting quality, or temporarily storing files locally before uploading.
+
+This guide covers the available upload methods, configuration options, and workflows, including how to save media locally and upload it via an API.
+
+## Types of Media Uploads
+
+FlutterFlow provides three methods for uploading media files, each catering to different needs:
+
+### Firebase
+
+Media files can be uploaded directly to **Firebase Storage**, a reliable cloud-based solution. Once the upload is complete, you can use the **Widget State > Uploaded File URL** to preview the media or store the file URL for later use.
+
+
+
+### Supabase
+
+You can upload media to a **Supabase bucket** at a specified location. After the upload, the file's URL is accessible via **Widget State > Uploaded File URL**, enabling you to preview the media or save the URL for later use in your app.
+
+
+
+### Local Upload (Widget State)
+
+This method initially stores your media on the device, making it accessible via **Widget State > Uploaded Local File**. You can preview, edit, or process the file before uploading it to a cloud storage.
+
+
+
+## Upload or Save Media [Action]
+
+This action allows you to upload a photo or video to your app. You can choose to store the file on [Firebase](#firebase), [Supabase](#supabase) storage, or your own server using an API. Once uploaded, you can access the file through its generated URL. This URL can be used to display the content immediately or store it in a database for future retrieval.
+
+:::info[Prerequisites for Firebase]
+1. **Firebase** should be connected to your project. Follow the instructions on [**this page**](../../ff-integrations/database/cloud-firestore/getting-started.md) for integrating Firebase with FlutterFlow.
+2. **Firebase Authentication** must be properly configured. Check out [**this page**](../../ff-integrations/authentication/firebase-auth/auth-initial-setup.md) for setting up authentication.
+3. **Firebase Storage** must be set up and properly configured. It takes just a second! Follow the instructions on [**this page**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
+4. At least one **Firebase Collection** should be configured for the project so that you can store the generated URL.
+:::
+
+
+:::info[Prerequisites for Supabase]
+1. Make sure to [**integrate Supabase**](../../ff-integrations/supabase/supabase-setup.md) into your app.
+2. [**Create a storage bucket**](https://supabase.com/docs/guides/storage/quickstart#create-a-bucket) in Supabase. By default, the **Public bucket** option is disabled, meaning uploaded media is not accessible by anyone without authentication. If needed, you can enable the Public bucket option, but this is not recommended for sensitive content.
+
+
+
+
+
+3. Apply additional [**security rules**](https://supabase.com/docs/guides/storage/quickstart#add-security-rules) which determine who can access the bucket. **Tip**: If you are uploading to a folder structure like this '*pics/uploads*,' here is how you can add a policy that allows only authenticated users to upload their profile picture.
+
+
+
+:::
+
+To create an upload media workflow, add the **Upload/Save Media** action to the widget (e.g., a button or any interactive element) where you want users to initiate the file upload. Next, set the [**Upload Type**](#types-of-media-uploads). In the **Media Type/Source** section, specify the type of media to upload: photo, video, or both. Then, use the **Media Source** dropdown to choose the source of the media:
+
+- **Camera**: Directly capture media using the device's camera.
+- **Gallery**: Select existing media from the device's gallery.
+- **Either Camera or Gallery**: Allows users to choose the source via a bottom sheet, letting them select either the camera or the gallery as the media source.
+
+Once the media is uploaded, see how to display it on a widget in the [next section](displaying-media.md).
+
+:::info
+
+When you set **Upload Type** to:
+
+- **Firebase**: You must [**deploy the storage rules**](../../ff-integrations/storage/firebase-storage/storage-rules.md).
+- **Supabase**: Provide the **Bucket Name** and set the **Uploaded Folder Path** (e.g., pics/uploaded). This is the path where the media will be uploaded.
+
+:::
+
+
+
+
+
+
+
+The Upload Media action offers various settings to control how media files are uploaded, resized, and processed in your app. Below is a breakdown of all the available properties.
+
+
+
+- **Max Width** and **Max Height**: If you are uploading a photo, you can set a maximum width and height using these properties. This resizes the image while maintaining its original aspect ratio.
+- **Image Quality**: Control the image quality by adjusting the slider or entering a value between 0 and 100, where 100 retains the original quality.
+- **Include Media Dimensions**: Enable this option to retrieve the dimensions (width and height) of the uploaded media. Keep in mind that this operation is resource-intensive, so enable it only if necessary.
+- **Include Blur Hash**: Automatically generates a BlurHash for the uploaded image, allowing you to display a blurred placeholder while the full image loads. For more information, refer to the [BlurHash](displaying-media.md#blurhash) section.
+- **Source Picker Style**: Customize the appearance of the bottom sheet UI that appears when selecting a media source (e.g., Camera or Gallery).
+- **Allow Multiple Images**: Enable this option to allow users to select multiple images. Note that this requires the **Media Source** to be set to **Gallery**. Once multiple images are uploaded, you can access their URLs via **Set from Variable menu > Widget State > Uploaded File URLs (`List`)**.
+- **Show Snackbar**: Enable this option to notify users about the upload progress with a snackbar message.
+
+Check out our YouTube video for a detailed explanation of the **Upload or Save Media [Action]** in FlutterFlow.
+
+
+
+
+
+
+
+### Store Media for Upload
+
+You can also save the media file temporarily on the device before uploading it to cloud storage by setting the **Upload Type** to [**Local Upload**](#local-upload-widget-state). This saves the file in Bytes, allowing you to preview, edit, or process it before finalizing the upload.
+
+Once the file is uploaded to the device, you can do the following:
+
+- **Preview or Validate the Media**: Show the user an in-app preview before they decide whether to finalize or discard the upload.
+
+- **Editing Before Submission**: In social media apps, users upload photos for posts or stories. The app temporarily saves the image on the device while users edit or apply filters, and then uploads the final image to cloud storage.
+- **Perform Data Operations**: In document scanning apps, users capture images of documents, which are temporarily stored on the device. The app accesses the file bytes to apply OCR (Optical Character Recognition), enhance contrast, or convert the image to PDF before uploading the final processed file to cloud storage.
+- **Offline Functionality**: Store the media locally and defer uploading until the user regains internet access.
+- **Upload to Server**: When you want to store the file externally, you can then make an API call (e.g., multipart form data) to transfer the local file. Be sure to retrieve and save the resulting file URL in your database if you plan to display it later.
+
+Here are some examples of uploading a file to a device and using it in different scenarios:
+
+**Example 1: Upload to Your Backend Server via API**
+
+First, set the **Upload/Save Media** action with the **Local Upload (Widget State)** upload type. Then, add the next action as an **API call** and select the API that will upload the file to your server. After the API call is complete, ensure your server returns the uploaded file's URL. Use this URL to save in the database or [display the uploaded image](displaying-media.md).
+
+:::info
+The request body for the API must be in *Multipart* format. See how to [**configure an API for the multipart request body**](../../resources/control-flow/backend-logic/api/rest-api.md#multipart-format).
+:::
+
+
+
+
+
+
+
+**Example 2: Compress Image Using Custom Action**
+
+First, configure the **Upload/Save Media** action with the **Local Upload (Widget State)** upload type. This temporarily saves the media file on the device.
+
+Next, create and add a [**Custom Action**](../../ff-concepts/adding-customization/custom-actions.md) (e.g., `compressImageAction`) that takes the locally stored file as input and compresses it using its **bytes** data. Ensure the custom action processes the image and returns a compressed file. Once compressed, the file can then be uploaded to cloud storage using another **Upload/Save Media** action.
+
+
+
+**Example 3: Upload to Firebase or Supabase**
+
+First, configure the **Upload/Save Media** action with the **Local Upload (Widget State)** upload type. Once the file is modified or processed, add another **Upload/Save Media** action to the widget that confirms the final upload. Set the **Upload Type** to **Firebase** or **Supabase**, choose **File Type** as the **Uploaded File**, and select **File to Upload** from **Widget State > Uploaded Local File**.
+
+
+
+
+## Upload or Save File [Action]
+
+You can upload any type of file to your app, such as PDFs, MP3s, and more. The process for uploading files is almost similar to the [Upload or Save Media Action](#upload-or-save-media-action).
+
+:::info[Web access for PDF files]
+
+If you plan to support the web version of your app or test the PDF upload feature in **Run Mode**, you’ll need to complete additional configuration steps required for certain file types (e.g., PDFs). Learn how to [**enable web access**](displaying-media.md#web-access-for-pdfs-and-other-files).
+
+:::
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/video/_category_.json b/docs/ff-concepts/file-handling/video/_category_.json
deleted file mode 100644
index 9cb05936..00000000
--- a/docs/ff-concepts/file-handling/video/_category_.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "label": "Video",
- "position": 1
-}
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/video/video-player.md b/docs/ff-concepts/file-handling/video/video-player.md
deleted file mode 100644
index 33682d18..00000000
--- a/docs/ff-concepts/file-handling/video/video-player.md
+++ /dev/null
@@ -1,271 +0,0 @@
----
-title: VideoPlayer
-slug: /concepts/file-handling/video-player
-sidebar_position: 0
-tags: [Media, Widget]
-keywords: [Media, VideoPlayer, Play Video]
----
-
-# VideoPlayer
-
-The VideoPlayer widget is used to show video from uploaded assets or the URL link. The VideoPlayer widget can play various video formats that include but are limited to MP4, MOV, WAV, MPEG, JPEG motion photo, and so on.
-
-## Adding VideoPlayer Widget
-
-Here's how you can add the VideoPlayer widget to your project:
-
-1. Drag the **VideoPlayer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Path** property and enter the **URL** for the new video.
-
-:::info
-By default, every VideoPlayer widget added to the project will show a sample video from a network URL.
-:::
-
-
-
-
-
-
-## Changing the Video Type
-
-By default, the widget is set to play a video from the internet. However, you can change this to use the video uploaded directly to your app.
-
-Here's how you can change the Video Type:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Video Type** dropdown. Click on **Network** (inside the dropdown) and select **Asset**.
-4. Now, find the **Asset Video** property, Click on the **Upload Video** button, select the video and upload it.
-
-
-
-
-
-
-If you want to use the same video multiple times in your app, you don't need to upload the same video multiple times. You can use the uploaded video for other VideoPlayer widgets as well.
-
-:::tip
-Once you upload the video, you can use it throughout your app. You can manage your uploaded videos with the Project Media Asset Manager.
-:::
-
-To use the uploaded video:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Video Type** dropdown. Click on **Network** (inside the dropdown) and select **Asset**.
-4. Click on **No asset select** (inside the dropdown) and choose the video.
-
-## Customization
-
-You can customize the appearance of this widget using the various properties available under the properties panel.
-
-### Setting Aspect Ratio
-
-Setting the *Aspect Ratio* to the VideoPlayer allows you to show video in a specific aspect ratio. The height of the widget is determined by applying the given aspect ratio to the width, expressed as a ratio of width to height. For example, setting the value of 1.7 will show the video in a 16:9 aspect ratio.
-
-To set the aspect ratio:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Aspect Ratio** property, if you want to set the aspect ratio of 16:9, enter the value as 1.7 (Simply divide the 16 by 9).
-
-:::tip
-Try changing the width of VideoPlayer and the height will be adjusted as per the aspect ratio.
-:::
-
-
-
-
-
-
-### Controlling the AutoPlay
-
-The *AutoPlay* property allows you to configure whether the video should start playing as soon as it loads. By default, this property is disabled and you have to click on the play button to start watching the video.
-
-To enable/disable auto-playing a video:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Enable the **Auto Play** property.
-
-### Enable or Disable Looping of Video
-
-The Loop Video property allows you to configure whether the video should start playing again after it ends. By default, this property is enabled and the video keeps on playing after it ends.
-
-To enable/disable the looping of video:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Loop Video** property, enable or disable to change the looping video behavior.
-
-### Show or Hide Video Controls
-
-The *Show Controls* property allows you to configure whether the player should show the controls over the video such as play-pause button, seek bar, and so on. By default, this property is enabled and all the video controls are visible over the video.
-
-To show/hide video controls:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Show Controls** property, Use it to show or hide controls over the video.
-
-
-
-
-
-
-### Controlling Full Screen
-
-The *Allow Full Screen* property allows you to configure whether the player should show the full-screen icon in video controls. By default, this property is enabled and users can open video in full-screen mode by tapping the full-screen icon at the bottom right corner of the player.
-
-To enable/disable full-screen icon:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Allow Full Screen** property, checkmark/uncheck to show/hide the full-screen mode icon.
-
-
-
-
-
-
-### Showing Playback Speed Menu
-
-The *Include Speed Playback Menu* property allows you to configure whether the player should show the playback speed menu. The playback speed menu helps users to increase or decrease the speed of the video. By default, this property is disabled.
-
-To show the playback speed menu:
-
-1. Select the **VideoPlayer** widget from the widget tree or from the canvas area.
-2. Move to the Property Editor (on the right side of your screen) and scroll down to the **Video Player** section.
-3. Find the **Include Playback Speed Menu** property, checkmark it (click on it).
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/ff-concepts/file-handling/video/youtube-player.md b/docs/ff-concepts/file-handling/video/youtube-player.md
deleted file mode 100644
index 7fb6a17e..00000000
--- a/docs/ff-concepts/file-handling/video/youtube-player.md
+++ /dev/null
@@ -1,127 +0,0 @@
----
-title: YoutubePlayer
-slug: /concepts/file-handling/youtube-player
-sidebar_position: 1
-tags: [Media, Widget]
-keywords: [Media, YoutubePlayer, Play YouTube Video]
----
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-# YoutubePlayer
-
-The **YouTubePlayer** widget in FlutterFlow allows you to seamlessly integrate and play YouTube videos within your app. It offers customizable playback options and an intuitive interface for enhancing the user experience.
-
-## Adding YoutubePlayer Widget
-
-To add the YoutubePlayer widget in your project:
-
-Simply drag the **YoutubePlayer** widget from the **Base Elements** tab (in the Widget Panel) or add it directly from the widget tree.
-
-
-
-
-
-
-## Setting The Video URL
-
-The YoutubePlayer widget uses Youtube's video URL to play the video. When you add the YoutubePlayer to your app, by default the URL is set to play a random video. You can change the Video URL by using the URL property.
-
-To set the Youtube Video URL:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **URL** property and enter the **URL** for the new video.
-
-
-
-
-
-
-
-## Control Looping Video
-
-By default, The Youtube video starts playing again after it is finished playing. You can change this behavior using the Loop Video property.
-
-To control looping:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **Loop Video** property, keep it checked for looping the video or uncheck to stop looping. Click on it.
-
-## Muting The Video
-
-To mute the video:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **Mute Video** property and click to checkmark it.
-
-## Enable or Disable Video Controls
-
-By default, when the video is being played, different controls are shown such as volume, play-pause, subtitles, fullscreen. You can enable or disable these controls using the *show controls* property.
-
-To enable or disable video controls:
-
-1. Select the **YoutubePlayer** from the widget tree or from the canvas area.
-2. Move to the Property Editor and scroll down to the **Youtube Player** section.
-3. Find the **Show Controls** property, keep it checked to show controls, or uncheck to hide the controls.
-4. (Optional) To disable the fullscreen control, uncheck the **Show Full Screen Control**.
-
-Here's how it looks on enabling and disabling the Controls:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/resources/ui/pages/page-lifecycle.md b/docs/resources/ui/pages/page-lifecycle.md
index de13aef0..1bbc4d18 100644
--- a/docs/resources/ui/pages/page-lifecycle.md
+++ b/docs/resources/ui/pages/page-lifecycle.md
@@ -158,7 +158,7 @@ To handle this, you can enable the option on the `TextField` widget to bypass ke
The **On Dispose** action trigger allows you to define actions that execute when a page is navigated away from or removed from memory. It is particularly useful for stopping ongoing operations.
-Imagine a scenario where [audio recording](../../../ff-concepts/file-handling/audio/audio-recroding.md) is started when the page loads using the [On Page Load](#on-page-load-action-trigger) action trigger. The recording process runs as long as the user remains on the page. However, when the user navigates away, you need to stop the recording to save resources and ensure the recorded audio is finalized. By using the On Dispose action trigger, you can safely stop the recording and save the file.
+Imagine a scenario where [audio recording](../../../ff-concepts/file-handling/displaying-media.md#audio-recording) is started when the page loads using the [On Page Load](#on-page-load-action-trigger) action trigger. The recording process runs as long as the user remains on the page. However, when the user navigates away, you need to stop the recording to save resources and ensure the recorded audio is finalized. By using the On Dispose action trigger, you can safely stop the recording and save the file.
Additionally, if you are using a third-party package that relies on persistent connections or listeners, you can leverage [Custom Actions](../../../ff-concepts/adding-customization/custom-actions.md) with the On Dispose action trigger to close streams or cancel subscriptions.
diff --git a/docs/resources/ui/widgets/built-in-widgets/media-display.md b/docs/resources/ui/widgets/built-in-widgets/media-display.md
index 90898310..a1b5763e 100644
--- a/docs/resources/ui/widgets/built-in-widgets/media-display.md
+++ b/docs/resources/ui/widgets/built-in-widgets/media-display.md
@@ -110,4 +110,4 @@ To customize the widget when image is displayed, refer [here](../../widgets/basi
### Customizing Video
-To customize the widget when video is displayed, refer [here](../../../../ff-concepts/file-handling/video/video-player.md#customization).
\ No newline at end of file
+To customize the widget when video is displayed, refer [here](../../../../ff-concepts/file-handling/displaying-media.md#videoplayer).
\ No newline at end of file
diff --git a/firebase.json b/firebase.json
index b21abfd2..6a8b9c09 100644
--- a/firebase.json
+++ b/firebase.json
@@ -2323,6 +2323,51 @@
"destination": "/integrations/database/cloud-firestore/firestore-content-manager/",
"type": 301
},
+ {
+ "source": "/concepts/file-handling/audio-player",
+ "destination": "/concepts/file-handling/displaying-media#audioplayer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/audio-recording",
+ "destination": "/concepts/file-handling/displaying-media#audio-recording",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/play-stop-sound",
+ "destination": "/concepts/file-handling/displaying-media#play-or-stop-sound",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/video-player",
+ "destination": "/concepts/file-handling/displaying-media#videoplayer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/youtube-player",
+ "destination": "/concepts/file-handling/displaying-media#youtubeplayer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/pdf-viewer",
+ "destination": "/concepts/file-handling/displaying-media#pdfviewer",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/upload-data",
+ "destination": "/concepts/file-handling/uploading-files",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/upload-save-file",
+ "destination": "/concepts/file-handling/uploading-files#upload-or-save-file-action",
+ "type": 301
+ },
+ {
+ "source": "/concepts/file-handling/upload-save-media",
+ "destination": "/concepts/file-handling/uploading-files#upload-or-save-media-action",
+ "type": 301
+ },
{
"source": "/concepts/state-management/generated-code",
"destination": "/generated-code/state-management",