@@ -103,6 +103,8 @@ public override string ToString()
103
103
private const string FOLDERS_FILTER_TEXT = "Folders" ;
104
104
private string DEFAULT_PATH ;
105
105
106
+ private const int FILENAME_INPUT_FIELD_MAX_FILE_COUNT = 7 ;
107
+
106
108
#if ! UNITY_EDITOR && UNITY_ANDROID
107
109
private const string SAF_PICK_FOLDER_QUICK_LINK_TEXT = "Pick Folder" ;
108
110
private const string SAF_PICK_FOLDER_QUICK_LINK_PATH = "SAF_PICK_FOLDER" ;
@@ -365,13 +367,19 @@ private string CurrentPath
365
367
if ( value != null )
366
368
value = GetPathWithoutTrailingDirectorySeparator ( value . Trim ( ) ) ;
367
369
368
- if ( value == null )
370
+ if ( string . IsNullOrEmpty ( value ) )
371
+ {
372
+ pathInputField . text = m_currentPath ;
369
373
return ;
374
+ }
370
375
371
376
if ( m_currentPath != value )
372
377
{
373
378
if ( ! FileBrowserHelpers . DirectoryExists ( value ) )
379
+ {
380
+ pathInputField . text = m_currentPath ;
374
381
return ;
382
+ }
375
383
376
384
m_currentPath = value ;
377
385
pathInputField . text = m_currentPath ;
@@ -404,7 +412,10 @@ private string CurrentPath
404
412
405
413
filenameImage . color = Color . white ;
406
414
if ( m_folderSelectMode )
415
+ {
407
416
filenameInputField . text = string . Empty ;
417
+ filenameInputField . interactable = true ;
418
+ }
408
419
}
409
420
410
421
m_multiSelectionToggleSelectionMode = false ;
@@ -465,8 +476,8 @@ private bool FolderSelectMode
465
476
}
466
477
467
478
Text placeholder = filenameInputField . placeholder as Text ;
468
- if ( placeholder != null )
469
- placeholder . text = m_folderSelectMode ? string . Empty : "Filename" ;
479
+ if ( placeholder )
480
+ placeholder . gameObject . SetActive ( ! m_folderSelectMode ) ;
470
481
}
471
482
}
472
483
}
@@ -873,64 +884,85 @@ public void OnSubmitButtonClicked()
873
884
return ;
874
885
}
875
886
876
- // In the first iteration, verify that all filenames entered to the input field are valid
877
- // ExtractFilenameFromInput doesn't use Substring, so this iteration is GC-free
878
- int startIndex = 0 , nextStartIndex ;
879
- int fileCount = 0 ;
880
- int indexOfDirectoryEntryToOpen = - 1 ;
881
- while ( startIndex < filenameInput . Length )
887
+ if ( m_allowMultiSelection && selectedFileEntries . Count > 1 )
882
888
{
883
- int filenameLength = ExtractFilenameFromInput ( filenameInput , ref startIndex , out nextStartIndex ) ;
884
- if ( filenameLength == 0 )
885
- continue ;
889
+ // When multiple files are selected via file browser UI, filenameInputField is not interactable and will show
890
+ // only the first FILENAME_INPUT_FIELD_MAX_FILE_COUNT entries for performance reasons. We should iterate over
891
+ // selectedFileEntries instead of filenameInputField
886
892
887
- if ( m_acceptNonExistingFilename )
888
- fileCount ++ ;
889
- else
893
+ // Beforehand, check if a folder is selected in file selection mode. If so, open that directory
894
+ if ( ! m_folderSelectMode )
890
895
{
891
- int fileEntryIndex = FilenameInputToFileEntryIndex ( filenameInput , startIndex , filenameLength ) ;
892
- if ( fileEntryIndex < 0 )
893
- {
894
- // File doesn't exist
895
- filenameImage . color = wrongFilenameColor ;
896
- return ;
897
- }
898
-
899
- if ( validFileEntries [ fileEntryIndex ] . IsDirectory )
896
+ for ( int i = 0 ; i < selectedFileEntries . Count ; i ++ )
900
897
{
901
- if ( m_folderSelectMode )
902
- fileCount ++ ;
903
- else
898
+ if ( validFileEntries [ selectedFileEntries [ i ] ] . IsDirectory )
904
899
{
905
- // Selected a directory in file selection mode, we'll open that directory if no files are selected
906
- indexOfDirectoryEntryToOpen = fileEntryIndex ;
900
+ CurrentPath = validFileEntries [ selectedFileEntries [ i ] ] . Path ;
901
+ return ;
907
902
}
908
903
}
904
+ }
905
+
906
+ string [ ] result = new string [ selectedFileEntries . Count ] ;
907
+ for ( int i = 0 ; i < selectedFileEntries . Count ; i ++ )
908
+ result [ i ] = validFileEntries [ selectedFileEntries [ i ] ] . Path ;
909
+
910
+ OnOperationSuccessful ( result ) ;
911
+ }
912
+ else
913
+ {
914
+ // When multiple files aren't selected via file browser UI, we must consider the rare case where user manually enters
915
+ // multiple filenames to filenameInputField in format "file1" "file2" and so on. So, we must parse filenameInputField
916
+
917
+ // In the first iteration, verify that all filenames entered to the input field are valid
918
+ // ExtractFilenameFromInput doesn't use Substring, so this iteration is GC-free
919
+ int fileCount = 0 ;
920
+ int startIndex = 0 , nextStartIndex ;
921
+ while ( startIndex < filenameInput . Length )
922
+ {
923
+ int filenameLength = ExtractFilenameFromInput ( filenameInput , ref startIndex , out nextStartIndex ) ;
924
+ if ( filenameLength == 0 )
925
+ continue ;
926
+
927
+ if ( m_acceptNonExistingFilename )
928
+ fileCount ++ ;
909
929
else
910
930
{
911
- if ( ! m_folderSelectMode )
912
- fileCount ++ ;
913
- else
931
+ int fileEntryIndex = FilenameInputToFileEntryIndex ( filenameInput , startIndex , filenameLength ) ;
932
+ if ( fileEntryIndex < 0 )
914
933
{
915
- // Can 't select a file in folder selection mode
934
+ // File doesn 't exist
916
935
filenameImage . color = wrongFilenameColor ;
917
936
return ;
918
937
}
938
+
939
+ if ( ! validFileEntries [ fileEntryIndex ] . IsDirectory )
940
+ fileCount ++ ;
941
+ else
942
+ {
943
+ if ( m_folderSelectMode )
944
+ fileCount ++ ;
945
+ else
946
+ {
947
+ // Selected a directory in file selection mode, open that directory
948
+ CurrentPath = validFileEntries [ fileEntryIndex ] . Path ;
949
+ return ;
950
+ }
951
+ }
919
952
}
953
+
954
+ startIndex = nextStartIndex ;
920
955
}
921
956
922
- startIndex = nextStartIndex ;
923
- }
957
+ if ( fileCount == 0 )
958
+ {
959
+ filenameImage . color = wrongFilenameColor ;
960
+ return ;
961
+ }
924
962
925
- if ( indexOfDirectoryEntryToOpen >= 0 )
926
- CurrentPath = validFileEntries [ indexOfDirectoryEntryToOpen ] . Path ;
927
- else if ( fileCount == 0 )
928
- filenameImage . color = wrongFilenameColor ;
929
- else
930
- {
963
+ // In the second iteration, extract filenames from the input field
931
964
string [ ] result = new string [ fileCount ] ;
932
965
933
- // In the second iteration, extract filenames from the input field
934
966
startIndex = 0 ;
935
967
fileCount = 0 ;
936
968
while ( startIndex < filenameInput . Length )
@@ -1271,6 +1303,7 @@ public void Show( string initialPath )
1271
1303
filesScrollRect . verticalNormalizedPosition = 1 ;
1272
1304
1273
1305
filenameInputField . text = string . Empty ;
1306
+ filenameInputField . interactable = true ;
1274
1307
filenameImage . color = Color . white ;
1275
1308
1276
1309
IsOpen = true ;
@@ -1376,6 +1409,14 @@ public void RefreshFiles( bool pathChanged )
1376
1409
pendingFileEntrySelection . Clear ( ) ;
1377
1410
}
1378
1411
1412
+ if ( ! filenameInputField . interactable && selectedFileEntries . Count <= 1 )
1413
+ {
1414
+ filenameInputField . interactable = true ;
1415
+
1416
+ if ( selectedFileEntries . Count == 0 )
1417
+ filenameInputField . text = string . Empty ;
1418
+ }
1419
+
1379
1420
listView . UpdateList ( ) ;
1380
1421
1381
1422
// Prevent the case where all the content stays offscreen after changing the search string
@@ -1412,6 +1453,8 @@ public void DeselectAllFiles()
1412
1453
MultiSelectionToggleSelectionMode = false ;
1413
1454
1414
1455
filenameInputField . text = string . Empty ;
1456
+ filenameInputField . interactable = true ;
1457
+
1415
1458
listView . UpdateList ( ) ;
1416
1459
}
1417
1460
@@ -1431,6 +1474,9 @@ private IEnumerator CreateNewFolderCoroutine()
1431
1474
selectedFileEntries . Clear ( ) ;
1432
1475
MultiSelectionToggleSelectionMode = false ;
1433
1476
1477
+ filenameInputField . text = string . Empty ;
1478
+ filenameInputField . interactable = true ;
1479
+
1434
1480
listView . UpdateList ( ) ;
1435
1481
}
1436
1482
@@ -1546,16 +1592,7 @@ public void DeleteSelectedFiles()
1546
1592
1547
1593
selectedFileEntries . Sort ( ) ;
1548
1594
1549
- Sprite [ ] icons = new Sprite [ selectedFileEntries . Count ] ;
1550
- string [ ] filenames = new string [ selectedFileEntries . Count ] ;
1551
- for ( int i = 0 ; i < selectedFileEntries . Count ; i ++ )
1552
- {
1553
- FileSystemEntry fileInfo = validFileEntries [ selectedFileEntries [ i ] ] ;
1554
- icons [ i ] = GetIconForFileEntry ( fileInfo ) ;
1555
- filenames [ i ] = fileInfo . Name ;
1556
- }
1557
-
1558
- deleteConfirmationPanel . Show ( icons , filenames , ( ) =>
1595
+ deleteConfirmationPanel . Show ( this , validFileEntries , selectedFileEntries , ( ) =>
1559
1596
{
1560
1597
for ( int i = selectedFileEntries . Count - 1 ; i >= 0 ; i -- )
1561
1598
{
@@ -1702,7 +1739,7 @@ internal void OnWindowDimensionsChanged( Vector2 size )
1702
1739
}
1703
1740
}
1704
1741
1705
- private Sprite GetIconForFileEntry ( FileSystemEntry fileInfo )
1742
+ internal Sprite GetIconForFileEntry ( FileSystemEntry fileInfo )
1706
1743
{
1707
1744
Sprite icon ;
1708
1745
if ( fileInfo . IsDirectory )
@@ -1741,7 +1778,7 @@ private void UpdateFilenameInputFieldWithSelection()
1741
1778
// Refresh filenameInputField as follows:
1742
1779
// 0 files selected: *blank*
1743
1780
// 1 file selected: file.Name
1744
- // 2+ files selected: "file1.Name" "file2.Name" ...
1781
+ // 2+ files selected: "file1.Name" "file2.Name" ... (up to FILENAME_INPUT_FIELD_MAX_FILE_COUNT filenames are displayed for performance reasons)
1745
1782
int filenameContributingFileCount = 0 ;
1746
1783
if ( FolderSelectMode )
1747
1784
filenameContributingFileCount = selectedFileEntries . Count ;
@@ -1750,10 +1787,17 @@ private void UpdateFilenameInputFieldWithSelection()
1750
1787
for ( int i = 0 ; i < selectedFileEntries . Count ; i ++ )
1751
1788
{
1752
1789
if ( ! validFileEntries [ selectedFileEntries [ i ] ] . IsDirectory )
1790
+ {
1753
1791
filenameContributingFileCount ++ ;
1792
+
1793
+ if ( filenameContributingFileCount >= FILENAME_INPUT_FIELD_MAX_FILE_COUNT )
1794
+ break ;
1795
+ }
1754
1796
}
1755
1797
}
1756
1798
1799
+ filenameInputField . interactable = selectedFileEntries . Count <= 1 ;
1800
+
1757
1801
if ( filenameContributingFileCount == 0 )
1758
1802
filenameInputField . text = string . Empty ;
1759
1803
else
@@ -1766,7 +1810,7 @@ private void UpdateFilenameInputFieldWithSelection()
1766
1810
multiSelectionFilenameBuilder . Length = 0 ;
1767
1811
}
1768
1812
1769
- for ( int i = 0 ; i < selectedFileEntries . Count ; i ++ )
1813
+ for ( int i = 0 , fileCount = 0 ; i < selectedFileEntries . Count ; i ++ )
1770
1814
{
1771
1815
FileSystemEntry selectedFile = validFileEntries [ selectedFileEntries [ i ] ] ;
1772
1816
if ( FolderSelectMode || ! selectedFile . IsDirectory )
@@ -1777,7 +1821,15 @@ private void UpdateFilenameInputFieldWithSelection()
1777
1821
break ;
1778
1822
}
1779
1823
else
1824
+ {
1780
1825
multiSelectionFilenameBuilder . Append ( "\" " ) . Append ( selectedFile . Name ) . Append ( "\" " ) ;
1826
+
1827
+ if ( ++ fileCount >= FILENAME_INPUT_FIELD_MAX_FILE_COUNT )
1828
+ {
1829
+ multiSelectionFilenameBuilder . Append ( "..." ) ;
1830
+ break ;
1831
+ }
1832
+ }
1781
1833
}
1782
1834
}
1783
1835
0 commit comments