Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public static void HideDialog( bool invokeCancelCallback = false );

If there is an open dialog and the **invokeCancelCallback** parameter is set to *true*, the *onCancel* callback of the dialog will be invoked. This function can also be used to initialize the file browser ahead of time, which in turn will reduce the lag when you first open a dialog.

To add a quick link to the browser, you can use the following function:
To add a quick link to the browser, you can use the following function (to clear all quick links, use `ClearQuickLinks()`):

```csharp
public static bool AddQuickLink( string name, string path, Sprite icon = null );
Expand Down Expand Up @@ -130,6 +130,18 @@ When **showAllFilesFilter** is set to true, a filter by the name "*All Files (.\
public static bool SetDefaultFilter( string defaultFilter );
```

You can programmatically filter the files/folders displayed in the file browser via the **DisplayedEntriesFilter** event:

```csharp
FileBrowser.DisplayedEntriesFilter += ( entry ) =>
{
if( !entry.IsDirectory )
return true; // Don't filter files

return entry.Name.StartsWith( "Save" ); // Show only the directories whose name start with "Save"
};
```

You can set whether or not hidden files should be shown in the file browser via **FileBrowser.ShowHiddenFiles** (has no effect when Storage Access Framework is used on Android 10+). This value can also be changed from the "*Show hidden files*" toggle in the user interface. To change the visibility of that toggle, you can use **FileBrowser.DisplayHiddenFilesToggle**. Note that this toggle is always hidden on Android 10+ when Storage Access Framework is used or on mobile devices when device is held in portrait orientation.

To open files or directories in the file browser with a single click (instead of double clicking), you can set **FileBrowser.SingleClickMode** to *true*.
Expand Down
6 changes: 6 additions & 0 deletions Plugins/SimpleFileBrowser/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ void HideDialog( bool invokeCancelCallback = false );

// Customizing the dialog
bool AddQuickLink( string name, string path, Sprite icon = null );
void ClearQuickLinks();

void SetExcludedExtensions( params string[] excludedExtensions );

// Filters should include the period (e.g. ".jpg" instead of "jpg")
Expand All @@ -79,6 +81,10 @@ void SetFilters( bool showAllFilesFilter, params FileBrowser.Filter[] filters );

bool SetDefaultFilter( string defaultFilter );

// Filtering displayed files/folders programmatically
delegate bool FileSystemEntryFilter( FileSystemEntry entry );
event FileSystemEntryFilter DisplayedEntriesFilter;

// Android runtime permissions
FileBrowser.Permission CheckPermission();
FileBrowser.Permission RequestPermission();
Expand Down
131 changes: 110 additions & 21 deletions Plugins/SimpleFileBrowser/Scripts/FileBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,32 @@ public static bool SingleClickMode
set { m_singleClickMode = value; }
}

private static FileSystemEntryFilter m_displayedEntriesFilter;
public static event FileSystemEntryFilter DisplayedEntriesFilter
{
add
{
m_displayedEntriesFilter -= value;
m_displayedEntriesFilter += value;

if( m_instance )
{
m_instance.PersistFileEntrySelection();
m_instance.RefreshFiles( false );
}
}
remove
{
m_displayedEntriesFilter -= value;

if( m_instance )
{
m_instance.PersistFileEntrySelection();
m_instance.RefreshFiles( false );
}
}
}

#if UNITY_EDITOR || ( !UNITY_ANDROID && !UNITY_IOS && !UNITY_WSA && !UNITY_WSA_10_0 )
private static float m_drivesRefreshInterval = 5f;
#else
Expand Down Expand Up @@ -531,11 +557,14 @@ private string CurrentPath
get { return m_currentPath; }
set
{
if( value != null )
{
value = value.Trim();
#if !UNITY_EDITOR && UNITY_ANDROID
if( !FileBrowserHelpers.ShouldUseSAF )
if( !FileBrowserHelpers.ShouldUseSAFForPath( value ) )
#endif
if( value != null )
value = GetPathWithoutTrailingDirectorySeparator( value.Trim() );
value = GetPathWithoutTrailingDirectorySeparator( value );
}

if( string.IsNullOrEmpty( value ) )
{
Expand Down Expand Up @@ -571,10 +600,22 @@ private string CurrentPath
forwardButton.interactable = currentPathIndex < pathsFollowed.Count - 1;
#if !UNITY_EDITOR && UNITY_ANDROID
if( FileBrowserHelpers.ShouldUseSAF )
upButton.interactable = !string.IsNullOrEmpty( FileBrowserHelpers.GetDirectoryName( m_currentPath ) );
{
string parentPath = FileBrowserHelpers.GetDirectoryName( m_currentPath );
upButton.interactable = !string.IsNullOrEmpty( parentPath ) && ( FileBrowserHelpers.ShouldUseSAFForPath( parentPath ) || FileBrowserHelpers.DirectoryExists( parentPath ) ); // DirectoryExists: Directory may not be accessible on Android 10+, this function checks that
}
else
#endif
upButton.interactable = Directory.GetParent( m_currentPath ) != null;
{
try // When "C:/" or "C:" is typed instead of "C:\", an exception is thrown
{
upButton.interactable = Directory.GetParent( m_currentPath ) != null;
}
catch
{
upButton.interactable = false;
}
}

m_searchString = string.Empty;
searchInputField.text = m_searchString;
Expand All @@ -592,7 +633,7 @@ private string CurrentPath
// If a quick link points to this directory, highlight it
#if !UNITY_EDITOR && UNITY_ANDROID
// Path strings aren't deterministic on Storage Access Framework but the paths' absolute parts usually are
if( FileBrowserHelpers.ShouldUseSAF )
if( FileBrowserHelpers.ShouldUseSAFForPath( m_currentPath ) )
{
int SAFAbsolutePathSeparatorIndex = m_currentPath.LastIndexOf( '/' );
if( SAFAbsolutePathSeparatorIndex >= 0 )
Expand Down Expand Up @@ -718,6 +759,7 @@ private string LastBrowsedFolder
#region Delegates
public delegate void OnSuccess( string[] paths );
public delegate void OnCancel();
public delegate bool FileSystemEntryFilter( FileSystemEntry entry );
#if UNITY_EDITOR || UNITY_ANDROID
public delegate void AndroidSAFDirectoryPickCallback( string rawUri, string name );
#endif
Expand Down Expand Up @@ -1238,15 +1280,21 @@ public void OnUpButtonPressed()
if( FileBrowserHelpers.ShouldUseSAF )
{
string parentPath = FileBrowserHelpers.GetDirectoryName( m_currentPath );
if( !string.IsNullOrEmpty( parentPath ) )
if( !string.IsNullOrEmpty( parentPath ) && ( FileBrowserHelpers.ShouldUseSAFForPath( parentPath ) || FileBrowserHelpers.DirectoryExists( parentPath ) ) ) // DirectoryExists: Directory may not be accessible on Android 10+, this function checks that
CurrentPath = parentPath;
}
else
#endif
{
DirectoryInfo parentPath = Directory.GetParent( m_currentPath );
if( parentPath != null )
CurrentPath = parentPath.FullName;
try // When "C:/" or "C:" is typed instead of "C:\", an exception is thrown
{
DirectoryInfo parentPath = Directory.GetParent( m_currentPath );
if( parentPath != null )
CurrentPath = parentPath.FullName;
}
catch
{
}
}
}

Expand Down Expand Up @@ -1420,7 +1468,7 @@ public void OnSubmitButtonClicked()
}

#if !UNITY_EDITOR && UNITY_ANDROID
if( FileBrowserHelpers.ShouldUseSAF )
if( FileBrowserHelpers.ShouldUseSAFForPath( m_currentPath ) )
{
if( m_pickerMode == PickMode.Folders )
result[fileCount++] = FileBrowserHelpers.CreateFolderInDirectory( m_currentPath, filename );
Expand Down Expand Up @@ -1646,7 +1694,7 @@ public void OnItemSelected( FileBrowserItem item, bool isDoubleClick )
{
// Enter the directory
#if !UNITY_EDITOR && UNITY_ANDROID
if( FileBrowserHelpers.ShouldUseSAF )
if( FileBrowserHelpers.ShouldUseSAFForPath( m_currentPath ) )
{
for( int i = 0; i < validFileEntries.Count; i++ )
{
Expand Down Expand Up @@ -1903,8 +1951,13 @@ public void RefreshFiles( bool pathChanged )
continue;
}

if( m_searchString.Length == 0 || textComparer.IndexOf( item.Name, m_searchString, textCompareOptions ) >= 0 )
validFileEntries.Add( item );
if( m_searchString.Length > 0 && textComparer.IndexOf( item.Name, m_searchString, textCompareOptions ) < 0 )
continue;

if( m_displayedEntriesFilter != null && !m_displayedEntriesFilter( item ) )
continue;

validFileEntries.Add( item );
}
catch( Exception e )
{
Expand Down Expand Up @@ -1943,7 +1996,7 @@ public void RefreshFiles( bool pathChanged )
listView.UpdateList();

// Prevent the case where all the content stays offscreen after changing the search string
filesScrollRect.OnScroll( nullPointerEventData );
EnsureScrollViewIsWithinBounds();
}

// Quickly selects all files and folders in the current directory
Expand Down Expand Up @@ -2164,7 +2217,7 @@ private bool AddQuickLink( Sprite icon, string name, string path )
return false;

#if !UNITY_EDITOR && UNITY_ANDROID
if( !FileBrowserHelpers.ShouldUseSAF )
if( !FileBrowserHelpers.ShouldUseSAFForPath( path ) )
#endif
{
if( !Directory.Exists( path ) )
Expand Down Expand Up @@ -2200,6 +2253,39 @@ private bool AddQuickLink( Sprite icon, string name, string path )
return true;
}

private void ClearQuickLinksInternal()
{
Vector2 anchoredPos = Vector2.zero;
for( int i = 0; i < allQuickLinks.Count; i++ )
{
if( allQuickLinks[i].TargetPath == SAF_PICK_FOLDER_QUICK_LINK_PATH )
{
allQuickLinks[i].TransformComponent.anchoredPosition = anchoredPos;
anchoredPos.y -= m_skin.FileHeight;
}
else
{
Destroy( allQuickLinks[i].gameObject );
allQuickLinks.RemoveAt( i-- );
}
}

quickLinksContainer.sizeDelta = new Vector2( 0f, -anchoredPos.y );

quickLinksInitialized = true;
generateQuickLinksForDrives = false;
}

// Makes sure that scroll view's contents are within scroll view's bounds
private void EnsureScrollViewIsWithinBounds()
{
// When scrollbar is snapped to the very bottom of the scroll view, sometimes OnScroll alone doesn't work
if( filesScrollRect.verticalNormalizedPosition <= Mathf.Epsilon )
filesScrollRect.verticalNormalizedPosition = 0.0001f;

filesScrollRect.OnScroll( nullPointerEventData );
}

internal void EnsureWindowIsWithinBounds()
{
Vector2 canvasSize = rectTransform.sizeDelta;
Expand Down Expand Up @@ -2267,7 +2353,7 @@ internal void OnWindowDimensionsChanged( Vector2 size )
showHiddenFilesToggle.gameObject.SetActive( m_displayHiddenFilesToggle );

listView.OnViewportDimensionsChanged();
filesScrollRect.OnScroll( nullPointerEventData );
EnsureScrollViewIsWithinBounds();
}
}
else
Expand All @@ -2285,7 +2371,7 @@ internal void OnWindowDimensionsChanged( Vector2 size )
showHiddenFilesToggle.gameObject.SetActive( false );

listView.OnViewportDimensionsChanged();
filesScrollRect.OnScroll( nullPointerEventData );
EnsureScrollViewIsWithinBounds();
}
}
}
Expand Down Expand Up @@ -2610,10 +2696,8 @@ public static IEnumerator WaitForLoadDialog( PickMode pickMode, bool allowMultiS

public static bool AddQuickLink( string name, string path, Sprite icon = null )
{
#if !UNITY_EDITOR && UNITY_ANDROID
if( FileBrowserHelpers.ShouldUseSAF )
if( string.IsNullOrEmpty( path ) || !FileBrowserHelpers.DirectoryExists( path ) )
return false;
#endif

if( !quickLinksInitialized )
{
Expand All @@ -2627,6 +2711,11 @@ public static bool AddQuickLink( string name, string path, Sprite icon = null )
return Instance.AddQuickLink( icon, name, path );
}

public static void ClearQuickLinks()
{
Instance.ClearQuickLinksInternal();
}

public static void SetExcludedExtensions( params string[] excludedExtensions )
{
Instance.excludedExtensions = excludedExtensions ?? new string[0];
Expand Down
Loading