198 lines
6.7 KiB
Dart
198 lines
6.7 KiB
Dart
|
import 'package:cross_file/cross_file.dart' show XFile;
|
||
|
import 'package:file_picker/file_picker.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||
|
import 'package:imagini/bloc/bloc-prov.dart';
|
||
|
import 'package:imagini/screens/upload/upload-bloc.dart';
|
||
|
import 'package:tus_client/tus_client.dart';
|
||
|
import 'package:url_launcher/url_launcher.dart';
|
||
|
|
||
|
class UploadScreen extends StatefulWidget {
|
||
|
@override
|
||
|
_UploadScreenState createState() => _UploadScreenState();
|
||
|
}
|
||
|
|
||
|
class _UploadScreenState extends State<UploadScreen> {
|
||
|
UploadBloc exampleBloc;
|
||
|
|
||
|
double _progress = 0;
|
||
|
XFile _file;
|
||
|
TusClient _client;
|
||
|
Uri _fileUrl;
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
super.initState();
|
||
|
exampleBloc = UploadBloc();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void dispose() {
|
||
|
exampleBloc.dispose();
|
||
|
super.dispose();
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return BlocProvider(
|
||
|
bloc: exampleBloc,
|
||
|
child: PlatformScaffold(
|
||
|
appBar: PlatformAppBar(
|
||
|
title: Text('Uploads'),
|
||
|
cupertino: (_, __) => CupertinoNavigationBarData(
|
||
|
// Issue with cupertino where a bar with no transparency
|
||
|
// will push the list down. Adding some alpha value fixes it (in a hacky way)
|
||
|
backgroundColor: Colors.lightGreen.withAlpha(254),
|
||
|
),
|
||
|
),
|
||
|
body: SingleChildScrollView(
|
||
|
child: Column(
|
||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||
|
children: <Widget>[
|
||
|
SizedBox(height: 12),
|
||
|
Padding(
|
||
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||
|
child: Text(
|
||
|
"This demo uses TUS client to upload a file",
|
||
|
style: TextStyle(fontSize: 18),
|
||
|
),
|
||
|
),
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.all(6),
|
||
|
child: Card(
|
||
|
color: Colors.teal,
|
||
|
child: InkWell(
|
||
|
onTap: () async {
|
||
|
_file =
|
||
|
await _getXFile(await FilePicker.platform.pickFiles());
|
||
|
setState(() {
|
||
|
_progress = 0;
|
||
|
_fileUrl = null;
|
||
|
});
|
||
|
},
|
||
|
child: Container(
|
||
|
padding: EdgeInsets.all(20),
|
||
|
child: Column(
|
||
|
children: <Widget>[
|
||
|
Icon(Icons.cloud_upload, color: Colors.white, size: 60),
|
||
|
Text(
|
||
|
"Upload a file",
|
||
|
style: TextStyle(fontSize: 25, color: Colors.white),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.all(8),
|
||
|
child: Row(
|
||
|
children: <Widget>[
|
||
|
Expanded(
|
||
|
child: RaisedButton(
|
||
|
onPressed: _file == null
|
||
|
? null
|
||
|
: () async {
|
||
|
// Create a client
|
||
|
print("Create a client");
|
||
|
_client = TusClient(
|
||
|
Uri.parse("https://master.tus.io/files/"),
|
||
|
_file,
|
||
|
store: TusMemoryStore(),
|
||
|
);
|
||
|
|
||
|
print("Starting upload");
|
||
|
await _client.upload(
|
||
|
onComplete: () async {
|
||
|
print("Completed!");
|
||
|
setState(() => _fileUrl = _client.uploadUrl);
|
||
|
},
|
||
|
onProgress: (progress) {
|
||
|
print("Progress: $progress");
|
||
|
setState(() => _progress = progress);
|
||
|
},
|
||
|
);
|
||
|
},
|
||
|
child: Text("Upload"),
|
||
|
),
|
||
|
),
|
||
|
SizedBox(width: 8),
|
||
|
Expanded(
|
||
|
child: RaisedButton(
|
||
|
onPressed: _progress == 0
|
||
|
? null
|
||
|
: () async {
|
||
|
_client.pause();
|
||
|
},
|
||
|
child: Text("Pause"),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
Stack(
|
||
|
children: <Widget>[
|
||
|
Container(
|
||
|
margin: const EdgeInsets.all(8),
|
||
|
padding: const EdgeInsets.all(1),
|
||
|
color: Colors.grey,
|
||
|
width: double.infinity,
|
||
|
child: Text(" "),
|
||
|
),
|
||
|
FractionallySizedBox(
|
||
|
widthFactor: _progress / 100,
|
||
|
child: Container(
|
||
|
margin: const EdgeInsets.all(8),
|
||
|
padding: const EdgeInsets.all(1),
|
||
|
color: Colors.green,
|
||
|
child: Text(" "),
|
||
|
),
|
||
|
),
|
||
|
Container(
|
||
|
margin: const EdgeInsets.all(8),
|
||
|
padding: const EdgeInsets.all(1),
|
||
|
width: double.infinity,
|
||
|
child: Text("Progress: ${_progress.toStringAsFixed(1)}%"),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
GestureDetector(
|
||
|
onTap: _progress != 100
|
||
|
? null
|
||
|
: () async {
|
||
|
await launch(_fileUrl.toString());
|
||
|
},
|
||
|
child: Container(
|
||
|
color: _progress == 100 ? Colors.green : Colors.grey,
|
||
|
padding: const EdgeInsets.all(8.0),
|
||
|
margin: const EdgeInsets.all(8.0),
|
||
|
child:
|
||
|
Text(_progress == 100 ? "Link to view:\n $_fileUrl" : "-"),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
Future<XFile> _getXFile(FilePickerResult result) async {
|
||
|
if (result != null) {
|
||
|
final chosenFile = result.files.first;
|
||
|
if (chosenFile.path != null) {
|
||
|
// Android, iOS, Desktop
|
||
|
return XFile(chosenFile.path);
|
||
|
} else {
|
||
|
// Web
|
||
|
return XFile.fromData(
|
||
|
chosenFile.bytes,
|
||
|
name: chosenFile.name,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|