Merge pull request #1383 from krille-chan/krille/use-file-selector-on-linux

refactor: Use file selector on linux
This commit is contained in:
Krille-chan 2024-10-03 21:37:40 +02:00 committed by GitHub
commit 44bd4db774
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 144 additions and 89 deletions

View file

@ -10,7 +10,6 @@ import 'package:collection/collection.dart';
import 'package:desktop_drop/desktop_drop.dart'; import 'package:desktop_drop/desktop_drop.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -29,11 +28,11 @@ import 'package:fluffychat/pages/chat/event_info_dialog.dart';
import 'package:fluffychat/pages/chat/recording_dialog.dart'; import 'package:fluffychat/pages/chat/recording_dialog.dart';
import 'package:fluffychat/pages/chat_details/chat_details.dart'; import 'package:fluffychat/pages/chat_details/chat_details.dart';
import 'package:fluffychat/utils/error_reporter.dart'; import 'package:fluffychat/utils/error_reporter.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import '../../utils/account_bundles.dart'; import '../../utils/account_bundles.dart';
import '../../utils/localized_exception_extension.dart'; import '../../utils/localized_exception_extension.dart';
@ -481,17 +480,12 @@ class ChatController extends State<ChatPageWithRoom>
} }
void sendFileAction() async { void sendFileAction() async {
final result = await AppLock.of(context).pauseWhile( final files = await selectFiles(context, allowMultiple: true);
FilePicker.platform.pickFiles( if (files.isEmpty) return;
compressionQuality: 0,
allowMultiple: true,
),
);
if (result == null || result.files.isEmpty) return;
await showAdaptiveDialog( await showAdaptiveDialog(
context: context, context: context,
builder: (c) => SendFileDialog( builder: (c) => SendFileDialog(
files: result.xFiles, files: files,
room: room, room: room,
outerContext: context, outerContext: context,
), ),
@ -511,19 +505,17 @@ class ChatController extends State<ChatPageWithRoom>
} }
void sendImageAction() async { void sendImageAction() async {
final result = await AppLock.of(context).pauseWhile( final files = await selectFiles(
FilePicker.platform.pickFiles( context,
compressionQuality: 0, allowMultiple: true,
type: FileType.image, extensions: imageExtensions,
allowMultiple: true,
),
); );
if (result == null || result.files.isEmpty) return; if (files.isEmpty) return;
await showAdaptiveDialog( await showAdaptiveDialog(
context: context, context: context,
builder: (c) => SendFileDialog( builder: (c) => SendFileDialog(
files: result.xFiles, files: files,
room: room, room: room,
outerContext: context, outerContext: context,
), ),

View file

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -11,9 +10,9 @@ import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/chat_details/chat_details_view.dart'; import 'package:fluffychat/pages/chat_details/chat_details_view.dart';
import 'package:fluffychat/pages/settings/settings.dart'; import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
enum AliasActions { copy, delete, setCanonical } enum AliasActions { copy, delete, setCanonical }
@ -165,16 +164,15 @@ class ChatDetailsController extends State<ChatDetails> {
name: result.path, name: result.path,
); );
} else { } else {
final picked = await AppLock.of(context).pauseWhile( final picked = await selectFiles(
FilePicker.platform.pickFiles( context,
type: FileType.image, allowMultiple: false,
withData: true, extensions: imageExtensions,
),
); );
final pickedFile = picked?.files.firstOrNull; final pickedFile = picked.firstOrNull;
if (pickedFile == null) return; if (pickedFile == null) return;
file = MatrixFile( file = MatrixFile(
bytes: pickedFile.bytes!, bytes: await pickedFile.readAsBytes(),
name: pickedFile.name, name: pickedFile.name,
); );
} }

View file

@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -15,8 +14,8 @@ import 'package:universal_html/html.dart' as html;
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import '../../utils/localized_exception_extension.dart'; import '../../utils/localized_exception_extension.dart';
@ -201,10 +200,8 @@ class HomeserverPickerController extends State<HomeserverPicker> {
Widget build(BuildContext context) => HomeserverPickerView(this); Widget build(BuildContext context) => HomeserverPickerView(this);
Future<void> restoreBackup() async { Future<void> restoreBackup() async {
final picked = await AppLock.of(context).pauseWhile( final picked = await selectFiles(context);
FilePicker.platform.pickFiles(withData: true), final file = picked.firstOrNull;
);
final file = picked?.files.firstOrNull;
if (file == null) return; if (file == null) return;
setState(() { setState(() {
error = null; error = null;
@ -212,7 +209,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
}); });
try { try {
final client = Matrix.of(context).getLoginClient(); final client = Matrix.of(context).getLoginClient();
await client.importDump(String.fromCharCodes(file.bytes!)); await client.importDump(String.fromCharCodes(await file.readAsBytes()));
Matrix.of(context).initMatrix(); Matrix.of(context).initMatrix();
} catch (e) { } catch (e) {
setState(() { setState(() {

View file

@ -2,11 +2,11 @@ import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart' as sdk;
import 'package:fluffychat/pages/new_group/new_group_view.dart'; import 'package:fluffychat/pages/new_group/new_group_view.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
class NewGroup extends StatefulWidget { class NewGroup extends StatefulWidget {
@ -35,15 +35,16 @@ class NewGroupController extends State<NewGroup> {
void setGroupCanBeFound(bool b) => setState(() => groupCanBeFound = b); void setGroupCanBeFound(bool b) => setState(() => groupCanBeFound = b);
void selectPhoto() async { void selectPhoto() async {
final photo = await FilePicker.platform.pickFiles( final photo = await selectFiles(
type: FileType.image, context,
extensions: imageExtensions,
allowMultiple: false, allowMultiple: false,
withData: true,
); );
final bytes = await photo.singleOrNull?.readAsBytes();
setState(() { setState(() {
avatarUrl = null; avatarUrl = null;
avatar = photo?.files.singleOrNull?.bytes; avatar = bytes;
}); });
} }

View file

@ -2,13 +2,13 @@ import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart' as sdk;
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/new_space/new_space_view.dart'; import 'package:fluffychat/pages/new_space/new_space_view.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
@ -32,15 +32,14 @@ class NewSpaceController extends State<NewSpace> {
Uri? avatarUrl; Uri? avatarUrl;
void selectPhoto() async { void selectPhoto() async {
final photo = await FilePicker.platform.pickFiles( final photo = await selectFiles(
type: FileType.image, context,
allowMultiple: false, extensions: imageExtensions,
withData: true,
); );
final bytes = await photo.firstOrNull?.readAsBytes();
setState(() { setState(() {
avatarUrl = null; avatarUrl = null;
avatar = photo?.files.singleOrNull?.bytes; avatar = bytes;
}); });
} }

View file

@ -4,14 +4,13 @@ import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
import '../bootstrap/bootstrap_dialog.dart'; import '../bootstrap/bootstrap_dialog.dart';
import 'settings_view.dart'; import 'settings_view.dart';
@ -136,16 +135,11 @@ class SettingsController extends State<Settings> {
name: result.path, name: result.path,
); );
} else { } else {
final result = await AppLock.of(context).pauseWhile( final result = await selectFiles(context, extensions: imageExtensions);
FilePicker.platform.pickFiles( final pickedFile = result.firstOrNull;
type: FileType.image,
withData: true,
),
);
final pickedFile = result?.files.firstOrNull;
if (pickedFile == null) return; if (pickedFile == null) return;
file = MatrixFile( file = MatrixFile(
bytes: pickedFile.bytes!, bytes: await pickedFile.readAsBytes(),
name: pickedFile.name, name: pickedFile.name,
); );
} }

View file

@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@ -13,8 +12,8 @@ import 'package:http/http.dart' hide Client;
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/client_manager.dart'; import 'package:fluffychat/utils/client_manager.dart';
import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
import 'import_archive_dialog.dart'; import 'import_archive_dialog.dart';
import 'settings_emotes_view.dart'; import 'settings_emotes_view.dart';
@ -222,16 +221,11 @@ class EmotesSettingsController extends State<EmotesSettings> {
void imagePickerAction( void imagePickerAction(
ValueNotifier<ImagePackImageContent?> controller, ValueNotifier<ImagePackImageContent?> controller,
) async { ) async {
final result = await AppLock.of(context).pauseWhile( final result = await selectFiles(context, extensions: imageExtensions);
FilePicker.platform.pickFiles( final pickedFile = result.firstOrNull;
type: FileType.image,
withData: true,
),
);
final pickedFile = result?.files.firstOrNull;
if (pickedFile == null) return; if (pickedFile == null) return;
var file = MatrixImageFile( var file = MatrixImageFile(
bytes: pickedFile.bytes!, bytes: await pickedFile.readAsBytes(),
name: pickedFile.name, name: pickedFile.name,
); );
try { try {
@ -282,21 +276,17 @@ class EmotesSettingsController extends State<EmotesSettings> {
final result = await showFutureLoadingDialog<Archive?>( final result = await showFutureLoadingDialog<Archive?>(
context: context, context: context,
future: () async { future: () async {
final result = await AppLock.of(context).pauseWhile( final result = await selectFiles(
FilePicker.platform.pickFiles( context,
type: FileType.custom, extensions: [
allowedExtensions: [ 'zip',
'zip', // TODO: add further encoders
// TODO: add further encoders ],
],
// TODO: migrate to stream, currently brrrr because of `archive_io`.
withData: true,
),
); );
if (result == null) return null; if (result.isEmpty) return null;
final buffer = InputStream(result.files.single.bytes); final buffer = InputStream(await result.first.readAsBytes());
final archive = ZipDecoder().decodeBuffer(buffer); final archive = ZipDecoder().decodeBuffer(buffer);

View file

@ -1,12 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/utils/account_config.dart'; import 'package:fluffychat/utils/account_config.dart';
import 'package:fluffychat/widgets/app_lock.dart'; import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/widgets/theme_builder.dart'; import 'package:fluffychat/widgets/theme_builder.dart';
import '../../widgets/matrix.dart'; import '../../widgets/matrix.dart';
import 'settings_style_view.dart'; import 'settings_style_view.dart';
@ -26,20 +25,15 @@ class SettingsStyleController extends State<SettingsStyle> {
void setWallpaper() async { void setWallpaper() async {
final client = Matrix.of(context).client; final client = Matrix.of(context).client;
final picked = await AppLock.of(context).pauseWhile( final picked = await selectFiles(context, extensions: imageExtensions);
FilePicker.platform.pickFiles( final pickedFile = picked.firstOrNull;
type: FileType.image,
withData: true,
),
);
final pickedFile = picked?.files.firstOrNull;
if (pickedFile == null) return; if (pickedFile == null) return;
await showFutureLoadingDialog( await showFutureLoadingDialog(
context: context, context: context,
future: () async { future: () async {
final url = await client.uploadContent( final url = await client.uploadContent(
pickedFile.bytes!, await pickedFile.readAsBytes(),
filename: pickedFile.name, filename: pickedFile.name,
); );
await client.updateApplicationAccountConfig( await client.updateApplicationAccountConfig(

View file

@ -0,0 +1,57 @@
import 'package:flutter/widgets.dart';
import 'package:file_picker/file_picker.dart';
import 'package:file_selector/file_selector.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
Future<List<XFile>> selectFiles(
BuildContext context, {
String? title,
List<String>? extensions,
bool allowMultiple = false,
}) async {
if (!PlatformInfos.isLinux) {
final result = await AppLock.of(context).pauseWhile(
FilePicker.platform.pickFiles(
compressionQuality: 0,
allowMultiple: allowMultiple,
allowedExtensions: extensions,
),
);
return result?.xFiles ?? [];
}
if (allowMultiple) {
return await AppLock.of(context).pauseWhile(
openFiles(
confirmButtonText: title,
acceptedTypeGroups: [
if (extensions != null) XTypeGroup(extensions: extensions),
],
),
);
}
final file = await AppLock.of(context).pauseWhile(
openFile(
confirmButtonText: title,
acceptedTypeGroups: [
if (extensions != null) XTypeGroup(extensions: extensions),
],
),
);
if (file == null) return [];
return [file];
}
const imageExtensions = [
'png',
'PNG',
'jpg',
'JPG',
'jpeg',
'JPEG',
'webp',
'WebP',
];

View file

@ -382,6 +382,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.1.2" version: "8.1.2"
file_selector:
dependency: "direct main"
description:
name: file_selector
sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
file_selector_android:
dependency: transitive
description:
name: file_selector_android
sha256: b8c9717a0177ca6fa035554b82cd6c83b838ddc66b7704eb6df0f77f027ecc90
url: "https://pub.dev"
source: hosted
version: "0.5.1+7"
file_selector_ios:
dependency: transitive
description:
name: file_selector_ios
sha256: "38ebf91ecbcfa89a9639a0854ccaed8ab370c75678938eebca7d34184296f0bb"
url: "https://pub.dev"
source: hosted
version: "0.5.3"
file_selector_linux: file_selector_linux:
dependency: transitive dependency: transitive
description: description:
@ -406,6 +430,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.2" version: "2.6.2"
file_selector_web:
dependency: transitive
description:
name: file_selector_web
sha256: c4c0ea4224d97a60a7067eca0c8fd419e708ff830e0c83b11a48faf566cec3e7
url: "https://pub.dev"
source: hosted
version: "0.9.4+2"
file_selector_windows: file_selector_windows:
dependency: transitive dependency: transitive
description: description:

View file

@ -27,6 +27,7 @@ dependencies:
emojis: ^0.9.9 emojis: ^0.9.9
#fcm_shared_isolate: ^0.1.0 #fcm_shared_isolate: ^0.1.0
file_picker: ^8.1.2 file_picker: ^8.1.2
file_selector: ^1.0.3
flutter: flutter:
sdk: flutter sdk: flutter
flutter_app_badger: ^1.5.0 flutter_app_badger: ^1.5.0

View file

@ -132,5 +132,5 @@ index 69c80d6e..efd32d89 100644
- #fcm_shared_isolate: ^0.1.0 - #fcm_shared_isolate: ^0.1.0
+ fcm_shared_isolate: ^0.1.0 + fcm_shared_isolate: ^0.1.0
file_picker: ^8.1.2 file_picker: ^8.1.2
file_selector: ^1.0.3
flutter: flutter:
sdk: flutter