Merge branch 'master_mohemm_flutter'
# Conflicts: # android/app/src/main/AndroidManifest.xml # ios/Runner.xcodeproj/project.pbxproj # lib/app_state/app_state.dart # pubspec.yamlmohemm_HMG_flutter_upgrade
commit
609d3ca48a
@ -0,0 +1,8 @@
|
|||||||
|
<paths>
|
||||||
|
<external-path name="external-path" path="."/>
|
||||||
|
<external-cache-path name="external-cache-path" path="."/>
|
||||||
|
<external-files-path name="external-files-path" path="."/>
|
||||||
|
<files-path name="files_path" path="."/>
|
||||||
|
<cache-path name="cache-path" path="."/>
|
||||||
|
<root-path name="root" path="."/>
|
||||||
|
</paths>
|
||||||
|
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 548 B After Width: | Height: | Size: 548 B |
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 470 B |
@ -0,0 +1,25 @@
|
|||||||
|
class ITGFormsAttachmentsModel {
|
||||||
|
String? fileBase64;
|
||||||
|
dynamic fileData;
|
||||||
|
String? fileName;
|
||||||
|
String? fileType;
|
||||||
|
|
||||||
|
ITGFormsAttachmentsModel(
|
||||||
|
{this.fileBase64, this.fileData, this.fileName, this.fileType});
|
||||||
|
|
||||||
|
ITGFormsAttachmentsModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
fileBase64 = json['fileBase64'];
|
||||||
|
fileData = json['fileData'];
|
||||||
|
fileName = json['fileName'];
|
||||||
|
fileType = json['fileType'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['fileBase64'] = this.fileBase64;
|
||||||
|
data['fileData'] = this.fileData;
|
||||||
|
data['fileName'] = this.fileName;
|
||||||
|
data['fileType'] = this.fileType;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
// class TutorialNotificationModel {
|
||||||
|
// List<Data>? data;
|
||||||
|
// bool? isSuccessful;
|
||||||
|
// String? message;
|
||||||
|
// int? statusCode;
|
||||||
|
//
|
||||||
|
// TutorialNotificationModel({this.data, this.isSuccessful, this.message, this.statusCode});
|
||||||
|
//
|
||||||
|
// TutorialNotificationModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
// if (json['data'] != null) {
|
||||||
|
// data = <Data>[];
|
||||||
|
// json['data'].forEach((v) {
|
||||||
|
// data!.add(new Data.fromJson(v));
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// isSuccessful = json['isSuccessful'];
|
||||||
|
// message = json['message'];
|
||||||
|
// statusCode = json['statusCode'];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Map<String, dynamic> toJson() {
|
||||||
|
// final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
// if (this.data != null) {
|
||||||
|
// data['data'] = this.data!.map((v) => v.toJson()).toList();
|
||||||
|
// }
|
||||||
|
// data['isSuccessful'] = this.isSuccessful;
|
||||||
|
// data['message'] = this.message;
|
||||||
|
// data['statusCode'] = this.statusCode;
|
||||||
|
//
|
||||||
|
// return data;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
class TutorialNotificationModel {
|
||||||
|
String? tutorialNotificationId;
|
||||||
|
String? tutorialName;
|
||||||
|
String? tutorialDescription;
|
||||||
|
String? startDate;
|
||||||
|
String? endDate;
|
||||||
|
String? fileName;
|
||||||
|
String? contentType;
|
||||||
|
String? filePath;
|
||||||
|
int? orderNo;
|
||||||
|
bool? isActive;
|
||||||
|
int? isStatus;
|
||||||
|
String? created;
|
||||||
|
String? createdBy;
|
||||||
|
String? modified;
|
||||||
|
String? modifiedBy;
|
||||||
|
|
||||||
|
TutorialNotificationModel({this.tutorialNotificationId,
|
||||||
|
this.tutorialName,
|
||||||
|
this.tutorialDescription,
|
||||||
|
this.startDate,
|
||||||
|
this.endDate,
|
||||||
|
this.fileName,
|
||||||
|
this.contentType,
|
||||||
|
this.filePath,
|
||||||
|
this.orderNo,
|
||||||
|
this.isActive,
|
||||||
|
this.isStatus,
|
||||||
|
this.created,
|
||||||
|
this.createdBy,
|
||||||
|
this.modified,
|
||||||
|
this.modifiedBy});
|
||||||
|
|
||||||
|
TutorialNotificationModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
tutorialNotificationId = json['tutorialNotificationId'];
|
||||||
|
tutorialName = json['tutorialName'];
|
||||||
|
tutorialDescription = json['tutorialDescription'];
|
||||||
|
startDate = json['startDate'];
|
||||||
|
endDate = json['endDate'];
|
||||||
|
fileName = json['fileName'];
|
||||||
|
contentType = json['contentType'];
|
||||||
|
filePath = json['filePath'];
|
||||||
|
orderNo = json['orderNo'];
|
||||||
|
isActive = json['isActive'];
|
||||||
|
isStatus = json['isStatus'];
|
||||||
|
created = json['created'];
|
||||||
|
createdBy = json['createdBy'];
|
||||||
|
modified = json['modified'];
|
||||||
|
modifiedBy = json['modifiedBy'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['tutorialNotificationId'] = this.tutorialNotificationId;
|
||||||
|
data['tutorialName'] = this.tutorialName;
|
||||||
|
data['tutorialDescription'] = this.tutorialDescription;
|
||||||
|
data['startDate'] = this.startDate;
|
||||||
|
data['endDate'] = this.endDate;
|
||||||
|
data['fileName'] = this.fileName;
|
||||||
|
data['contentType'] = this.contentType;
|
||||||
|
data['filePath'] = this.filePath;
|
||||||
|
data['orderNo'] = this.orderNo;
|
||||||
|
data['isActive'] = this.isActive;
|
||||||
|
data['isStatus'] = this.isStatus;
|
||||||
|
data['created'] = this.created;
|
||||||
|
data['createdBy'] = this.createdBy;
|
||||||
|
data['modified'] = this.modified;
|
||||||
|
data['modifiedBy'] = this.modifiedBy;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
class GetTransactionAttachmentModel {
|
||||||
|
int? attachmentId;
|
||||||
|
String? fileName;
|
||||||
|
String? contentType;
|
||||||
|
dynamic attachFileStream;
|
||||||
|
String? base64String;
|
||||||
|
dynamic isActive;
|
||||||
|
dynamic referenceItemId;
|
||||||
|
dynamic content;
|
||||||
|
dynamic filePath;
|
||||||
|
int? languageId;
|
||||||
|
|
||||||
|
GetTransactionAttachmentModel(
|
||||||
|
{this.attachmentId,
|
||||||
|
this.fileName,
|
||||||
|
this.contentType,
|
||||||
|
this.attachFileStream,
|
||||||
|
this.base64String,
|
||||||
|
this.isActive,
|
||||||
|
this.referenceItemId,
|
||||||
|
this.content,
|
||||||
|
this.filePath,
|
||||||
|
this.languageId});
|
||||||
|
|
||||||
|
GetTransactionAttachmentModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
attachmentId = json['attachmentId'];
|
||||||
|
fileName = json['fileName'];
|
||||||
|
contentType = json['contentType'];
|
||||||
|
attachFileStream = json['attachFileStream'];
|
||||||
|
base64String = json['base64String'];
|
||||||
|
isActive = json['isActive'];
|
||||||
|
referenceItemId = json['referenceItemId'];
|
||||||
|
content = json['content'];
|
||||||
|
filePath = json['filePath'];
|
||||||
|
languageId = json['languageId'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
Map<String, dynamic> data = Map<String, dynamic>();
|
||||||
|
data['attachmentId'] = this.attachmentId;
|
||||||
|
data['fileName'] = this.fileName;
|
||||||
|
data['contentType'] = this.contentType;
|
||||||
|
data['attachFileStream'] = this.attachFileStream;
|
||||||
|
data['base64String'] = this.base64String;
|
||||||
|
data['isActive'] = this.isActive;
|
||||||
|
data['referenceItemId'] = this.referenceItemId;
|
||||||
|
data['content'] = this.content;
|
||||||
|
data['filePath'] = this.filePath;
|
||||||
|
data['languageId'] = this.languageId;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
class TerminationNotificationBody {
|
||||||
|
String? sEGMENTPROMPT;
|
||||||
|
String? sEGMENTVALUEDSP;
|
||||||
|
|
||||||
|
TerminationNotificationBody({this.sEGMENTPROMPT, this.sEGMENTVALUEDSP});
|
||||||
|
|
||||||
|
TerminationNotificationBody.fromJson(Map<String, dynamic> json) {
|
||||||
|
sEGMENTPROMPT = json['SEGMENT_PROMPT'];
|
||||||
|
sEGMENTVALUEDSP = json['SEGMENT_VALUE_DSP'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['SEGMENT_PROMPT'] = this.sEGMENTPROMPT;
|
||||||
|
data['SEGMENT_VALUE_DSP'] = this.sEGMENTVALUEDSP;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,241 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io' as Io;
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_countdown_timer/index.dart';
|
||||||
|
import 'package:lottie/lottie.dart';
|
||||||
|
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
|
||||||
|
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
||||||
|
import 'package:mohem_flutter_app/classes/colors.dart';
|
||||||
|
import 'package:mohem_flutter_app/classes/file_process.dart';
|
||||||
|
import 'package:mohem_flutter_app/classes/lottie_consts.dart';
|
||||||
|
import 'package:mohem_flutter_app/classes/utils.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
|
||||||
|
import 'package:mohem_flutter_app/main.dart';
|
||||||
|
import 'package:mohem_flutter_app/models/itg/advertisement.dart' as ads;
|
||||||
|
import 'package:mohem_flutter_app/models/marathon/tutorial_notification_model.dart';
|
||||||
|
import 'package:mohem_flutter_app/ui/chat/common.dart';
|
||||||
|
import 'package:mohem_flutter_app/ui/marathon/marathon_provider.dart';
|
||||||
|
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
|
||||||
|
import 'package:mohem_flutter_app/widgets/button/default_button.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
|
class MarathonTutorialViewerScreen extends StatefulWidget {
|
||||||
|
const MarathonTutorialViewerScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_MarathonTutorialViewerScreenState createState() => _MarathonTutorialViewerScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MarathonTutorialViewerScreenState extends State<MarathonTutorialViewerScreen> {
|
||||||
|
late Future<VideoPlayerController> _futureController;
|
||||||
|
VideoPlayerController? _controller;
|
||||||
|
bool skip = false;
|
||||||
|
|
||||||
|
bool isVideo = false;
|
||||||
|
bool isImage = false;
|
||||||
|
bool isAudio = false;
|
||||||
|
bool isPdf = false;
|
||||||
|
|
||||||
|
String link = "";
|
||||||
|
|
||||||
|
String ext = '';
|
||||||
|
late File imageFile;
|
||||||
|
ads.Advertisement? advertisementData;
|
||||||
|
dynamic data;
|
||||||
|
String? masterID;
|
||||||
|
int videoDuration = 0;
|
||||||
|
|
||||||
|
ValueNotifier<int> videoLength = ValueNotifier(0);
|
||||||
|
|
||||||
|
void checkFileTypes(String link) {
|
||||||
|
ext = "." + link.split(".").last.toLowerCase();
|
||||||
|
if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") {
|
||||||
|
isImage = true;
|
||||||
|
} else if (ext == ".pdf") {
|
||||||
|
isPdf = true;
|
||||||
|
} else {
|
||||||
|
if (ext == ".aac") {
|
||||||
|
isAudio = true;
|
||||||
|
}
|
||||||
|
isVideo = true;
|
||||||
|
_futureController = createVideoPlayer(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future processImage(String encodedBytes) async {
|
||||||
|
try {
|
||||||
|
Uint8List decodedBytes = base64Decode(encodedBytes.split("base64,").last);
|
||||||
|
Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); // 1
|
||||||
|
imageFile = Io.File("${appDocumentsDirectory.path}/addImage$ext");
|
||||||
|
imageFile.writeAsBytesSync(decodedBytes);
|
||||||
|
} catch (e) {
|
||||||
|
logger.d(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<VideoPlayerController> createVideoPlayer(String link) async {
|
||||||
|
try {
|
||||||
|
VideoPlayerController controller = VideoPlayerController.networkUrl(Uri.parse(link));
|
||||||
|
await controller.initialize();
|
||||||
|
await controller.play();
|
||||||
|
await controller.setVolume(1.0);
|
||||||
|
await controller.setLooping(false);
|
||||||
|
controller.addListener(() {
|
||||||
|
controller.position.then((value) {
|
||||||
|
videoLength.value = value!.inMilliseconds;
|
||||||
|
// if(controller.value.isCompleted) {
|
||||||
|
// videoLength.value = 0;
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return controller;
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
return VideoPlayerController.network("https://apimohemmweb.cloudsolutions.com.sa/ErmAttachment/compressedvideo.mp4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool showControls = false;
|
||||||
|
|
||||||
|
void showVideoControls() {
|
||||||
|
showControls = !showControls;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
TutorialNotificationModel? tutorial;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (tutorial == null) {
|
||||||
|
tutorial ??= context.read<MarathonProvider>().tutorial;
|
||||||
|
link = tutorial!.filePath!;
|
||||||
|
checkFileTypes(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
appBar: AppBarWidget(context, title: tutorial!.fileName!, showHomeButton: false),
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
if (isVideo)
|
||||||
|
FutureBuilder(
|
||||||
|
future: _futureController,
|
||||||
|
builder: (BuildContext context, AsyncSnapshot<Object?> snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.done && snapshot.data != null) {
|
||||||
|
_controller = snapshot.data as VideoPlayerController;
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: isAudio
|
||||||
|
? Lottie.asset(MyLottieConsts.audioPlaybackLottie)
|
||||||
|
: AspectRatio(
|
||||||
|
aspectRatio: _controller!.value.aspectRatio,
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
children: [
|
||||||
|
VideoPlayer(_controller!),
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
color: Colors.black.withOpacity(showControls ? .4 : .0),
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
opacity: showControls ? 1 : 0,
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Icon(_controller!.value.isPlaying ? Icons.pause : Icons.play_arrow, color: Colors.white)
|
||||||
|
.onPress(() {
|
||||||
|
if (!showControls) {
|
||||||
|
showVideoControls();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_controller!.value.isPlaying) {
|
||||||
|
_controller!.pause();
|
||||||
|
}
|
||||||
|
// else if (_controller!.value.isCompleted) {
|
||||||
|
// videoLength.value = 0;
|
||||||
|
// _controller!.play();
|
||||||
|
// }
|
||||||
|
else {
|
||||||
|
_controller!.play();
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
})
|
||||||
|
.center
|
||||||
|
.expanded,
|
||||||
|
ValueListenableBuilder<int>(
|
||||||
|
valueListenable: videoLength,
|
||||||
|
builder: (context, val, child) {
|
||||||
|
return SeekBar(
|
||||||
|
duration: _controller!.value.duration,
|
||||||
|
position: Duration(milliseconds: val),
|
||||||
|
bufferedPosition: Duration(),
|
||||||
|
onChanged: (duration) {
|
||||||
|
_controller!.seekTo(duration);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).onPress(() {
|
||||||
|
showVideoControls();
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
30.height,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (isImage) Image.network(link).center,
|
||||||
|
if (isPdf)
|
||||||
|
DefaultButton(LocaleKeys.open.tr(), () async {
|
||||||
|
try {
|
||||||
|
Utils.showLoading(context);
|
||||||
|
await FileProcess.downloadFileFromUrl(link, tutorial!.fileName!).then((path) {
|
||||||
|
Utils.hideLoading(context);
|
||||||
|
FileProcess.openFile(path, isFullPath: true);
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
Utils.hideLoading(context);
|
||||||
|
Utils.handleException(ex, context, null);
|
||||||
|
}
|
||||||
|
}).paddingAll(21).center
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
|
||||||
|
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
|
||||||
|
|
||||||
|
class ViewTransactionAttachment extends StatelessWidget {
|
||||||
|
final File imageFile;
|
||||||
|
|
||||||
|
const ViewTransactionAttachment({Key? key, required this.imageFile}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBarWidget(
|
||||||
|
context,
|
||||||
|
title: LocaleKeys.mowadhafhiRequest.tr(),
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Image.file(imageFile),
|
||||||
|
50.height,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:mohem_flutter_app/classes/utils.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
|
||||||
|
import 'package:mohem_flutter_app/models/itg_forms_models/itg_forms_attachments_model.dart';
|
||||||
|
import 'package:mohem_flutter_app/widgets/dialogs/confirm_dialog.dart';
|
||||||
|
import 'package:open_filex/open_filex.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
class ITGAttachmentsFragment extends StatelessWidget {
|
||||||
|
List<ITGFormsAttachmentsModel> itgFormAttachmentsList;
|
||||||
|
|
||||||
|
ITGAttachmentsFragment(this.itgFormAttachmentsList);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListView.separated(
|
||||||
|
itemCount: itgFormAttachmentsList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(determineFileIcon(itgFormAttachmentsList[index].fileType ?? "")),
|
||||||
|
12.width,
|
||||||
|
(itgFormAttachmentsList[index].fileName ?? "").toText16().expanded,
|
||||||
|
],
|
||||||
|
).objectContainerView().onPress(() async {
|
||||||
|
try {
|
||||||
|
String path = await _createFileFromString(itgFormAttachmentsList[index].fileBase64 ?? "", itgFormAttachmentsList[index].fileType ?? "");
|
||||||
|
OpenFilex.open(path);
|
||||||
|
} catch (ex) {
|
||||||
|
Utils.showToast("Cannot open file.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
separatorBuilder: (BuildContext context, int index) => 12.height,
|
||||||
|
).paddingAll(21);
|
||||||
|
}
|
||||||
|
|
||||||
|
String determineFileIcon(String fileContentType) {
|
||||||
|
String icon = "";
|
||||||
|
switch (fileContentType) {
|
||||||
|
case "pdf":
|
||||||
|
icon = "assets/images/pdf.svg";
|
||||||
|
break;
|
||||||
|
case "xls":
|
||||||
|
icon = "assets/images/xls.svg";
|
||||||
|
break;
|
||||||
|
case "xlsx":
|
||||||
|
icon = "assets/images/xls.svg";
|
||||||
|
break;
|
||||||
|
case "png":
|
||||||
|
icon = "assets/images/png.svg";
|
||||||
|
break;
|
||||||
|
case "jpg":
|
||||||
|
icon = "assets/images/jpg.svg";
|
||||||
|
break;
|
||||||
|
case "jpeg":
|
||||||
|
icon = "assets/images/jpg.svg";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> _createFileFromString(String encodedStr, String ext) async {
|
||||||
|
Uint8List bytes = base64.decode(encodedStr);
|
||||||
|
String dir = (await getApplicationDocumentsDirectory()).path;
|
||||||
|
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
|
||||||
|
await file.writeAsBytes(bytes);
|
||||||
|
return file.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue