diff --git a/CHANGELOG.md b/CHANGELOG.md index facdff9e..74043dca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 7.0.2 +### Desktop (Linux) +File picker extensions for Linux Zenity are case insensitive now +Fixes [#1322](https://github.com/miguelpruivo/flutter_file_picker/issues/1322) + ## 6.2.1 ### Desktop (Windows) The `initialDirectory` parameter of `getDirectoryPath()` now works ([#970](https://github.com/miguelpruivo/flutter_file_picker/issues/970)). @@ -30,10 +35,13 @@ Fix several warnings in the iOS plugin implementation. ### iOS Fix if selecting from gallery multiple files from remote sources (eg GoPro, Drone) imported to the device gallery and uploaded to iCloud they would have the same file name and it shows only one image repeated Fix returned images are in different onder from the gallery selection + ## 5.3.4 fix [#1317](https://github.com/miguelpruivo/flutter_file_picker/issues/1317) + ## 5.3.3 fix [#1312](https://github.com/miguelpruivo/flutter_file_picker/issues/1312) + ## 5.3.2 ### Desktop (Windows) Bumps the dependency `win32` to 5.0.2 ([#1281](https://github.com/miguelpruivo/flutter_file_picker/pull/1281)). Thank you @frg2089! diff --git a/lib/src/linux/dialog_handler.dart b/lib/src/linux/dialog_handler.dart index 82e3a5fa..6826447e 100644 --- a/lib/src/linux/dialog_handler.dart +++ b/lib/src/linux/dialog_handler.dart @@ -2,6 +2,8 @@ import 'package:file_picker/file_picker.dart'; import 'package:file_picker/src/linux/kdialog_handler.dart'; import 'package:file_picker/src/linux/qarma_and_zenity_handler.dart'; +import '../utils.dart'; + abstract class DialogHandler { factory DialogHandler(String pathToExecutable) { pathToExecutable = pathToExecutable.toLowerCase(); @@ -40,4 +42,12 @@ abstract class DialogHandler { /// Converts the result string (stdout) of `qarma`, `zenity` or `kdialog` /// into a [List] of file paths. List resultStringToFilePaths(String fileSelectionResult); + + static String toCaseInsensitive(String filter) { + return filter + .split("") + .map((e) => + isAlpha(e) ? "[" + e.toLowerCase() + e.toUpperCase() + "]" : e) + .join(); + } } diff --git a/lib/src/linux/kdialog_handler.dart b/lib/src/linux/kdialog_handler.dart index 6b94f553..8d37c93f 100644 --- a/lib/src/linux/kdialog_handler.dart +++ b/lib/src/linux/kdialog_handler.dart @@ -56,15 +56,15 @@ class KDialogHandler implements DialogHandler { case FileType.any: return ''; case FileType.audio: - return 'Audio File (*.aac *.midi *.mp3 *.ogg *.wav)'; + return 'Audio File (${DialogHandler.toCaseInsensitive("*.aac *.midi *.mp3 *.ogg *.wav")})'; case FileType.custom: - return '${allowedExtensions!.map((ext) => ext.toUpperCase()).join(' File, ')} File (*.${allowedExtensions.join(' *.')})'; + return '${allowedExtensions!.map((ext) => ext.toUpperCase()).join(' File, ')} File (${DialogHandler.toCaseInsensitive("*.${allowedExtensions.join(' *.')}")})'; case FileType.image: - return 'Image File (*.bmp *.gif *.jpeg *.jpg *.png)'; + return 'Image File (${DialogHandler.toCaseInsensitive("*.bmp *.gif *.jpeg *.jpg *.png")})'; case FileType.media: - return 'Media File (*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv *.bmp *.gif *.jpeg *.jpg *.png)'; + return 'Media File (${DialogHandler.toCaseInsensitive("*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv *.bmp *.gif *.jpeg *.jpg *.png")})'; case FileType.video: - return 'Video File (*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv)'; + return 'Video File (${DialogHandler.toCaseInsensitive("*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv")})'; default: throw Exception('unknown file type'); } diff --git a/lib/src/linux/qarma_and_zenity_handler.dart b/lib/src/linux/qarma_and_zenity_handler.dart index 3089a0d5..03bcb736 100644 --- a/lib/src/linux/qarma_and_zenity_handler.dart +++ b/lib/src/linux/qarma_and_zenity_handler.dart @@ -48,15 +48,15 @@ class QarmaAndZenityHandler implements DialogHandler { case FileType.any: return ''; case FileType.audio: - return '*.aac *.midi *.mp3 *.ogg *.wav'; + return "Audio Files | ${DialogHandler.toCaseInsensitive('*.aac *.midi *.mp3 *.ogg *.wav')}"; case FileType.custom: - return '*.${allowedExtensions!.join(' *.')}'; + return "Custom Files | ${DialogHandler.toCaseInsensitive('*.${allowedExtensions!.join(' *.')}')}"; case FileType.image: - return '*.bmp *.gif *.jpeg *.jpg *.png'; + return "Image Files | ${DialogHandler.toCaseInsensitive('*.bmp *.gif *.jpeg *.jpg *.png')}"; case FileType.media: - return '*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv *.bmp *.gif *.jpeg *.jpg *.png'; + return "Media Files | ${DialogHandler.toCaseInsensitive('*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv *.bmp *.gif *.jpeg *.jpg *.png')}"; case FileType.video: - return '*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv'; + return "Video Files | ${DialogHandler.toCaseInsensitive('*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv')}"; default: throw Exception('unknown file type'); } diff --git a/lib/src/utils.dart b/lib/src/utils.dart index be1c83eb..a62ba1b6 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -63,3 +63,9 @@ Future isExecutableOnPath(String executable) async { } return path; } + +bool isAlpha(String x) { + int codeUnit = x.codeUnitAt(0); + return 'a'.codeUnitAt(0) <= codeUnit && codeUnit <= 'z'.codeUnitAt(0) || + 'A'.codeUnitAt(0) <= codeUnit && codeUnit <= 'Z'.codeUnitAt(0); +} diff --git a/pubspec.yaml b/pubspec.yaml index 9533bc31..db136768 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A package that allows you to use a native file explorer to pick sin homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker repository: https://github.com/miguelpruivo/flutter_file_picker issue_tracker: https://github.com/miguelpruivo/flutter_file_picker/issues -version: 6.2.1 +version: 7.0.2 dependencies: flutter: diff --git a/test/file_picker_utils_test.dart b/test/file_picker_utils_test.dart index 0eb16856..79351e0b 100644 --- a/test/file_picker_utils_test.dart +++ b/test/file_picker_utils_test.dart @@ -1,5 +1,4 @@ @TestOn('linux || mac-os') - import 'dart:io'; import 'package:file_picker/src/utils.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -143,4 +142,16 @@ void main() { ); }); }); + + group('isAlpha()', () { + test('should identify alpha chars', () async { + expect(isAlpha('a'), equals(true)); + expect(isAlpha('A'), equals(true)); + expect(isAlpha('z'), equals(true)); + expect(isAlpha('Z'), equals(true)); + expect(isAlpha('.'), equals(false)); + expect(isAlpha('*'), equals(false)); + expect(isAlpha(' '), equals(false)); + }); + }); } diff --git a/test/linux/kdialog_handler_test.dart b/test/linux/kdialog_handler_test.dart index 1e724780..77f98903 100644 --- a/test/linux/kdialog_handler_test.dart +++ b/test/linux/kdialog_handler_test.dart @@ -1,5 +1,4 @@ @TestOn('linux') - import 'package:file_picker/src/file_picker.dart'; import 'package:file_picker/src/linux/kdialog_handler.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -21,25 +20,27 @@ void main() { expect( dialogHandler.fileTypeToFileFilter(FileType.audio, null), - equals('Audio File (*.aac *.midi *.mp3 *.ogg *.wav)'), + equals( + 'Audio File (*.[aA][aA][cC] *.[mM][iI][dD][iI] *.[mM][pP]3 *.[oO][gG][gG] *.[wW][aA][vV])'), ); expect( dialogHandler.fileTypeToFileFilter(FileType.image, null), - equals('Image File (*.bmp *.gif *.jpeg *.jpg *.png)'), + equals( + 'Image File (*.[bB][mM][pP] *.[gG][iI][fF] *.[jJ][pP][eE][gG] *.[jJ][pP][gG] *.[pP][nN][gG])'), ); expect( dialogHandler.fileTypeToFileFilter(FileType.media, null), equals( - 'Media File (*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv *.bmp *.gif *.jpeg *.jpg *.png)', + 'Media File (*.[aA][vV][iI] *.[fF][lL][vV] *.[mM][kK][vV] *.[mM][oO][vV] *.[mM][pP]4 *.[mM][pP][eE][gG] *.[wW][eE][bB][mM] *.[wW][mM][vV] *.[bB][mM][pP] *.[gG][iI][fF] *.[jJ][pP][eE][gG] *.[jJ][pP][gG] *.[pP][nN][gG])', ), ); expect( dialogHandler.fileTypeToFileFilter(FileType.video, null), equals( - 'Video File (*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv)'), + 'Video File (*.[aA][vV][iI] *.[fF][lL][vV] *.[mM][kK][vV] *.[mM][oO][vV] *.[mM][pP]4 *.[mM][pP][eE][gG] *.[wW][eE][bB][mM] *.[wW][mM][vV])'), ); }); @@ -48,12 +49,12 @@ void main() { expect( dialogHandler.fileTypeToFileFilter(FileType.custom, ['dart']), - equals('DART File (*.dart)'), + equals('DART File (*.[dD][aA][rR][tT])'), ); expect( dialogHandler.fileTypeToFileFilter(FileType.custom, ['dart', 'html']), - equals('DART File, HTML File (*.dart *.html)'), + equals('DART File, HTML File (*.[dD][aA][rR][tT] *.[hH][tT][mM][lL])'), ); }); }); diff --git a/test/linux/qarma_and_zenity_handler_test.dart b/test/linux/qarma_and_zenity_handler_test.dart index 15784ac3..59d3bc01 100644 --- a/test/linux/qarma_and_zenity_handler_test.dart +++ b/test/linux/qarma_and_zenity_handler_test.dart @@ -1,5 +1,4 @@ @TestOn('linux') - import 'package:file_picker/src/file_picker.dart'; import 'package:file_picker/src/linux/qarma_and_zenity_handler.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -20,24 +19,27 @@ void main() { expect( dialogHandler.fileTypeToFileFilter(FileType.audio, null), - equals('*.aac *.midi *.mp3 *.ogg *.wav'), + equals( + 'Audio Files | *.[aA][aA][cC] *.[mM][iI][dD][iI] *.[mM][pP]3 *.[oO][gG][gG] *.[wW][aA][vV]'), ); expect( dialogHandler.fileTypeToFileFilter(FileType.image, null), - equals('*.bmp *.gif *.jpeg *.jpg *.png'), + equals( + 'Image Files | *.[bB][mM][pP] *.[gG][iI][fF] *.[jJ][pP][eE][gG] *.[jJ][pP][gG] *.[pP][nN][gG]'), ); expect( dialogHandler.fileTypeToFileFilter(FileType.media, null), equals( - '*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv *.bmp *.gif *.jpeg *.jpg *.png', + 'Media Files | *.[aA][vV][iI] *.[fF][lL][vV] *.[mM][kK][vV] *.[mM][oO][vV] *.[mM][pP]4 *.[mM][pP][eE][gG] *.[wW][eE][bB][mM] *.[wW][mM][vV] *.[bB][mM][pP] *.[gG][iI][fF] *.[jJ][pP][eE][gG] *.[jJ][pP][gG] *.[pP][nN][gG]', ), ); expect( dialogHandler.fileTypeToFileFilter(FileType.video, null), - equals('*.avi *.flv *.mkv *.mov *.mp4 *.mpeg *.webm *.wmv'), + equals( + 'Video Files | *.[aA][vV][iI] *.[fF][lL][vV] *.[mM][kK][vV] *.[mM][oO][vV] *.[mM][pP]4 *.[mM][pP][eE][gG] *.[wW][eE][bB][mM] *.[wW][mM][vV]'), ); }); @@ -46,12 +48,12 @@ void main() { expect( dialogHandler.fileTypeToFileFilter(FileType.custom, ['dart']), - equals('*.dart'), + equals('Custom Files | *.[dD][aA][rR][tT]'), ); expect( dialogHandler.fileTypeToFileFilter(FileType.custom, ['dart', 'html']), - equals('*.dart *.html'), + equals('Custom Files | *.[dD][aA][rR][tT] *.[hH][tT][mM][lL]'), ); }); });