10: Fixed input colors in login view when using dark theme; Added removal of individual files selected for upload; Added size for individual files selected for upload; Replaced intent sharing library with flutter_sharing_intent
This commit is contained in:
parent
a65c7d9253
commit
a5dab51765
9 changed files with 158 additions and 140 deletions
|
@ -1,6 +1,10 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
## 1.5.2+18
|
## 1.5.2+18
|
||||||
|
* Fixed input colors in login view when using dark theme
|
||||||
|
* Added removal of individual files selected for upload
|
||||||
|
* Added size for individual files selected for upload
|
||||||
|
* Replaced intent sharing library with `flutter_sharing_intent`
|
||||||
* Added proper linting to project
|
* Added proper linting to project
|
||||||
|
|
||||||
## 1.5.1+17
|
## 1.5.1+17
|
||||||
|
|
|
@ -21,46 +21,6 @@
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="text/*" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="video/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="video/*" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
</dict>
|
</dict>
|
||||||
<dict/>
|
<dict/>
|
||||||
</array>
|
</array>
|
||||||
// TODO follow steps 2) on create share extension (https://pub.dev/packages/receive_sharing_intent)
|
// TODO follow steps on create share extension (https://pub.dev/packages/flutter_sharing_intent)
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>Allow to select photos and upload them via the app</string>
|
<string>Allow to select photos and upload them via the app</string>
|
||||||
<key>LSApplicationQueriesSchemes</key>
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
|
|
@ -80,6 +80,7 @@ class BaseModel extends ChangeNotifier {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_logger.d("Calling dispose");
|
||||||
super.dispose();
|
super.dispose();
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,11 @@ import 'dart:io';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
|
||||||
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
import 'package:flutter_translate/flutter_translate.dart';
|
import 'package:flutter_translate/flutter_translate.dart';
|
||||||
import 'package:logger/logger.dart';
|
import 'package:logger/logger.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
|
||||||
|
|
||||||
import '../../locator.dart';
|
import '../../locator.dart';
|
||||||
import '../enums/error_code.dart';
|
import '../enums/error_code.dart';
|
||||||
|
@ -45,6 +46,41 @@ class UploadModel extends BaseModel {
|
||||||
|
|
||||||
TextEditingController get pasteTextController => _pasteTextController;
|
TextEditingController get pasteTextController => _pasteTextController;
|
||||||
|
|
||||||
|
void _parseIntentFiles(List<SharedFile> files) {
|
||||||
|
if (files.isNotEmpty) {
|
||||||
|
setStateView(ViewState.busy);
|
||||||
|
|
||||||
|
paths = files.map((sharedFile) {
|
||||||
|
_logger.d("Shared file name: ${basename(sharedFile.value ?? '')}");
|
||||||
|
_logger.d("Shared file path: ${sharedFile.value}");
|
||||||
|
_logger.d(
|
||||||
|
"Shared file size: ${File(sharedFile.value ?? '').lengthSync()}");
|
||||||
|
_logger.d("Shared file type: ${sharedFile.type}");
|
||||||
|
return PlatformFile.fromMap({
|
||||||
|
'path': sharedFile.value,
|
||||||
|
'name': basename(sharedFile.value!),
|
||||||
|
'size': File(sharedFile.value!).lengthSync(),
|
||||||
|
'bytes': null
|
||||||
|
});
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
setStateView(ViewState.idle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteIntentFile(String path) {
|
||||||
|
setStateView(ViewState.busy);
|
||||||
|
_logger.d("Removing path '$path' from $paths");
|
||||||
|
|
||||||
|
paths?.removeWhere((element) => element.path == path);
|
||||||
|
|
||||||
|
int length = paths!.length;
|
||||||
|
if (length == 0) {
|
||||||
|
paths = null;
|
||||||
|
}
|
||||||
|
setStateView(ViewState.idle);
|
||||||
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
_pasteTextController.addListener(() {
|
_pasteTextController.addListener(() {
|
||||||
pasteTextTouched = pasteTextController.text.isNotEmpty;
|
pasteTextTouched = pasteTextController.text.isNotEmpty;
|
||||||
|
@ -52,61 +88,21 @@ class UploadModel extends BaseModel {
|
||||||
});
|
});
|
||||||
|
|
||||||
// For sharing images coming from outside the app while the app is in the memory
|
// For sharing images coming from outside the app while the app is in the memory
|
||||||
_intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream().listen((List<SharedMediaFile> value) {
|
_intentDataStreamSubscription = FlutterSharingIntent.instance
|
||||||
if (value.isNotEmpty) {
|
.getMediaStream()
|
||||||
setStateView(ViewState.busy);
|
.listen((List<SharedFile> value) {
|
||||||
paths = value.map((sharedFile) {
|
_logger.d("Retrieved ${value.length} files from intent");
|
||||||
return PlatformFile.fromMap({
|
_parseIntentFiles(value);
|
||||||
'path': sharedFile.path,
|
|
||||||
'name': basename(sharedFile.path),
|
|
||||||
'size': File(sharedFile.path).lengthSync(),
|
|
||||||
'bytes': null
|
|
||||||
});
|
|
||||||
}).toList();
|
|
||||||
setStateView(ViewState.idle);
|
|
||||||
}
|
|
||||||
}, onError: (err) {
|
}, onError: (err) {
|
||||||
_errorIntentHandle(err);
|
_errorIntentHandle(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
// For sharing images coming from outside the app while the app is closed
|
// For sharing images coming from outside the app while the app is closed
|
||||||
ReceiveSharingIntent.getInitialMedia().then((List<SharedMediaFile> value) {
|
FlutterSharingIntent.instance
|
||||||
if (value.isNotEmpty) {
|
.getInitialSharing()
|
||||||
setStateView(ViewState.busy);
|
.then((List<SharedFile> value) {
|
||||||
paths = value.map((sharedFile) {
|
_logger.d("Retrieved ${value.length} files from inactive intent");
|
||||||
return PlatformFile.fromMap({
|
_parseIntentFiles(value);
|
||||||
'path': sharedFile.path,
|
|
||||||
'name': basename(sharedFile.path),
|
|
||||||
'size': File(sharedFile.path).lengthSync(),
|
|
||||||
'bytes': null
|
|
||||||
});
|
|
||||||
}).toList();
|
|
||||||
setStateView(ViewState.idle);
|
|
||||||
}
|
|
||||||
}, onError: (err) {
|
|
||||||
_errorIntentHandle(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// For sharing or opening urls/text coming from outside the app while the app is in the memory
|
|
||||||
_intentDataStreamSubscription = ReceiveSharingIntent.getTextStream().listen((String value) {
|
|
||||||
if (value.isNotEmpty) {
|
|
||||||
setStateView(ViewState.busy);
|
|
||||||
pasteTextController.text = value;
|
|
||||||
setStateView(ViewState.idle);
|
|
||||||
}
|
|
||||||
}, onError: (err) {
|
|
||||||
_errorIntentHandle(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// For sharing or opening urls/text coming from outside the app while the app is closed
|
|
||||||
ReceiveSharingIntent.getInitialText().then((String? value) {
|
|
||||||
if (value != null && value.isNotEmpty) {
|
|
||||||
setStateView(ViewState.busy);
|
|
||||||
pasteTextController.text = value;
|
|
||||||
setStateView(ViewState.idle);
|
|
||||||
}
|
|
||||||
}, onError: (err) {
|
|
||||||
_errorIntentHandle(err);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +146,9 @@ class UploadModel extends BaseModel {
|
||||||
allowMultiple: true,
|
allowMultiple: true,
|
||||||
withData: false,
|
withData: false,
|
||||||
withReadStream: true,
|
withReadStream: true,
|
||||||
allowedExtensions: (_extension?.isNotEmpty ?? false) ? _extension?.replaceAll(' ', '').split(',') : null,
|
allowedExtensions: (_extension?.isNotEmpty ?? false)
|
||||||
|
? _extension?.replaceAll(' ', '').split(',')
|
||||||
|
: null,
|
||||||
))
|
))
|
||||||
?.files;
|
?.files;
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
|
@ -185,21 +183,25 @@ class UploadModel extends BaseModel {
|
||||||
Map<String, String>? additionalFiles;
|
Map<String, String>? additionalFiles;
|
||||||
|
|
||||||
if (pasteTextController.text.isNotEmpty) {
|
if (pasteTextController.text.isNotEmpty) {
|
||||||
additionalFiles =
|
additionalFiles = Map.from({
|
||||||
Map.from({'paste-${(DateTime.now().millisecondsSinceEpoch / 1000).round()}.txt': pasteTextController.text});
|
'paste-${(DateTime.now().millisecondsSinceEpoch / 1000).round()}.txt':
|
||||||
|
pasteTextController.text
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paths != null && paths!.isNotEmpty) {
|
if (paths != null && paths!.isNotEmpty) {
|
||||||
files = paths!.map((e) => File(e.path!)).toList();
|
files = paths!.map((e) => File(e.path!)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
UploadedResponse response = await _fileService.uploadPaste(files, additionalFiles);
|
UploadedResponse response =
|
||||||
|
await _fileService.uploadPaste(files, additionalFiles);
|
||||||
for (var element in response.data.ids) {
|
for (var element in response.data.ids) {
|
||||||
uploadedPasteIds.putIfAbsent(element, () => false);
|
uploadedPasteIds.putIfAbsent(element, () => false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createMulti && response.data.ids.length > 1) {
|
if (createMulti && response.data.ids.length > 1) {
|
||||||
UploadedMultiResponse multiResponse = await _fileService.uploadMultiPaste(response.data.ids);
|
UploadedMultiResponse multiResponse =
|
||||||
|
await _fileService.uploadMultiPaste(response.data.ids);
|
||||||
uploadedPasteIds.putIfAbsent(multiResponse.data.urlId, () => true);
|
uploadedPasteIds.putIfAbsent(multiResponse.data.urlId, () => true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,9 +221,11 @@ class UploadModel extends BaseModel {
|
||||||
e.responseBody is RestError &&
|
e.responseBody is RestError &&
|
||||||
e.responseBody.message != null) {
|
e.responseBody.message != null) {
|
||||||
if (e.statusCode == HttpStatus.badRequest) {
|
if (e.statusCode == HttpStatus.badRequest) {
|
||||||
errorMessage = translate('api.bad_request', args: {'reason': e.responseBody.message});
|
errorMessage = translate('api.bad_request',
|
||||||
|
args: {'reason': e.responseBody.message});
|
||||||
} else {
|
} else {
|
||||||
errorMessage = translate('api.general_rest_error_payload', args: {'message': e.responseBody.message});
|
errorMessage = translate('api.general_rest_error_payload',
|
||||||
|
args: {'message': e.responseBody.message});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errorMessage = translate('api.general_rest_error');
|
errorMessage = translate('api.general_rest_error');
|
||||||
|
@ -252,6 +256,8 @@ class UploadModel extends BaseModel {
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_pasteTextController.dispose();
|
_pasteTextController.dispose();
|
||||||
_intentDataStreamSubscription.cancel();
|
_intentDataStreamSubscription.cancel();
|
||||||
|
FlutterSharingIntent.instance.reset();
|
||||||
|
paths = null;
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:clipboard/clipboard.dart';
|
import 'package:clipboard/clipboard.dart';
|
||||||
|
import 'package:fbmobile/core/util/formatter_util.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_translate/flutter_translate.dart';
|
import 'package:flutter_translate/flutter_translate.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -20,12 +21,14 @@ class UploadView extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseView<UploadModel>(
|
return BaseView<UploadModel>(
|
||||||
onModelReady: (model) => model.init(),
|
onModelReady: (model) => model.init(),
|
||||||
builder: (context, model, child) =>
|
builder: (context, model, child) => Scaffold(
|
||||||
Scaffold(appBar: MyAppBar(title: Text(translate('titles.upload'))), body: _render(model, context)));
|
appBar: MyAppBar(title: Text(translate('titles.upload'))),
|
||||||
|
body: _render(model, context)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isUploadButtonEnabled(UploadModel model) {
|
bool _isUploadButtonEnabled(UploadModel model) {
|
||||||
return model.pasteTextTouched || (model.paths != null && model.paths!.isNotEmpty);
|
return model.pasteTextTouched ||
|
||||||
|
(model.paths != null && model.paths!.isNotEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _render(UploadModel model, BuildContext context) {
|
Widget _render(UploadModel model, BuildContext context) {
|
||||||
|
@ -38,7 +41,9 @@ class UploadView extends StatelessWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const CircularProgressIndicator(),
|
const CircularProgressIndicator(),
|
||||||
(model.stateMessage != null && model.stateMessage!.isNotEmpty ? Text(model.stateMessage!) : Container())
|
(model.stateMessage != null && model.stateMessage!.isNotEmpty
|
||||||
|
? Text(model.stateMessage!)
|
||||||
|
: Container())
|
||||||
]))
|
]))
|
||||||
: ListView(children: <Widget>[
|
: ListView(children: <Widget>[
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -56,12 +61,15 @@ class UploadView extends StatelessWidget {
|
||||||
Icons.text_snippet,
|
Icons.text_snippet,
|
||||||
),
|
),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
onPressed: () => model.pasteTextController.clear(),
|
onPressed: () =>
|
||||||
|
model.pasteTextController.clear(),
|
||||||
icon: const Icon(Icons.clear),
|
icon: const Icon(Icons.clear),
|
||||||
),
|
),
|
||||||
hintText: translate('upload.text_to_be_pasted'),
|
hintText: translate('upload.text_to_be_pasted'),
|
||||||
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
|
contentPadding: const EdgeInsets.fromLTRB(
|
||||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
|
20.0, 10.0, 20.0, 10.0),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(32.0)),
|
||||||
),
|
),
|
||||||
controller: model.pasteTextController)),
|
controller: model.pasteTextController)),
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -77,14 +85,17 @@ class UploadView extends StatelessWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.file_copy_sharp, color: blueColor),
|
icon: const Icon(Icons.file_copy_sharp,
|
||||||
|
color: blueColor),
|
||||||
onPressed: () => model.openFileExplorer(),
|
onPressed: () => model.openFileExplorer(),
|
||||||
label: Text(
|
label: Text(
|
||||||
translate('upload.open_file_explorer'),
|
translate('upload.open_file_explorer'),
|
||||||
)),
|
)),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.cancel, color: orangeColor),
|
icon: const Icon(Icons.cancel,
|
||||||
onPressed: model.paths != null && model.paths!.isNotEmpty
|
color: orangeColor),
|
||||||
|
onPressed: model.paths != null &&
|
||||||
|
model.paths!.isNotEmpty
|
||||||
? () => model.clearCachedFiles()
|
? () => model.clearCachedFiles()
|
||||||
: null,
|
: null,
|
||||||
label: Text(
|
label: Text(
|
||||||
|
@ -114,34 +125,47 @@ class UploadView extends StatelessWidget {
|
||||||
onPressed: !_isUploadButtonEnabled(model)
|
onPressed: !_isUploadButtonEnabled(model)
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
Map<String, bool>? items = await model.upload();
|
Map<String, bool>? items =
|
||||||
String? clipboardContent = model.generatePasteLinks(items, url);
|
await model.upload();
|
||||||
|
String? clipboardContent = model
|
||||||
|
.generatePasteLinks(items, url);
|
||||||
|
|
||||||
if (clipboardContent != null && clipboardContent.isNotEmpty) {
|
if (clipboardContent != null &&
|
||||||
FlutterClipboard.copy(clipboardContent).then((value) {
|
clipboardContent.isNotEmpty) {
|
||||||
|
FlutterClipboard.copy(
|
||||||
|
clipboardContent)
|
||||||
|
.then((value) {
|
||||||
final snackBar = SnackBar(
|
final snackBar = SnackBar(
|
||||||
action: SnackBarAction(
|
action: SnackBarAction(
|
||||||
label: translate('upload.dismiss'),
|
label: translate(
|
||||||
|
'upload.dismiss'),
|
||||||
textColor: blueColor,
|
textColor: blueColor,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(
|
||||||
|
context)
|
||||||
|
.hideCurrentSnackBar();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
content: Text(translate('upload.uploaded')),
|
content: Text(translate(
|
||||||
duration: const Duration(seconds: 10),
|
'upload.uploaded')),
|
||||||
|
duration:
|
||||||
|
const Duration(seconds: 10),
|
||||||
);
|
);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
ScaffoldMessenger.of(context)
|
||||||
|
.showSnackBar(snackBar);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.upload_rounded, color: greenColor),
|
icon: const Icon(Icons.upload_rounded,
|
||||||
|
color: greenColor),
|
||||||
label: Text(
|
label: Text(
|
||||||
translate('upload.upload'),
|
translate('upload.upload'),
|
||||||
)),
|
)),
|
||||||
])),
|
])),
|
||||||
model.errorMessage != null && model.errorMessage!.isNotEmpty
|
model.errorMessage != null && model.errorMessage!.isNotEmpty
|
||||||
? (Padding(
|
? (Padding(
|
||||||
padding: const EdgeInsets.only(top: 10.0, bottom: 10.0),
|
padding:
|
||||||
|
const EdgeInsets.only(top: 10.0, bottom: 10.0),
|
||||||
child: CenteredErrorRow(model.errorMessage)))
|
child: CenteredErrorRow(model.errorMessage)))
|
||||||
: Container(),
|
: Container(),
|
||||||
Builder(
|
Builder(
|
||||||
|
@ -152,28 +176,54 @@ class UploadView extends StatelessWidget {
|
||||||
)
|
)
|
||||||
: model.paths != null
|
: model.paths != null
|
||||||
? Container(
|
? Container(
|
||||||
padding: const EdgeInsets.only(bottom: 30.0),
|
padding: const EdgeInsets.only(bottom: 20.0),
|
||||||
height: MediaQuery.of(context).size.height * 0.50,
|
height:
|
||||||
|
MediaQuery.of(context).size.height * 0.50,
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
itemCount: model.paths != null && model.paths!.isNotEmpty ? model.paths!.length : 1,
|
itemCount: model.paths != null &&
|
||||||
itemBuilder: (BuildContext context, int index) {
|
model.paths!.isNotEmpty
|
||||||
final bool isMultiPath = model.paths != null && model.paths!.isNotEmpty;
|
? model.paths!.length
|
||||||
|
: 1,
|
||||||
|
itemBuilder:
|
||||||
|
(BuildContext context, int index) {
|
||||||
|
final bool isMultiPath =
|
||||||
|
model.paths != null &&
|
||||||
|
model.paths!.isNotEmpty;
|
||||||
final String name = (isMultiPath
|
final String name = (isMultiPath
|
||||||
? model.paths!.map((e) => e.name).toList()[index]
|
? model.paths!
|
||||||
|
.map((e) => e.name)
|
||||||
|
.toList()[index]
|
||||||
: model.fileName ?? '...');
|
: model.fileName ?? '...');
|
||||||
|
final size = model.paths!.isNotEmpty
|
||||||
|
? model.paths!
|
||||||
|
.map((e) => e.size)
|
||||||
|
.toList()[index]
|
||||||
|
.toString()
|
||||||
|
: '';
|
||||||
final path = model.paths!.isNotEmpty
|
final path = model.paths!.isNotEmpty
|
||||||
? model.paths!.map((e) => e.path).toList()[index].toString()
|
? model.paths!
|
||||||
|
.map((e) => e.path)
|
||||||
|
.toList()[index]
|
||||||
|
.toString()
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.clear,
|
||||||
|
color: orangeColor),
|
||||||
|
onPressed: () {
|
||||||
|
model.deleteIntentFile(path);
|
||||||
|
}),
|
||||||
title: Text(
|
title: Text(
|
||||||
name,
|
"$name (${FormatterUtil.formatBytes(int.parse(size), 2)})",
|
||||||
),
|
),
|
||||||
subtitle: Text(path),
|
subtitle: Text(path),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
separatorBuilder: (BuildContext context, int index) => const Divider(),
|
separatorBuilder:
|
||||||
|
(BuildContext context, int index) =>
|
||||||
|
const Divider(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../shared/app_colors.dart';
|
|
||||||
|
|
||||||
class LoginTextField extends StatelessWidget {
|
class LoginTextField extends StatelessWidget {
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
final String placeHolder;
|
final String placeHolder;
|
||||||
|
@ -19,7 +17,6 @@ class LoginTextField extends StatelessWidget {
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
|
margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
|
||||||
height: 50.0,
|
height: 50.0,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
decoration: BoxDecoration(color: whiteColor, borderRadius: BorderRadius.circular(10.0)),
|
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
keyboardType: keyboardType,
|
keyboardType: keyboardType,
|
||||||
obscureText: obscureText,
|
obscureText: obscureText,
|
||||||
|
|
14
pubspec.lock
14
pubspec.lock
|
@ -256,6 +256,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.7"
|
version: "2.0.7"
|
||||||
|
flutter_sharing_intent:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_sharing_intent
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.5"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -588,13 +595,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
receive_sharing_intent:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: receive_sharing_intent
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.5"
|
|
||||||
share_plus:
|
share_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -36,13 +36,13 @@ dependencies:
|
||||||
share_plus: 6.3.0
|
share_plus: 6.3.0
|
||||||
file_picker: 5.2.4
|
file_picker: 5.2.4
|
||||||
clipboard: 0.1.3
|
clipboard: 0.1.3
|
||||||
receive_sharing_intent: 1.4.5
|
|
||||||
permission_handler: 10.2.0
|
permission_handler: 10.2.0
|
||||||
package_info_plus: 3.0.2
|
package_info_plus: 3.0.2
|
||||||
json_annotation: 4.7.0
|
json_annotation: 4.7.0
|
||||||
dynamic_color: 1.5.4
|
dynamic_color: 1.5.4
|
||||||
intl: 0.17.0
|
intl: 0.17.0
|
||||||
path: 1.8.2
|
path: 1.8.2
|
||||||
|
flutter_sharing_intent: 1.0.5
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
Loading…
Reference in a new issue