Factor out showFilePicker into a generic controller
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
3d85883f8e
commit
c6192ef736
|
@ -0,0 +1,3 @@
|
||||||
|
const int MaxImageFileSharingSize = 20971520;
|
||||||
|
|
||||||
|
const int MaxGeneralImageFileSharingSize = 10737418240;
|
|
@ -0,0 +1,30 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:cwtch/models/appstate.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
void showFilePicker(BuildContext ctx, int maxBytes, Function(File) onSuccess, Function onCancel, Function onError) async {
|
||||||
|
// only allow one file picker at a time
|
||||||
|
// note: ideally we would destroy file picker when leaving a conversation
|
||||||
|
// but we don't currently have that option.
|
||||||
|
// we need to store AppState in a variable because ctx might be destroyed
|
||||||
|
// while awaiting for pickFiles.
|
||||||
|
var appstate = Provider.of<AppState>(ctx, listen: false);
|
||||||
|
appstate.disableFilePicker = true;
|
||||||
|
// currently lockParentWindow only works on Windows...
|
||||||
|
FilePickerResult? result = await FilePicker.platform.pickFiles(lockParentWindow: true);
|
||||||
|
appstate.disableFilePicker = false;
|
||||||
|
if (result != null && result.files.first.path != null) {
|
||||||
|
File file = File(result.files.first.path!);
|
||||||
|
// We have a maximum number of bytes we can represent in terms of
|
||||||
|
// a manifest (see : https://git.openprivacy.ca/cwtch.im/cwtch/src/branch/master/protocol/files/manifest.go#L25)
|
||||||
|
if (file.lengthSync() <= maxBytes) {
|
||||||
|
onSuccess(file);
|
||||||
|
} else {
|
||||||
|
onError();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onCancel();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:cwtch/config.dart';
|
import 'package:cwtch/config.dart';
|
||||||
import 'package:cwtch/cwtch/cwtch.dart';
|
import 'package:cwtch/cwtch/cwtch.dart';
|
||||||
import 'package:cwtch/models/appstate.dart';
|
import 'package:cwtch/models/appstate.dart';
|
||||||
import 'package:cwtch/models/profile.dart';
|
import 'package:cwtch/models/profile.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:cwtch/controllers/filesharing.dart' as filesharing;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:cwtch/widgets/buttontextfield.dart';
|
import 'package:cwtch/widgets/buttontextfield.dart';
|
||||||
|
@ -17,6 +15,7 @@ import 'package:cwtch/widgets/textfield.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
|
import '../constants.dart';
|
||||||
import '../cwtch_icons_icons.dart';
|
import '../cwtch_icons_icons.dart';
|
||||||
import '../errorHandler.dart';
|
import '../errorHandler.dart';
|
||||||
import '../main.dart';
|
import '../main.dart';
|
||||||
|
@ -68,37 +67,6 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showFilePicker(BuildContext ctx) async {
|
|
||||||
// only allow one file picker at a time
|
|
||||||
// note: ideally we would destroy file picker when leaving a conversation
|
|
||||||
// but we don't currently have that option.
|
|
||||||
// we need to store AppState in a variable because ctx might be destroyed
|
|
||||||
// while awaiting for pickFiles.
|
|
||||||
var appstate = Provider.of<AppState>(ctx, listen: false);
|
|
||||||
appstate.disableFilePicker = true;
|
|
||||||
// currently lockParentWindow only works on Windows...
|
|
||||||
FilePickerResult? result = await FilePicker.platform.pickFiles(lockParentWindow: true);
|
|
||||||
appstate.disableFilePicker = false;
|
|
||||||
if (result != null && result.files.first.path != null) {
|
|
||||||
File file = File(result.files.first.path!);
|
|
||||||
// We have a maximum number of bytes we can represent in terms of
|
|
||||||
// a manifest (see : https://git.openprivacy.ca/cwtch.im/cwtch/src/branch/master/protocol/files/manifest.go#L25)
|
|
||||||
if (file.lengthSync() <= 10737418240) {
|
|
||||||
var profile = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
|
||||||
// Share this image publically (conversation handle == -1)
|
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.ShareFile(profile, -1, file.path);
|
|
||||||
// update the image cache locally
|
|
||||||
Provider.of<ProfileInfoState>(context, listen: false).imagePath = file.path;
|
|
||||||
} else {
|
|
||||||
final snackBar = SnackBar(
|
|
||||||
content: Text(AppLocalizations.of(context)!.msgFileTooBig),
|
|
||||||
duration: Duration(seconds: 4),
|
|
||||||
);
|
|
||||||
ScaffoldMessenger.of(ctx).showSnackBar(snackBar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A few implementation notes
|
// A few implementation notes
|
||||||
// We use Visibility to hide optional structures when they are not requested.
|
// We use Visibility to hide optional structures when they are not requested.
|
||||||
// We used SizedBox for inter-widget height padding in columns, otherwise elements can render a little too close together.
|
// We used SizedBox for inter-widget height padding in columns, otherwise elements can render a little too close together.
|
||||||
|
@ -125,9 +93,23 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
||||||
MouseRegion(
|
MouseRegion(
|
||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: Provider.of<AppState>(context).disableFilePicker
|
||||||
_showFilePicker(context);
|
? null
|
||||||
},
|
: () {
|
||||||
|
filesharing.showFilePicker(context, MaxImageFileSharingSize, (File file) {
|
||||||
|
var profile = Provider.of<ProfileInfoState>(context, listen: false).onion;
|
||||||
|
// Share this image publicly (conversation handle == -1)
|
||||||
|
Provider.of<FlwtchState>(context, listen: false).cwtch.ShareFile(profile, -1, file.path);
|
||||||
|
// update the image cache locally
|
||||||
|
Provider.of<ProfileInfoState>(context, listen: false).imagePath = file.path;
|
||||||
|
}, () {
|
||||||
|
final snackBar = SnackBar(
|
||||||
|
content: Text(AppLocalizations.of(context)!.msgFileTooBig),
|
||||||
|
duration: Duration(seconds: 4),
|
||||||
|
);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
|
}, () {});
|
||||||
|
},
|
||||||
child: ProfileImage(
|
child: ProfileImage(
|
||||||
imagePath: Provider.of<ProfileInfoState>(context).imagePath,
|
imagePath: Provider.of<ProfileInfoState>(context).imagePath,
|
||||||
diameter: 120,
|
diameter: 120,
|
||||||
|
|
|
@ -11,7 +11,7 @@ import 'package:cwtch/models/profile.dart';
|
||||||
import 'package:cwtch/widgets/malformedbubble.dart';
|
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||||
import 'package:cwtch/widgets/messageloadingbubble.dart';
|
import 'package:cwtch/widgets/messageloadingbubble.dart';
|
||||||
import 'package:cwtch/widgets/profileimage.dart';
|
import 'package:cwtch/widgets/profileimage.dart';
|
||||||
|
import 'package:cwtch/controllers/filesharing.dart' as filesharing;
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
@ -23,6 +23,7 @@ import 'package:provider/provider.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||||
|
|
||||||
|
import '../constants.dart';
|
||||||
import '../main.dart';
|
import '../main.dart';
|
||||||
import '../settings.dart';
|
import '../settings.dart';
|
||||||
import '../widgets/messagelist.dart';
|
import '../widgets/messagelist.dart';
|
||||||
|
@ -92,7 +93,16 @@ class _MessageViewState extends State<MessageView> {
|
||||||
onPressed: Provider.of<AppState>(context).disableFilePicker
|
onPressed: Provider.of<AppState>(context).disableFilePicker
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
_showFilePicker(context);
|
imagePreview = null;
|
||||||
|
filesharing.showFilePicker(context, MaxGeneralImageFileSharingSize, (File file) {
|
||||||
|
_confirmFileSend(context, file.path);
|
||||||
|
}, () {
|
||||||
|
final snackBar = SnackBar(
|
||||||
|
content: Text(AppLocalizations.of(context)!.msgFileTooBig),
|
||||||
|
duration: Duration(seconds: 4),
|
||||||
|
);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
|
}, () {});
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -415,36 +425,6 @@ class _MessageViewState extends State<MessageView> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showFilePicker(BuildContext ctx) async {
|
|
||||||
imagePreview = null;
|
|
||||||
|
|
||||||
// only allow one file picker at a time
|
|
||||||
// note: ideally we would destroy file picker when leaving a conversation
|
|
||||||
// but we don't currently have that option.
|
|
||||||
// we need to store AppState in a variable because ctx might be destroyed
|
|
||||||
// while awaiting for pickFiles.
|
|
||||||
var appstate = Provider.of<AppState>(ctx, listen: false);
|
|
||||||
appstate.disableFilePicker = true;
|
|
||||||
// currently lockParentWindow only works on Windows...
|
|
||||||
FilePickerResult? result = await FilePicker.platform.pickFiles(lockParentWindow: true);
|
|
||||||
appstate.disableFilePicker = false;
|
|
||||||
if (result != null && result.files.first.path != null) {
|
|
||||||
File file = File(result.files.first.path!);
|
|
||||||
// We have a maximum number of bytes we can represent in terms of
|
|
||||||
// a manifest (see : https://git.openprivacy.ca/cwtch.im/cwtch/src/branch/master/protocol/files/manifest.go#L25)
|
|
||||||
if (file.lengthSync() <= 10737418240) {
|
|
||||||
print("Sending " + file.path);
|
|
||||||
_confirmFileSend(ctx, file.path);
|
|
||||||
} else {
|
|
||||||
final snackBar = SnackBar(
|
|
||||||
content: Text(AppLocalizations.of(context)!.msgFileTooBig),
|
|
||||||
duration: Duration(seconds: 4),
|
|
||||||
);
|
|
||||||
ScaffoldMessenger.of(ctx).showSnackBar(snackBar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _confirmFileSend(BuildContext ctx, String path) async {
|
void _confirmFileSend(BuildContext ctx, String path) async {
|
||||||
showModalBottomSheet<void>(
|
showModalBottomSheet<void>(
|
||||||
context: ctx,
|
context: ctx,
|
||||||
|
|
Loading…
Reference in New Issue