step 8 : fix issue camera prevent hardware karena OBS terinstall
This commit is contained in:
38
lib/provider/camera_controller_provider.dart
Normal file
38
lib/provider/camera_controller_provider.dart
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
final cameraControllerProvider =
|
||||||
|
StateNotifierProvider<CameraControllerNotifier, CameraController?>(
|
||||||
|
(ref) => CameraControllerNotifier());
|
||||||
|
|
||||||
|
class CameraControllerNotifier extends StateNotifier<CameraController?> {
|
||||||
|
CameraControllerNotifier() : super(null);
|
||||||
|
|
||||||
|
Future<void> initializeCamera(CameraDescription camera) async {
|
||||||
|
final controller = CameraController(camera, ResolutionPreset.medium);
|
||||||
|
await controller.initialize();
|
||||||
|
state = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> takePicture() async {
|
||||||
|
if (state == null || !state!.value.isInitialized) {
|
||||||
|
throw Exception('Camera is not initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
final path = p.join(
|
||||||
|
(await getTemporaryDirectory()).path,
|
||||||
|
'${DateTime.now()}.png',
|
||||||
|
);
|
||||||
|
|
||||||
|
await state!.takePicture();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
state?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
92
lib/screen/presensi/camera_page.dart
Normal file
92
lib/screen/presensi/camera_page.dart
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CameraPage extends StatefulWidget {
|
||||||
|
const CameraPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CameraPage> createState() => _CameraPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CameraPageState extends State<CameraPage> {
|
||||||
|
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)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:camera_web/camera_web.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:absensi_sas/repository/googleapis_repository.dart';
|
import 'package:absensi_sas/repository/googleapis_repository.dart';
|
||||||
import 'package:absensi_sas/screen/presensi/presensi_clock_in_provider.dart';
|
import 'package:absensi_sas/screen/presensi/presensi_clock_in_provider.dart';
|
||||||
import 'package:absensi_sas/screen/presensi/presensi_clock_out_provider.dart';
|
import 'package:absensi_sas/screen/presensi/presensi_clock_out_provider.dart';
|
||||||
import 'package:absensi_sas/widget/custom_drawer.dart';
|
import 'package:absensi_sas/widget/custom_drawer.dart';
|
||||||
import 'package:dart_nominatim/dart_nominatim.dart';
|
import 'package:dart_nominatim/dart_nominatim.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||||
// import 'package:geocoding/geocoding.dart';
|
// import 'package:geocoding/geocoding.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';
|
||||||
@@ -20,6 +23,7 @@ import 'package:mobkit_dashed_border/mobkit_dashed_border.dart';
|
|||||||
|
|
||||||
import '../../app/constant.dart';
|
import '../../app/constant.dart';
|
||||||
import '../../app/route.dart';
|
import '../../app/route.dart';
|
||||||
|
import '../../provider/camera_controller_provider.dart';
|
||||||
import '../../provider/current_check_distance_provider.dart';
|
import '../../provider/current_check_distance_provider.dart';
|
||||||
import '../../provider/current_check_jam_presensi_provider.dart';
|
import '../../provider/current_check_jam_presensi_provider.dart';
|
||||||
import '../../provider/current_user_provider.dart';
|
import '../../provider/current_user_provider.dart';
|
||||||
@@ -27,12 +31,15 @@ import '../../widget/custom_dialog_presensi_selfie_sukses.dart';
|
|||||||
import '../../widget/real_date.dart';
|
import '../../widget/real_date.dart';
|
||||||
import '../../widget/real_time.dart';
|
import '../../widget/real_time.dart';
|
||||||
import '../../widget/sankbar_widget.dart';
|
import '../../widget/sankbar_widget.dart';
|
||||||
|
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 'presensi_selfie_upload_area.dart';
|
||||||
import 'dart:io' as io;
|
import 'dart:io' as io;
|
||||||
|
|
||||||
|
import 'presensi_selfie_upload_area_web.dart';
|
||||||
|
|
||||||
class PresensiSelfieScreen extends HookConsumerWidget {
|
class PresensiSelfieScreen extends HookConsumerWidget {
|
||||||
const PresensiSelfieScreen({super.key});
|
const PresensiSelfieScreen({super.key});
|
||||||
|
|
||||||
@@ -56,10 +63,15 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
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 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();
|
||||||
if (fileData.value != null) {
|
if (fileData.value != null) {
|
||||||
@@ -79,38 +91,50 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final ImagePicker _picker = ImagePicker();
|
final ImagePicker _picker = ImagePicker();
|
||||||
pickImage() async {
|
|
||||||
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 =
|
pickImage() async {
|
||||||
// await getApplicationDocumentsDirectory();
|
if (kIsWeb) {
|
||||||
// print(appDocumentsDir);
|
try {
|
||||||
// await pickedFile!.saveTo(appDocumentsDir.path);
|
final path =
|
||||||
await getBase64();
|
await ref.read(cameraControllerProvider.notifier).takePicture();
|
||||||
|
imageUrl.value = path;
|
||||||
|
} catch (e) {
|
||||||
|
SanckbarWidget(
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +196,7 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
isLoadingAddressUserLocation.value = true;
|
isLoadingAddressUserLocation.value = true;
|
||||||
// Mendapatkan posisi pengguna
|
// Mendapatkan posisi pengguna
|
||||||
// LocationPermission permission = await Geolocator.requestPermission();
|
// LocationPermission permission = await Geolocator.requestPermission();
|
||||||
final permission = await location.hasPermission();
|
final permission = await location.hasPermission();
|
||||||
|
|
||||||
if (permission == PermissionStatus.denied) {
|
if (permission == PermissionStatus.denied) {
|
||||||
isLoadingAddressUserLocation.value = false;
|
isLoadingAddressUserLocation.value = false;
|
||||||
@@ -757,13 +781,48 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
? Center(
|
? Center(
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
)
|
)
|
||||||
: PresensiSelfieUploadAreaWidget(
|
: InkWell(
|
||||||
isLoading: isLoadingAddressUserLocation,
|
onTap: () async {
|
||||||
isImage: isImage,
|
Navigator.push(
|
||||||
fileData: fileData,
|
context,
|
||||||
fileDataBase64: fileDataBase64,
|
MaterialPageRoute(
|
||||||
pickFile: pickFile,
|
builder: (_) =>
|
||||||
pickImage: pickImage,
|
CameraPage(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
] else ...[
|
] else ...[
|
||||||
// gambar icon presensi clock out
|
// gambar icon presensi clock out
|
||||||
@@ -774,7 +833,7 @@ class PresensiSelfieScreen extends HookConsumerWidget {
|
|||||||
? Center(
|
? Center(
|
||||||
child: CircularProgressIndicator(),
|
child: CircularProgressIndicator(),
|
||||||
)
|
)
|
||||||
: PresensiSelfieUploadAreaWidget(
|
: PresensiSelfieUploadAreaWebWidget(
|
||||||
isLoading: isLoadingAddressUserLocation,
|
isLoading: isLoadingAddressUserLocation,
|
||||||
isImage: isImage,
|
isImage: isImage,
|
||||||
fileData: fileData,
|
fileData: fileData,
|
||||||
|
|||||||
198
lib/screen/presensi/presensi_selfie_upload_area_web.dart
Normal file
198
lib/screen/presensi/presensi_selfie_upload_area_web.dart
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import '../../app/constant.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:mime/mime.dart';
|
||||||
|
|
||||||
|
class PresensiSelfieUploadAreaWebWidget extends StatelessWidget {
|
||||||
|
const PresensiSelfieUploadAreaWebWidget({
|
||||||
|
super.key,
|
||||||
|
required this.isImage,
|
||||||
|
required this.fileData,
|
||||||
|
required this.fileDataBase64,
|
||||||
|
required this.pickFile,
|
||||||
|
required this.pickImage,
|
||||||
|
required this.isLoading,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ValueNotifier<bool> isImage;
|
||||||
|
final ValueNotifier<bool> isLoading;
|
||||||
|
final ValueNotifier<XFile?> fileData;
|
||||||
|
final ValueNotifier<String> fileDataBase64;
|
||||||
|
final Function pickImage;
|
||||||
|
final Function pickFile;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: !isLoading.value
|
||||||
|
? () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return Container(
|
||||||
|
height: Constant.getActualYPhone(context: context, y: 200),
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// Column(
|
||||||
|
// children: [
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// Navigator.pop(context);
|
||||||
|
// pickFile();
|
||||||
|
// },
|
||||||
|
// icon: Icon(
|
||||||
|
// Icons.folder_copy_rounded,
|
||||||
|
// size: 50,
|
||||||
|
// color: Constant.textOrange,
|
||||||
|
// )),
|
||||||
|
// Text(
|
||||||
|
// "Browse a file",
|
||||||
|
// style: Constant.titleH2_400_12(context: context)
|
||||||
|
// .copyWith(
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
// color: Constant.textBlack,
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
pickImage();
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.add_a_photo_rounded,
|
||||||
|
size: 50,
|
||||||
|
color: Constant.textOrange,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context, y: 10),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Take a picture",
|
||||||
|
style: Constant.titleH2_400_12(context: context)
|
||||||
|
.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Constant.textBlack,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Stack(
|
||||||
|
alignment: AlignmentDirectional.topEnd,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: Constant.getActualXPhone(context: context, x: 390),
|
||||||
|
height: Constant.getActualYPhone(
|
||||||
|
context: context, y: isImage.value ? 200 : 83),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Constant.bgUploadFile,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
final String? mime = lookupMimeType(fileData.value?.path ?? "");
|
||||||
|
return Semantics(
|
||||||
|
label: 'image_picker_example_picked_image',
|
||||||
|
child: (mime != null
|
||||||
|
? (mime.startsWith('image/'))
|
||||||
|
? Image.network(
|
||||||
|
// image: AssetImage(photo.value!.path),
|
||||||
|
fileData.value!.path,
|
||||||
|
frameBuilder: (context, child, frame,
|
||||||
|
wasSynchronouslyLoaded) {
|
||||||
|
return (wasSynchronouslyLoaded)
|
||||||
|
? Center(
|
||||||
|
child: Text("Loadinga"),
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
errorBuilder: (BuildContext context, Object error,
|
||||||
|
StackTrace? stackTrace) {
|
||||||
|
return const Center(
|
||||||
|
child: Text(
|
||||||
|
'This image type is not supported'));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.file_present_rounded,
|
||||||
|
size: 40,
|
||||||
|
color: Constant.textOrange,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
fileData.value?.name ?? '',
|
||||||
|
style:
|
||||||
|
Constant.titleH2_400(context: context),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: 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),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)));
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
if (fileData.value != null && !isLoading.value)
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
fileData.value = null;
|
||||||
|
fileDataBase64.value = '';
|
||||||
|
isImage.value = false;
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.cancel_outlined)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
pubspec.lock
62
pubspec.lock
@@ -41,6 +41,46 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
|
camera:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: camera
|
||||||
|
sha256: "26ff41045772153f222ffffecba711a206f670f5834d40ebf5eed3811692f167"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.11.0+2"
|
||||||
|
camera_android_camerax:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: camera_android_camerax
|
||||||
|
sha256: "7cd93578ad201dcc6bb5810451fb00d76a86bab9b68dceb68b8cbd7038ac5846"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.8+3"
|
||||||
|
camera_avfoundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: camera_avfoundation
|
||||||
|
sha256: "7c28969a975a7eb2349bc2cb2dfe3ad218a33dba9968ecfb181ce08c87486655"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.17+3"
|
||||||
|
camera_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: camera_platform_interface
|
||||||
|
sha256: b3ede1f171532e0d83111fe0980b46d17f1aa9788a07a2fbed07366bbdbb9061
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.8.0"
|
||||||
|
camera_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: camera_web
|
||||||
|
sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.5"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -262,6 +302,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.18.6"
|
version: "0.18.6"
|
||||||
|
flutter_image_compress:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_image_compress
|
||||||
|
sha256: "37f1b26399098e5f97b74c1483f534855e7dff68ead6ddaccf747029fb03f29f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.3"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -777,7 +825,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.2"
|
version: "3.3.2"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||||
@@ -1069,6 +1117,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
stream_transform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_transform
|
||||||
|
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1238,5 +1294,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.4.0 <4.0.0"
|
dart: ">=3.5.0 <4.0.0"
|
||||||
flutter: ">=3.19.0"
|
flutter: ">=3.24.0"
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ dependencies:
|
|||||||
image_picker_web: ^4.0.0
|
image_picker_web: ^4.0.0
|
||||||
dart_nominatim: ^1.0.1
|
dart_nominatim: ^1.0.1
|
||||||
location: ^5.0.0
|
location: ^5.0.0
|
||||||
|
# camera_web: ^0.3.5
|
||||||
|
camera: ^0.11.0+2
|
||||||
|
flutter_image_compress: ^1.1.0
|
||||||
|
path: ^1.8.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user