fist commit ftc staff app clone
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ftc_mobile_app/models/clients/memoryListResponse/MemoryListData.dart';
|
||||
import 'package:ftc_mobile_app/models/profileData/user_data.dart';
|
||||
import 'package:ftc_mobile_app/view/custom_widgets/my_network_image.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
|
||||
import 'controller/add_edit_memory_box_screen_controller.dart';
|
||||
import 'widget/VideoPlayerWidget.dart';
|
||||
|
||||
class AddEditMemoryBoxScreenArgs {
|
||||
final UserData userData;
|
||||
final MemoryListData? data;
|
||||
final bool viewOnly;
|
||||
|
||||
AddEditMemoryBoxScreenArgs({
|
||||
required this.userData,
|
||||
this.data,
|
||||
this.viewOnly = false,
|
||||
});
|
||||
}
|
||||
|
||||
//This screen is used to view, add and edit memory box
|
||||
class AddEditMemoryBoxScreen extends StatefulWidget {
|
||||
final AddEditMemoryBoxScreenArgs args;
|
||||
|
||||
const AddEditMemoryBoxScreen({super.key, required this.args});
|
||||
|
||||
@override
|
||||
State<AddEditMemoryBoxScreen> createState() => _AddEditMemoryBoxScreenState();
|
||||
}
|
||||
|
||||
class _AddEditMemoryBoxScreenState extends State<AddEditMemoryBoxScreen> {
|
||||
final controller = Get.put(AddEditMemoryBoxScreenController());
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
controller.serviceUserId = widget.args.userData.id!;
|
||||
|
||||
if (forUpdate) {
|
||||
controller.filePath.value =
|
||||
'${WebUrls.baseUrl}${widget.args.data!.filePath ?? ""}';
|
||||
controller.noteDetailsController.text = widget.args.data!.note ?? "";
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
bool get forUpdate => widget.args.data != null;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomScaffold(
|
||||
backgroundColor: CustomAppColors.kPrimaryColor,
|
||||
screenKey: controller.screenKey,
|
||||
onScreenTap: controller.removeFocus,
|
||||
showAppBar: true,
|
||||
appBar: CustomAppBarTitleOnly(
|
||||
context,
|
||||
titleText:
|
||||
"${widget.args.viewOnly ? "View" : forUpdate ? "Update" : "Add"} Memory Box",
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.r),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: (widget.args.viewOnly)
|
||||
? _viewOnlyWidgets
|
||||
: [
|
||||
12.verticalSpace,
|
||||
Obx(() {
|
||||
final path = controller.filePath();
|
||||
return mediaViewer(path: path);
|
||||
}),
|
||||
CustomTextWidget(
|
||||
text: "Upload File",
|
||||
textAlign: TextAlign.left,
|
||||
fontSize: 16.sp,
|
||||
fontColor: Colors.black,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
// CustomTextWidget(
|
||||
// text: "Please upload a file that is 1MB or smaller.",
|
||||
// textAlign: TextAlign.left,
|
||||
// fontSize: 12.sp,
|
||||
// fontColor: Colors.grey,
|
||||
// ),
|
||||
12.verticalSpace,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: SizedBox(
|
||||
height: 32.r,
|
||||
child: CustomAppButton(
|
||||
buttonColor: Get.theme.primaryColor,
|
||||
buttonText: "Choose File",
|
||||
onTap: controller.onFileChooseButtonTap,
|
||||
),
|
||||
).paddingOnly(right: 8.r),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Obx(() {
|
||||
return controller.filePath.isNotEmpty
|
||||
? Obx(
|
||||
() => CustomTextWidget(
|
||||
text: controller.filePath.value
|
||||
.split("/")
|
||||
.last,
|
||||
isExpanded: false,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
)
|
||||
: FrequentFunctions.noWidget;
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
20.verticalSpace,
|
||||
CustomTextFieldWidget(
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
borderColor: CustomAppColors.kLightGreyColor,
|
||||
controller: controller.noteDetailsController,
|
||||
heading: "Note Details",
|
||||
hintText: "Type here...",
|
||||
minLines: 6,
|
||||
maxLines: 6,
|
||||
onChange: (_) {},
|
||||
),
|
||||
32.verticalSpace,
|
||||
CustomAppButton(
|
||||
buttonText: forUpdate ? "Update" : "Save",
|
||||
onTap: () {
|
||||
forUpdate
|
||||
? controller
|
||||
.updateButtonPress(widget.args.data!.id!)
|
||||
: controller.saveButtonPress();
|
||||
},
|
||||
),
|
||||
5.verticalSpace,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> get _viewOnlyWidgets {
|
||||
return [
|
||||
12.verticalSpace,
|
||||
mediaViewer(
|
||||
path: '${WebUrls.baseUrl}${widget.args.data?.filePath ?? ""}'),
|
||||
20.verticalSpace,
|
||||
Column(
|
||||
children: [
|
||||
CustomTextWidget(
|
||||
text: "Note Details",
|
||||
textAlign: TextAlign.left,
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontColor: Colors.black,
|
||||
),
|
||||
CustomTextWidget(
|
||||
text: widget.args.data?.note ?? "",
|
||||
textAlign: TextAlign.left,
|
||||
fontSize: 14.sp,
|
||||
fontColor: Colors.black,
|
||||
),
|
||||
],
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
Widget mediaViewer({required String path}) {
|
||||
if (path.isVideoFileName) {
|
||||
return VideoPlayerWidget(
|
||||
path: path,
|
||||
type: path.startsWith("http")
|
||||
? VideoSourceType.network
|
||||
: VideoSourceType.file,
|
||||
);
|
||||
} else if (path.isImageFileName) {
|
||||
if (path.startsWith("http")) {
|
||||
return MyNetworkImage(url: path);
|
||||
} else {
|
||||
return Image.file(File(path));
|
||||
}
|
||||
} else {
|
||||
return FrequentFunctions.noWidget;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import 'dart:io';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ftc_mobile_app/utilities/extensions/custom_extensions.dart';
|
||||
import 'package:ftc_mobile_app/utilities/frequent_functions.dart';
|
||||
import 'package:ftc_mobile_app/web_services/client_services.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AddEditMemoryBoxScreenController extends GetxController {
|
||||
final GlobalKey<ScaffoldState> screenKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
TextEditingController documentTitleController = TextEditingController();
|
||||
TextEditingController noteDetailsController = TextEditingController();
|
||||
|
||||
late final String serviceUserId;
|
||||
|
||||
final file = Rx<File?>(null);
|
||||
|
||||
//Should stores full path of file or url
|
||||
final filePath = "".obs;
|
||||
|
||||
onFileChooseButtonTap() async {
|
||||
FilePickerResult? result =
|
||||
await FilePicker.platform.pickFiles(type: FileType.media);
|
||||
|
||||
if (result != null && result.files.single.path != null) {
|
||||
if (result.files.single.path!.isVideoFileName ||
|
||||
result.files.single.path!.isImageFileName) {
|
||||
file.value = File(result.files.single.path!);
|
||||
filePath.value = result.files.single.path!;
|
||||
} else {
|
||||
FrequentFunctions.showToast(message: "Unsupported File");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveButtonPress() async {
|
||||
if (file() == null) {
|
||||
FrequentFunctions.showToast(message: "Please select file first");
|
||||
return;
|
||||
}
|
||||
if (noteDetailsController.text.trim().isEmpty) {
|
||||
FrequentFunctions.showToast(message: "Note details field is required");
|
||||
return;
|
||||
}
|
||||
|
||||
var response = await ClientService()
|
||||
.addMemoryBoxFile(
|
||||
userId: serviceUserId,
|
||||
filePath: file.value!.path,
|
||||
noteDetails: noteDetailsController.text,
|
||||
)
|
||||
.showLoader();
|
||||
|
||||
if (response == true) {
|
||||
backButtonPressed(argument: true);
|
||||
} else {
|
||||
FrequentFunctions.showToast(message: response);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateButtonPress(String id) async {
|
||||
if (noteDetailsController.text.trim().isEmpty) {
|
||||
FrequentFunctions.showToast(message: "Note details field is required");
|
||||
return;
|
||||
}
|
||||
|
||||
var response = await ClientService()
|
||||
.updateMemoryBoxFile(
|
||||
id: id,
|
||||
userId: serviceUserId,
|
||||
filePath: file.value?.path ?? "",
|
||||
noteDetails: noteDetailsController.text,
|
||||
)
|
||||
.showLoader();
|
||||
|
||||
if (response == true) {
|
||||
backButtonPressed(argument: true);
|
||||
} else {
|
||||
FrequentFunctions.showToast(message: response);
|
||||
}
|
||||
}
|
||||
|
||||
void backButtonPressed({dynamic argument}) {
|
||||
Navigator.of(screenKey.currentContext!).pop(argument);
|
||||
}
|
||||
|
||||
void removeFocus() {
|
||||
FocusScope.of(screenKey.currentContext!).unfocus();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
noteDetailsController.dispose();
|
||||
Get.delete<AddEditMemoryBoxScreenController>();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
enum VideoSourceType { file, network }
|
||||
|
||||
class VideoPlayerWidget extends StatefulWidget {
|
||||
final String path;
|
||||
final VideoSourceType type;
|
||||
|
||||
const VideoPlayerWidget({
|
||||
super.key,
|
||||
required this.path,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
@override
|
||||
State<VideoPlayerWidget> createState() => _VideoPlayerWidgetState();
|
||||
}
|
||||
|
||||
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
|
||||
VideoPlayerController? _videoPlayerController;
|
||||
final RxBool isInitialized = false.obs;
|
||||
final RxBool isError = false.obs;
|
||||
final RxBool isPlaying = false.obs;
|
||||
double aspectRatio = 16.0 / 9.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
print("Video path: ${widget.path}");
|
||||
if (widget.type == VideoSourceType.network) {
|
||||
print("VideoSourceType.network");
|
||||
_videoPlayerController =
|
||||
VideoPlayerController.networkUrl(Uri.parse(widget.path));
|
||||
} else {
|
||||
print("VideoSourceType.file");
|
||||
_videoPlayerController = VideoPlayerController.file(File(widget.path));
|
||||
}
|
||||
|
||||
_videoPlayerController?.initialize().then((_) {
|
||||
isInitialized.value = true;
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AspectRatio(
|
||||
aspectRatio: aspectRatio,
|
||||
child: Obx(() {
|
||||
return (isError())
|
||||
? FrequentFunctions.centerText(text: "Something went wrong")
|
||||
: isInitialized.isFalse
|
||||
? FrequentFunctions.centerText(text: "Loading video...")
|
||||
: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: VideoPlayer(_videoPlayerController!),
|
||||
),
|
||||
Center(
|
||||
child: Obx(() {
|
||||
return (isPlaying())
|
||||
? FrequentFunctions.noWidget
|
||||
: InkWell(
|
||||
onTap: () {
|
||||
if (isPlaying.isFalse) {
|
||||
isPlaying.value = true;
|
||||
_videoPlayerController?.play();
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
Icons.play_circle,
|
||||
color: Get.theme.primaryColor,
|
||||
size: 56.r,
|
||||
),
|
||||
);
|
||||
}),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoPlayerController?.dispose();
|
||||
_videoPlayerController = null;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user