Skip to content
Shiny.NET

Folders

NuGet package Shiny.AppDeviceBridge.Folders

The folders bridge shows the platform’s folder picker and makes the picked folder a file root, remembered across launches. FolderRoots adds folders the app maps by path — see Settings, Files & Folders.

Terminal window
dotnet add package Shiny.AppDeviceBridge.Folders
builder.UseAppDeviceBridge(
bridge => bridge.AddFoldersBridge(),
webApp => { /* … */ }
);
Client C# TypeScript
IFoldersBridge AddFoldersBridgeClient() FoldersBridge
  • Picking: POST folders/pick with { "root": "documents" } shows the platform’s folder picker. The folder becomes a file root under that name — /_bridge/files/documents/… — and answers 204 if the user cancels. Picking again under the same name replaces the folder. The app’s own roots can’t be replaced.

  • Remembered: picked folders come back as roots every time the app starts, until DELETE folders/{root} forgets one. GET folders lists them, with available: false for one that was moved, deleted or had its access revoked since.

  • Platforms: Apple platforms keep a security-scoped bookmark; Android keeps a persisted Storage Access Framework grant; Windows and Linux (GTK’s file dialog) keep the path.

  • Android folders aren’t paths. The files bridge reads and writes them through the Storage Access Framework, but bridges that hand the OS a file path — sharing, transfers, notification images — refuse them.

  • A plain net10.0 project that references it (a shared setup project that mobile heads also use) compiles against the Linux build, which references GirCore. GirCore’s source generators then run in that project, and the code they add references GTK’s assemblies, which a mobile app doesn’t ship. iOS stops at launch with Could not find GLib-2.0. Remove the generators in that project’s csproj:

    <Target Name="_DropGirCoreGenerators" AfterTargets="ResolveLockFileAnalyzers">
    <ItemGroup>
    <Analyzer Remove="@(Analyzer)" Condition="$([System.String]::Copy('%(Analyzer.NuGetPackageId)').StartsWith('GirCore.'))" />
    </ItemGroup>
    </Target>
import { FoldersBridge, FilesBridge } from "@shinyorg/appdevicebridge";
const folder = await new FoldersBridge().pick({ title: "Choose a project folder" });
if (folder) {
// the pick is now a file root like any other
const entries = await new FilesBridge().list(folder.root);
}
GET/_bridge/folders#

Whether folders can be picked here, and the folders picked so far.

C#IFoldersBridge.GetFoldersAsyncTSFoldersBridge.getFolders
Response
200 FolderList
FolderList · 2 fields
supportedbooleanWhether this platform has a folder picker.
foldersPickedFolder[]
POST/_bridge/folders/pick#

Shows the folder picker. Null when the user cancels. Picking again under a root name already in use replaces that folder; the app's own roots (data, cache) cannot be replaced.

C#IFoldersBridge.PickAsyncTSFoldersBridge.pick
Body
application/json · FolderPickRequest
FolderPickRequest · 2 fields
rootstring | nullThe file root name to give the folder: 1–64 letters, digits, - or _. One is chosen when null.
titlestring | nullThe picker's title, where the platform shows one.
Response
200 PickedFolder · or 204 when there is none
PickedFolder · 3 fields
rootstringThe file root name the files bridge knows the folder by.
displayNamestringThe folder's name as the user saw it in the picker.
availablebooleanFalse when the folder was moved, deleted or its access revoked since it was picked.
DELETE/_bridge/folders/{root}#

Forgets a picked folder: its root goes away and the app gives up its access to it.

C#IFoldersBridge.ForgetAsyncTSFoldersBridge.forget
ParameterInType
rootpathstringrequired
Response
204 No content

This bridge raises no events — everything it does is a request and its response.

JSON property names are camelCase and enums travel as their names. A ? marks a property the payload may omit;| null one that may be null.

FolderListobject#
supportedbooleanWhether this platform has a folder picker.
foldersPickedFolder[]
PickedFolderobject#
rootstringThe file root name the files bridge knows the folder by.
displayNamestringThe folder's name as the user saw it in the picker.
availablebooleanFalse when the folder was moved, deleted or its access revoked since it was picked.
FolderPickRequestobject#
root?string | nullThe file root name to give the folder: 1–64 letters, digits, - or _. One is chosen when null.
title?string | nullThe picker's title, where the platform shows one.

These routes sit under AppDeviceBridgePolicies.Bridges like every other bridge: callers on this device by default. See Security.