step 9 : clock in & clock out selfie sudah bisa, need fix at clear camera controller after take photo
This commit is contained in:
@@ -1,33 +1,63 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:path/path.dart' as p;
|
|
||||||
|
final imgPhotoWebProvider = StateProvider<String?>((ref) => "");
|
||||||
|
|
||||||
final cameraControllerProvider =
|
final cameraControllerProvider =
|
||||||
StateNotifierProvider<CameraControllerNotifier, CameraController?>(
|
StateNotifierProvider<CameraControllerNotifier, CameraController?>((ref) {
|
||||||
(ref) => CameraControllerNotifier());
|
return CameraControllerNotifier();
|
||||||
|
});
|
||||||
|
|
||||||
|
// StateNotifier to manage CameraController
|
||||||
class CameraControllerNotifier extends StateNotifier<CameraController?> {
|
class CameraControllerNotifier extends StateNotifier<CameraController?> {
|
||||||
CameraControllerNotifier() : super(null);
|
CameraControllerNotifier() : super(null) {
|
||||||
|
_initializeCamera();
|
||||||
Future<void> initializeCamera(CameraDescription camera) async {
|
|
||||||
final controller = CameraController(camera, ResolutionPreset.medium);
|
|
||||||
await controller.initialize();
|
|
||||||
state = controller;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> takePicture() async {
|
Future<void> _initializeCamera() async {
|
||||||
if (state == null || !state!.value.isInitialized) {
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
throw Exception('Camera is not initialized');
|
try {
|
||||||
|
final cameras = await availableCameras();
|
||||||
|
if (cameras.isNotEmpty) {
|
||||||
|
final controller = CameraController(cameras[0], ResolutionPreset.max);
|
||||||
|
await controller.initialize();
|
||||||
|
state = controller;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error initializing camera: $e');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final path = p.join(
|
Future<void> takePicture(
|
||||||
(await getTemporaryDirectory()).path,
|
// ValueNotifier<XFile?> imageFile,
|
||||||
'${DateTime.now()}.png',
|
ValueNotifier<String> base64ImageString,
|
||||||
);
|
ValueNotifier<String> imagePath,
|
||||||
|
) async {
|
||||||
|
// final flag = ValueNotifier<bool>(false);
|
||||||
|
if (state != null) {
|
||||||
|
try {
|
||||||
|
final image = await state!.takePicture();
|
||||||
|
final bytes = await image.readAsBytes();
|
||||||
|
String base64Image = base64Encode(bytes);
|
||||||
|
|
||||||
await state!.takePicture();
|
// imageFile.value = image;
|
||||||
return path;
|
base64ImageString.value = base64Image;
|
||||||
|
imagePath.value = image.path;
|
||||||
|
|
||||||
|
// final shared = await SharedPreferences.getInstance();
|
||||||
|
// shared.setString("base64Image", base64Image);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error taking picture: $e');
|
||||||
|
// flag.value = false;
|
||||||
|
// RespErr(flag: false, message: 'Error taking picture: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print('CameraController is not initialized.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,90 +1,223 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:absensi_sas/widget/sankbar_widget.dart';
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class CameraPage extends StatefulWidget {
|
import '../../app/constant.dart';
|
||||||
const CameraPage({Key? key}) : super(key: key);
|
import '../../provider/camera_controller_provider.dart';
|
||||||
|
|
||||||
|
class CameraPage extends HookConsumerWidget {
|
||||||
|
const CameraPage({
|
||||||
|
Key? key,
|
||||||
|
required this.filePathParam,
|
||||||
|
required this.fileDataBase64Param,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final ValueNotifier<String> filePathParam;
|
||||||
|
final ValueNotifier<String> fileDataBase64Param;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CameraPage> createState() => _CameraPageState();
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
}
|
final controller = ref.watch(cameraControllerProvider);
|
||||||
|
// final imagePath = useState<String?>("");
|
||||||
|
// final fileDataBase64 = useState<String?>("");
|
||||||
|
|
||||||
class _CameraPageState extends State<CameraPage> {
|
// final fileData = useState<XFile?>(null);
|
||||||
CameraController? controller;
|
final filePath = useState<String>("");
|
||||||
String imagePath = "";
|
final fileDataBase64 = useState<String>("");
|
||||||
List<CameraDescription>? cameras;
|
final cameraController = useState<CameraController?>(null);
|
||||||
|
|
||||||
@override
|
useEffect(() {
|
||||||
void initState() {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||||
super.initState();
|
try {
|
||||||
initializeCamera();
|
final cameras = await availableCameras();
|
||||||
}
|
if (cameras.isNotEmpty) {
|
||||||
|
final controller =
|
||||||
Future<void> initializeCamera() async {
|
CameraController(cameras[0], ResolutionPreset.max);
|
||||||
// Initialize cameras
|
await controller.initialize();
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
cameraController.value = controller;
|
||||||
try {
|
}
|
||||||
cameras = await availableCameras();
|
} catch (e) {
|
||||||
if (cameras != null && cameras!.isNotEmpty) {
|
print('Error initializing camera: $e');
|
||||||
// Use the first available camera
|
|
||||||
controller = CameraController(cameras![0], ResolutionPreset.max);
|
|
||||||
await controller?.initialize();
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
return () {};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
Future<void> initializeCamera() async {
|
||||||
|
try {
|
||||||
|
final cameras = await availableCameras();
|
||||||
|
if (cameras.isNotEmpty) {
|
||||||
|
final controller = CameraController(cameras[0], ResolutionPreset.max);
|
||||||
|
await controller.initialize();
|
||||||
|
cameraController.value = controller;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error initializing camera: $e');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
print('Error initializing camera: $e');
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
Future<void> takePicture(
|
||||||
void dispose() {
|
// ValueNotifier<XFile?> imageFile,
|
||||||
controller?.dispose();
|
ValueNotifier<String> base64ImageString,
|
||||||
super.dispose();
|
ValueNotifier<String> imagePath,
|
||||||
}
|
) async {
|
||||||
|
// final flag = ValueNotifier<bool>(false);
|
||||||
|
if (cameraController.value != null) {
|
||||||
|
try {
|
||||||
|
final image = await cameraController.value!.takePicture();
|
||||||
|
final bytes = await image.readAsBytes();
|
||||||
|
String base64Image = base64Encode(bytes);
|
||||||
|
|
||||||
@override
|
// imageFile.value = image;
|
||||||
Widget build(BuildContext context) {
|
base64ImageString.value = base64Image;
|
||||||
if (controller == null || !controller!.value.isInitialized) {
|
imagePath.value = image.path;
|
||||||
return Center(child: CircularProgressIndicator());
|
|
||||||
|
fileDataBase64Param.value = base64Image;
|
||||||
|
filePathParam.value = image.path;
|
||||||
|
|
||||||
|
// final shared = await SharedPreferences.getInstance();
|
||||||
|
// shared.setString("base64Image", base64Image);
|
||||||
|
} catch (e) {
|
||||||
|
print('Error taking picture: $e');
|
||||||
|
// flag.value = false;
|
||||||
|
// RespErr(flag: false, message: 'Error taking picture: $e');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print('CameraController is not initialized.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processFoto(BuildContext context) async {
|
||||||
|
await takePicture(
|
||||||
|
// fileData,
|
||||||
|
fileDataBase64,
|
||||||
|
filePath,
|
||||||
|
);
|
||||||
|
|
||||||
|
print("fileDataBase64 : ${fileDataBase64.value}");
|
||||||
|
|
||||||
|
if (fileDataBase64.value != "") {
|
||||||
|
// ref.read(imgPhotoWebProvider.notifier).state = fileDataBase64.value;
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
} else {
|
||||||
|
print('Error: Image result is null');
|
||||||
|
}
|
||||||
|
|
||||||
|
// proses base64
|
||||||
|
// final shared = await SharedPreferences.getInstance();
|
||||||
|
// final imageBase64 = shared.getString("base64Image");
|
||||||
|
|
||||||
|
// if (imageBase64 != "") {
|
||||||
|
// fileDataBase64.value = imageBase64;
|
||||||
|
// ref.read(imgPhotoWebProvider.notifier).state = imageBase64;
|
||||||
|
// Navigator.of(context).pop();
|
||||||
|
// } else {
|
||||||
|
// print('Error: Image result is null');
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Take Photo'),
|
||||||
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(
|
child: controller == null || !controller.value.isInitialized
|
||||||
children: [
|
? const CircularProgressIndicator()
|
||||||
SizedBox(height: 50),
|
: Padding(
|
||||||
Container(
|
padding: EdgeInsets.all(20),
|
||||||
width: 200,
|
child: Column(
|
||||||
height: 200,
|
children: [
|
||||||
child: AspectRatio(
|
// const SizedBox(height: 50),
|
||||||
aspectRatio: controller!.value.aspectRatio,
|
Expanded(
|
||||||
child: CameraPreview(controller!),
|
child: AspectRatio(
|
||||||
|
aspectRatio: controller.value.aspectRatio,
|
||||||
|
child: CameraPreview(controller),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height:
|
||||||
|
Constant.getActualYPhone(context: context, y: 20),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
fileDataBase64Param.value = "";
|
||||||
|
filePathParam.value = "";
|
||||||
|
// cameraController.dispose();
|
||||||
|
// await controller.dispose();
|
||||||
|
// await initializeCamera();
|
||||||
|
},
|
||||||
|
child: const Text("Clear Foto"),
|
||||||
|
),
|
||||||
|
|
||||||
|
Spacer(),
|
||||||
|
ElevatedButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// Navigator.of(context).pushNamed(homeRoute);
|
||||||
|
// },
|
||||||
|
onPressed: () async {
|
||||||
|
processFoto(context);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateColor.resolveWith(
|
||||||
|
(st) => (fileDataBase64.value != "")
|
||||||
|
? Constant.textDarkGrey
|
||||||
|
: Constant.textOrange),
|
||||||
|
shape:
|
||||||
|
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
side: BorderSide(
|
||||||
|
color: Constant.textOrange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor:
|
||||||
|
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||||
|
elevation: MaterialStateProperty.all(4.0),
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
(fileDataBase64.value != "")
|
||||||
|
? SizedBox(
|
||||||
|
width: Constant.getActualXPhone(
|
||||||
|
context: context, x: 24),
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context, y: 32),
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Constant.textOrange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'Process Photo',
|
||||||
|
style: Constant.titleH1_500_18(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
color: Constant.textWhite,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// if (imagePath.value.isNotEmpty)
|
||||||
|
// Container(
|
||||||
|
// width: 300,
|
||||||
|
// height: 300,
|
||||||
|
// child: Image.network(imagePath.value),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
try {
|
|
||||||
final image = await controller!.takePicture();
|
|
||||||
setState(() {
|
|
||||||
imagePath = image.path;
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
print('Error taking picture: $e');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text("Take Photo"),
|
|
||||||
),
|
|
||||||
if (imagePath.isNotEmpty)
|
|
||||||
Container(
|
|
||||||
width: 300,
|
|
||||||
height: 300,
|
|
||||||
child: Image.file(File(imagePath)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
92
lib/screen/presensi/camera_page_v1.dart
Normal file
92
lib/screen/presensi/camera_page_v1.dart
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CameraPageV1 extends StatefulWidget {
|
||||||
|
const CameraPageV1({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CameraPageV1> createState() => _CameraPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CameraPageState extends State<CameraPageV1> {
|
||||||
|
CameraController? controller;
|
||||||
|
String imagePath = "";
|
||||||
|
List<CameraDescription>? cameras;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
initializeCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initializeCamera() async {
|
||||||
|
// Initialize cameras
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
try {
|
||||||
|
cameras = await availableCameras();
|
||||||
|
if (cameras != null && cameras!.isNotEmpty) {
|
||||||
|
// Use the first available camera
|
||||||
|
controller = CameraController(cameras![0], ResolutionPreset.max);
|
||||||
|
await controller?.initialize();
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error initializing camera: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
controller?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (controller == null || !controller!.value.isInitialized) {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
body: SafeArea(
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 50),
|
||||||
|
Container(
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: controller!.value.aspectRatio,
|
||||||
|
child: CameraPreview(controller!),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
final image = await controller!.takePicture();
|
||||||
|
setState(() {
|
||||||
|
imagePath = image.path;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
print('Error taking picture: $e');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text("Take Photo"),
|
||||||
|
),
|
||||||
|
if (imagePath.isNotEmpty)
|
||||||
|
Container(
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
child: Image.file(File(imagePath)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,9 +16,11 @@ import 'package:flutter_image_compress/flutter_image_compress.dart';
|
|||||||
// import 'package:geolocator/geolocator.dart';
|
// import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:image_picker_web/image_picker_web.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
import 'package:location/location.dart';
|
import 'package:location/location.dart';
|
||||||
import 'package:mobkit_dashed_border/mobkit_dashed_border.dart';
|
import 'package:mobkit_dashed_border/mobkit_dashed_border.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
// import 'package:permission_handler/permission_handler.dart';
|
// import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
import '../../app/constant.dart';
|
import '../../app/constant.dart';
|
||||||
@@ -35,7 +37,6 @@ import 'camera_page.dart';
|
|||||||
import 'check_distance_provider.dart';
|
import 'check_distance_provider.dart';
|
||||||
import 'check_presensi_jam_provider.dart';
|
import 'check_presensi_jam_provider.dart';
|
||||||
import 'googleapis_provider.dart';
|
import 'googleapis_provider.dart';
|
||||||
import 'presensi_selfie_upload_area.dart';
|
|
||||||
import 'dart:io' as io;
|
import 'dart:io' as io;
|
||||||
|
|
||||||
import 'presensi_selfie_upload_area_web.dart';
|
import 'presensi_selfie_upload_area_web.dart';
|
||||||
@@ -55,22 +56,19 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
final positionLatitude = useState<String>("");
|
final positionLatitude = useState<String>("");
|
||||||
final positionLongitude = useState<String>("");
|
final positionLongitude = useState<String>("");
|
||||||
// final tTransactionCurrentDistance = useState<String>("NULL");
|
|
||||||
|
|
||||||
final fileData = useState<XFile?>(null);
|
final fileData = useState<XFile?>(null);
|
||||||
final fileDataBase64 = useState<String>("");
|
final fileDataBase64 = useState<String>("");
|
||||||
|
final filePath = useState<String>("");
|
||||||
final isImage = useState(false);
|
final isImage = useState(false);
|
||||||
final fileEkstension = useState("");
|
final fileEkstension = useState("");
|
||||||
final fileSize = useState(0);
|
final fileSize = useState(0);
|
||||||
final fileName = useState("");
|
final fileName = useState("");
|
||||||
List<CameraDescription> cameras;
|
|
||||||
|
|
||||||
Location location = new Location();
|
Location location = new Location();
|
||||||
LocationData _locationData;
|
LocationData _locationData;
|
||||||
|
|
||||||
final controller = ref.watch(cameraControllerProvider);
|
// final imgPhotoWeb = ref.read(imgPhotoWebProvider);
|
||||||
final isInited = useState(false);
|
|
||||||
final imageUrl = useState<String?>(null);
|
|
||||||
|
|
||||||
getBase64() async {
|
getBase64() async {
|
||||||
// List<int> imageBytes = await fileData.value?.readAsBytes();
|
// List<int> imageBytes = await fileData.value?.readAsBytes();
|
||||||
@@ -94,47 +92,23 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
pickImage() async {
|
pickImage() async {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
|
// final shared = await SharedPreferences.getInstance();
|
||||||
|
// final imageBase64 = shared.getString("base64Image");
|
||||||
|
// final imagePathNew = shared.getString("imagePath");
|
||||||
try {
|
try {
|
||||||
final path =
|
Navigator.push(
|
||||||
await ref.read(cameraControllerProvider.notifier).takePicture();
|
context,
|
||||||
imageUrl.value = path;
|
MaterialPageRoute(
|
||||||
|
builder: (_) => CameraPage(
|
||||||
|
fileDataBase64Param: fileDataBase64,
|
||||||
|
filePathParam: filePath,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
SanckbarWidget(
|
SanckbarWidget(
|
||||||
context, "Failed to take picture", snackbarType.warning);
|
context, "Failed to take picture", snackbarType.warning);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
final XFile? pickedFile = await _picker.pickImage(
|
|
||||||
source: ImageSource.camera,
|
|
||||||
// maxWidth set untuk width image
|
|
||||||
maxWidth: 640,
|
|
||||||
// maxHeight set untuk width image
|
|
||||||
maxHeight: 480);
|
|
||||||
if (pickedFile != null) {
|
|
||||||
final tmpFile = FilePickerResult([
|
|
||||||
PlatformFile(
|
|
||||||
name: pickedFile.name,
|
|
||||||
size: await pickedFile.length(),
|
|
||||||
path: pickedFile.path,
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
if (await pickedFile.length() > 10000000) {
|
|
||||||
SanckbarWidget(context, "File tidak boleh lebih dari 10 MB",
|
|
||||||
snackbarType.warning);
|
|
||||||
} else {
|
|
||||||
fileData.value = pickedFile;
|
|
||||||
isImage.value = true;
|
|
||||||
fileEkstension.value = tmpFile.files.single.extension ?? "";
|
|
||||||
DateTime now = new DateTime.now();
|
|
||||||
fileName.value =
|
|
||||||
"IMG-${now.year}${now.month}${now.day}.${tmpFile.files.single.extension ?? ''}";
|
|
||||||
}
|
|
||||||
|
|
||||||
// final Directory appDocumentsDir =
|
|
||||||
// await getApplicationDocumentsDirectory();
|
|
||||||
// print(appDocumentsDir);
|
|
||||||
// await pickedFile!.saveTo(appDocumentsDir.path);
|
|
||||||
await getBase64();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,46 +756,51 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
)
|
)
|
||||||
: InkWell(
|
: InkWell(
|
||||||
onTap: () async {
|
onTap: () {
|
||||||
Navigator.push(
|
pickImage();
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (_) =>
|
|
||||||
CameraPage(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Container(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
width: Constant.getActualXPhone(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
context: context, x: 390),
|
||||||
children: [
|
height: Constant.getActualYPhone(
|
||||||
// Icon(
|
context: context,
|
||||||
// Icons.upload_outlined,
|
y: isImage.value ? 200 : 83),
|
||||||
// color: Constant.textOrange,
|
decoration: BoxDecoration(
|
||||||
// ),
|
color: Constant.bgUploadFile,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// Icon(
|
||||||
|
// Icons.upload_outlined,
|
||||||
|
// color: Constant.textOrange,
|
||||||
|
// ),
|
||||||
|
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'images/camera_selfie.png', // Path gambar untuk "Check In"
|
'images/camera_selfie.png', // Path gambar untuk "Check In"
|
||||||
width: Constant.getActualXPhone(
|
width: Constant.getActualXPhone(
|
||||||
context: context, x: 24),
|
context: context, x: 24),
|
||||||
height: Constant.getActualYPhone(
|
height: Constant.getActualYPhone(
|
||||||
context: context, y: 24),
|
context: context, y: 24),
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: Constant.getActualYPhone(
|
|
||||||
context: context,
|
|
||||||
y: 4,
|
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
Text(
|
height: Constant.getActualYPhone(
|
||||||
'Upload File',
|
context: context,
|
||||||
style: Constant.titleH2_400_12(
|
y: 4,
|
||||||
context: context)
|
),
|
||||||
.copyWith(
|
),
|
||||||
fontWeight: FontWeight.w600,
|
Text(
|
||||||
color: Constant.textOrange),
|
'Upload File',
|
||||||
)
|
style: Constant.titleH2_400_12(
|
||||||
],
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textOrange),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
] else ...[
|
] else ...[
|
||||||
@@ -833,18 +812,75 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
? Center(
|
? Center(
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
)
|
)
|
||||||
: PresensiSelfieUploadAreaWebWidget(
|
: InkWell(
|
||||||
isLoading: isLoadingAddressUserLocation,
|
onTap: () {
|
||||||
isImage: isImage,
|
pickImage();
|
||||||
fileData: fileData,
|
},
|
||||||
fileDataBase64: fileDataBase64,
|
child: Container(
|
||||||
pickFile: pickFile,
|
width: Constant.getActualXPhone(
|
||||||
pickImage: pickImage,
|
context: context, x: 390),
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context,
|
||||||
|
y: isImage.value ? 200 : 83),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.bgUploadFile,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// Icon(
|
||||||
|
// Icons.upload_outlined,
|
||||||
|
// color: Constant.textOrange,
|
||||||
|
// ),
|
||||||
|
|
||||||
|
Image.asset(
|
||||||
|
'images/camera_selfie.png', // Path gambar untuk "Check In"
|
||||||
|
width: Constant.getActualXPhone(
|
||||||
|
context: context, x: 24),
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context, y: 24),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context,
|
||||||
|
y: 4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Upload File',
|
||||||
|
style: Constant.titleH2_400_12(
|
||||||
|
context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textOrange),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// gambar selfie
|
||||||
|
if (fileDataBase64.value.isNotEmpty) ...[
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 40),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height:
|
||||||
|
Constant.getActualYPhone(context: context, y: 200),
|
||||||
|
child: Image.network(
|
||||||
|
filePath.value,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
Spacer(),
|
Spacer(),
|
||||||
|
|
||||||
// button clock in dan clock out
|
// button clock in dan clock out
|
||||||
@@ -924,9 +960,8 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
token,
|
token,
|
||||||
"Clock In");
|
"Clock In");
|
||||||
|
|
||||||
// print(
|
print(
|
||||||
// fileDataBase64.value,
|
"proses imageX: ${fileDataBase64.value}");
|
||||||
// );
|
|
||||||
},
|
},
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
|
||||||
import '../../app/constant.dart';
|
import '../../app/constant.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
|
|
||||||
class PresensiSelfieUploadAreaWebWidget extends StatelessWidget {
|
import '../../provider/camera_controller_provider.dart';
|
||||||
|
|
||||||
|
class PresensiSelfieUploadAreaWebWidget extends HookConsumerWidget {
|
||||||
const PresensiSelfieUploadAreaWebWidget({
|
const PresensiSelfieUploadAreaWebWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.isImage,
|
required this.isImage,
|
||||||
@@ -24,7 +29,9 @@ class PresensiSelfieUploadAreaWebWidget extends StatelessWidget {
|
|||||||
final Function pickFile;
|
final Function pickFile;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final imgPhotoWeb = ref.read(imgPhotoWebProvider);
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: !isLoading.value
|
onTap: !isLoading.value
|
||||||
? () {
|
? () {
|
||||||
|
|||||||
Reference in New Issue
Block a user