Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
migrate file_selector_windows from cpp to dart
Browse files Browse the repository at this point in the history
Co-authored-by: Alejandro Pinola <[email protected]>
  • Loading branch information
eugerossetto and adpinola committed Nov 17, 2022
1 parent b828242 commit 24ae23b
Show file tree
Hide file tree
Showing 56 changed files with 1,932 additions and 2,422 deletions.
4 changes: 4 additions & 0 deletions packages/file_selector/file_selector_windows/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.0

* Migrates implementation from Cpp to Dart.

## 0.9.1+4

* Changes XTypeGroup initialization from final to const.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:flutter/material.dart';
/// then displays the selected directory in a dialog.
class GetDirectoryPage extends StatelessWidget {
/// Default Constructor
const GetDirectoryPage({Key? key}) : super(key: key);
const GetDirectoryPage({super.key});

Future<void> _getDirectoryPath(BuildContext context) async {
const String confirmButtonText = 'Choose';
Expand Down Expand Up @@ -58,7 +58,7 @@ class GetDirectoryPage extends StatelessWidget {
/// Widget that displays a text file in a dialog.
class TextDisplay extends StatelessWidget {
/// Creates a `TextDisplay`.
const TextDisplay(this.directoryPath, {Key? key}) : super(key: key);
const TextDisplay(this.directoryPath, {super.key});

/// The path selected in the dialog.
final String directoryPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
/// Home Page of the application.
class HomePage extends StatelessWidget {
/// Default Constructor
const HomePage({Key? key}) : super(key: key);
const HomePage({super.key});

@override
Widget build(BuildContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void main() {
/// MyApp is the Main Application.
class MyApp extends StatelessWidget {
/// Default Constructor
const MyApp({Key? key}) : super(key: key);
const MyApp({super.key});

@override
Widget build(BuildContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'package:flutter/material.dart';
/// `openFiles`, then displays the selected images in a gallery dialog.
class OpenImagePage extends StatelessWidget {
/// Default Constructor
const OpenImagePage({Key? key}) : super(key: key);
const OpenImagePage({super.key});

Future<void> _openImageFile(BuildContext context) async {
const XTypeGroup typeGroup = XTypeGroup(
Expand Down Expand Up @@ -65,8 +65,7 @@ class OpenImagePage extends StatelessWidget {
/// Widget that displays an image in a dialog.
class ImageDisplay extends StatelessWidget {
/// Default Constructor.
const ImageDisplay(this.fileName, this.filePath, {Key? key})
: super(key: key);
const ImageDisplay(this.fileName, this.filePath, {super.key});

/// The name of the selected file.
final String fileName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'package:flutter/material.dart';
/// `openFiles`, then displays the selected images in a gallery dialog.
class OpenMultipleImagesPage extends StatelessWidget {
/// Default Constructor
const OpenMultipleImagesPage({Key? key}) : super(key: key);
const OpenMultipleImagesPage({super.key});

Future<void> _openImageFile(BuildContext context) async {
const XTypeGroup jpgsTypeGroup = XTypeGroup(
Expand Down Expand Up @@ -69,7 +69,7 @@ class OpenMultipleImagesPage extends StatelessWidget {
/// Widget that displays a text file in a dialog.
class MultipleImagesDisplay extends StatelessWidget {
/// Default Constructor.
const MultipleImagesDisplay(this.files, {Key? key}) : super(key: key);
const MultipleImagesDisplay(this.files, {super.key});

/// The files containing the images.
final List<XFile> files;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';

import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
import 'package:flutter/material.dart';

/// Screen that allows the user to select a text file using `openFile`, then
/// displays its contents in a dialog.
class OpenTextPage extends StatelessWidget {
/// Default Constructor
const OpenTextPage({Key? key}) : super(key: key);
const OpenTextPage({super.key});

Future<void> _openTextFile(BuildContext context) async {
const XTypeGroup typeGroup = XTypeGroup(
Expand All @@ -23,7 +25,14 @@ class OpenTextPage extends StatelessWidget {
return;
}
final String fileName = file.name;
final String fileContent = await file.readAsString();

// This behavior defaults works when reading files encoded using UTF-16 LE.
// If you have files encoded with UTF-8 you can simply use file.readAsString()
// For other encodings, consider using Encoding.getByName() method, to get your encoder
// before calling file.readAsString()
final Uint8List bytes = await file.readAsBytes();
final Uint16List utf16CodeUnits = bytes.buffer.asUint16List();
final String fileContent = String.fromCharCodes(utf16CodeUnits);

await showDialog<void>(
context: context,
Expand Down Expand Up @@ -62,8 +71,7 @@ class OpenTextPage extends StatelessWidget {
/// Widget that displays a text file in a dialog.
class TextDisplay extends StatelessWidget {
/// Default Constructor.
const TextDisplay(this.fileName, this.fileContent, {Key? key})
: super(key: key);
const TextDisplay(this.fileName, this.fileContent, {super.key});

/// The name of the selected file.
final String fileName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
/// then writes text to a file at that location.
class SaveTextPage extends StatelessWidget {
/// Default Constructor
SaveTextPage({Key? key}) : super(key: key);
SaveTextPage({super.key});

final TextEditingController _nameController = TextEditingController();
final TextEditingController _contentController = TextEditingController();
Expand All @@ -25,10 +25,12 @@ class SaveTextPage extends StatelessWidget {
return;
}
final String text = _contentController.text;
final Uint8List fileData = Uint8List.fromList(text.codeUnits);

// This behavior saves an Utf-16 LE encoded file.
final Uint16List fileData = Uint16List.fromList(text.codeUnits);
const String fileMimeType = 'text/plain';
final XFile textFile =
XFile.fromData(fileData, mimeType: fileMimeType, name: fileName);
final XFile textFile = XFile.fromData(fileData.buffer.asUint8List(),
mimeType: fileMimeType, name: fileName);
await textFile.saveTo(path);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ publish_to: 'none'
version: 1.0.0

environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.10.0"
sdk: ">=2.17.0 <3.0.0"
flutter: ">=3.0.0"

dependencies:
file_selector_platform_interface: ^2.2.0
file_selector_platform_interface: ^2.3.0
file_selector_windows:
# When depending on this package from a real application you should use:
# file_selector_windows: ^x.y.z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#

list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,31 @@
// found in the LICENSE file.

import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
import 'package:flutter/foundation.dart';
import 'package:win32/win32.dart';

import 'src/messages.g.dart';
import 'src/file_selector_api.dart';
import 'src/file_selector_dart/dialog_wrapper_factory.dart';
import 'src/file_selector_dart/file_dialog_controller_factory.dart';
import 'src/file_selector_dart/ifile_dialog_factory.dart';
import 'src/file_selector_dart/selection_options.dart';

/// An implementation of [FileSelectorPlatform] for Windows.
class FileSelectorWindows extends FileSelectorPlatform {
final FileSelectorApi _hostApi = FileSelectorApi();
/// Creates a new instance of [FileSelectorApi].
FileSelectorWindows()
: _hostApi = FileSelectorApi(
DialogWrapperFactory(
FileDialogControllerFactory(),
IFileDialogFactory(),
),
GetActiveWindow());

/// Creates a fake implementation of [FileSelectorApi] for testing purposes.
@visibleForTesting
FileSelectorWindows.useFakeApi(this._hostApi);

final FileSelectorApi _hostApi;

/// Registers the Windows implementation.
static void registerWith() {
Expand All @@ -21,14 +40,11 @@ class FileSelectorWindows extends FileSelectorPlatform {
String? initialDirectory,
String? confirmButtonText,
}) async {
final List<String?> paths = await _hostApi.showOpenDialog(
SelectionOptions(
allowMultiple: false,
selectFolders: false,
allowedTypes: _typeGroupsFromXTypeGroups(acceptedTypeGroups),
),
initialDirectory,
confirmButtonText);
final List<String?> paths = _hostApi.showOpenDialog(
SelectionOptions(allowedTypes: _allowedXTypeGroups(acceptedTypeGroups)),
initialDirectory,
confirmButtonText,
);
return paths.isEmpty ? null : XFile(paths.first!);
}

Expand All @@ -38,14 +54,13 @@ class FileSelectorWindows extends FileSelectorPlatform {
String? initialDirectory,
String? confirmButtonText,
}) async {
final List<String?> paths = await _hostApi.showOpenDialog(
SelectionOptions(
final List<String?> paths = _hostApi.showOpenDialog(
SelectionOptions(
allowMultiple: true,
selectFolders: false,
allowedTypes: _typeGroupsFromXTypeGroups(acceptedTypeGroups),
),
initialDirectory,
confirmButtonText);
allowedTypes: _allowedXTypeGroups(acceptedTypeGroups)),
initialDirectory,
confirmButtonText,
);
return paths.map((String? path) => XFile(path!)).toList();
}

Expand All @@ -56,15 +71,12 @@ class FileSelectorWindows extends FileSelectorPlatform {
String? suggestedName,
String? confirmButtonText,
}) async {
final List<String?> paths = await _hostApi.showSaveDialog(
SelectionOptions(
allowMultiple: false,
selectFolders: false,
allowedTypes: _typeGroupsFromXTypeGroups(acceptedTypeGroups),
),
initialDirectory,
suggestedName,
confirmButtonText);
final List<String?> paths = _hostApi.showSaveDialog(
SelectionOptions(allowedTypes: _allowedXTypeGroups(acceptedTypeGroups)),
initialDirectory,
suggestedName,
confirmButtonText,
);
return paths.isEmpty ? null : paths.first!;
}

Expand All @@ -73,27 +85,23 @@ class FileSelectorWindows extends FileSelectorPlatform {
String? initialDirectory,
String? confirmButtonText,
}) async {
final List<String?> paths = await _hostApi.showOpenDialog(
SelectionOptions(
allowMultiple: false,
selectFolders: true,
allowedTypes: <TypeGroup>[],
),
initialDirectory,
confirmButtonText);
final List<String?> paths = _hostApi.showOpenDialog(
SelectionOptions(selectFolders: true, allowedTypes: <XTypeGroup>[]),
initialDirectory,
confirmButtonText,
);
return paths.isEmpty ? null : paths.first!;
}
}

List<TypeGroup> _typeGroupsFromXTypeGroups(List<XTypeGroup>? xtypes) {
List<XTypeGroup> _allowedXTypeGroups(List<XTypeGroup>? xtypes) {
return (xtypes ?? <XTypeGroup>[]).map((XTypeGroup xtype) {
if (!xtype.allowsAny && (xtype.extensions?.isEmpty ?? true)) {
throw ArgumentError('Provided type group $xtype does not allow '
'all files, but does not set any of the Windows-supported filter '
'categories. "extensions" must be non-empty for Windows if '
'anything is non-empty.');
}
return TypeGroup(
label: xtype.label ?? '', extensions: xtype.extensions ?? <String>[]);
return xtype;
}).toList();
}
Loading

0 comments on commit 24ae23b

Please sign in to comment.