Commit 28db98a7 authored by Dio Maulana's avatar Dio Maulana

update design

parent 3107e9e1
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart';
import 'package:tour_travel_agr/api/response_api.dart'; import 'package:tour_travel_agr/api/response_api.dart';
import 'package:tour_travel_agr/helper/function/replace_date.dart'; import 'package:tour_travel_agr/helper/function/replace_date.dart';
import 'package:tour_travel_agr/helper/prefs.dart'; import 'package:tour_travel_agr/helper/prefs.dart';
...@@ -10,6 +11,7 @@ import 'package:tour_travel_agr/models/transaction_model.dart'; ...@@ -10,6 +11,7 @@ import 'package:tour_travel_agr/models/transaction_model.dart';
import 'package:tour_travel_agr/resource/constanta_string.dart'; import 'package:tour_travel_agr/resource/constanta_string.dart';
import 'package:tour_travel_agr/resource/routes.dart'; import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/strings.dart'; import 'package:tour_travel_agr/resource/strings.dart';
import 'package:http/http.dart' as http;
class Api { class Api {
static Future<ApiResponse> login( static Future<ApiResponse> login(
...@@ -456,14 +458,24 @@ class Api { ...@@ -456,14 +458,24 @@ class Api {
"name": name, "name": name,
"nik": "", "nik": "",
"mobile_phone": "", "mobile_phone": "",
"photo_base64": photo, "photo_base64": photo ?? "",
}; };
MultipartFile? multiPartFile;
// if (photo != null) {
// multiPartFile = http.MultipartFile.fromBytes(
// "photo_base64",
// photo.toList(),
// );
// }
String bodies = jsonEncode(data); String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest( dynamic jsonObject = await httpRequest(
typePost, typePost,
apiUrl, apiUrl,
"changeProfile", "changeProfile",
bodies: bodies, bodies: bodies,
isMultiPartRequest: true,
multipartFile: multiPartFile,
); );
if (jsonObject == false) { if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer); return ApiResponse(error: true, msg: Strings.cantConnectToServer);
......
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:http/http.dart';
import 'package:tour_travel_agr/helper/logger.dart'; import 'package:tour_travel_agr/helper/logger.dart';
import 'package:tour_travel_agr/main.dart'; import 'package:tour_travel_agr/main.dart';
...@@ -20,11 +21,33 @@ int typeGet = 1; ...@@ -20,11 +21,33 @@ int typeGet = 1;
int typePost = 2; int typePost = 2;
Future<dynamic> httpRequest(int typeRequest, String apiUrl, String namaFungsi, Future<dynamic> httpRequest(int typeRequest, String apiUrl, String namaFungsi,
{String? bodies = ''}) async { {String? bodies = '',
bool isMultiPartRequest = false,
http.MultipartFile? multipartFile}) async {
dynamic apiResult; dynamic apiResult;
if (typeRequest == typePost) { if (typeRequest == typePost) {
if (isMultiPartRequest == false) {
apiResult = await http.post(Uri.parse(apiUrl), apiResult = await http.post(Uri.parse(apiUrl),
headers: {"Content-Type": "application/json"}, body: bodies); headers: {"Content-Type": "application/json"}, body: bodies);
} else {
MultipartRequest request =
http.MultipartRequest('POST', Uri.parse(apiUrl));
if (multipartFile != null) {
request.files.add(
multipartFile,
);
}
if (bodies != null || bodies != "") {
dynamic jsonDecodeBodies = jsonDecode(bodies!);
jsonDecodeBodies.forEach((key, value) {
request.fields[key] = value.toString();
});
}
late http.StreamedResponse streamedResponse;
streamedResponse = await http.Client().send(request);
apiResult = await http.Response.fromStream(streamedResponse);
}
} else if (typeRequest == typeGet) { } else if (typeRequest == typeGet) {
apiResult = await http.get( apiResult = await http.get(
Uri.parse(apiUrl), Uri.parse(apiUrl),
......
...@@ -12,11 +12,13 @@ class ListTransaction extends StatelessWidget { ...@@ -12,11 +12,13 @@ class ListTransaction extends StatelessWidget {
this.date, this.date,
this.title, this.title,
this.subtitle, this.subtitle,
this.isCompletedShow = false,
}); });
final String? date; final String? date;
final String? title; final String? title;
final String? subtitle; final String? subtitle;
final bool isCompletedShow;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -99,7 +101,8 @@ class ListTransaction extends StatelessWidget { ...@@ -99,7 +101,8 @@ class ListTransaction extends StatelessWidget {
), ),
), ),
), ),
Container( Expanded(
child: Container(
margin: EdgeInsets.only( margin: EdgeInsets.only(
left: AppMargin.m16, left: AppMargin.m16,
), ),
...@@ -108,17 +111,33 @@ class ListTransaction extends StatelessWidget { ...@@ -108,17 +111,33 @@ class ListTransaction extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
(title != null) (title != null)
? Text( ? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title!, title!,
style: getBoldStyle( style: getBoldStyle(
color: Colors.black, color: Colors.black,
fontFamily: FontConstants.mulish, fontFamily: FontConstants.mulish,
fontSize: 18, fontSize: 18,
), ),
),
(isCompletedShow)
? Text(
'Selesai',
style: getBoldStyle(
color: ColorManager.green,
fontFamily: FontConstants.mulish,
fontSize: 14,
),
)
: const SizedBox(),
],
) )
: Shimmer.fromColors( : Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer, baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer, highlightColor:
ColorManager.highlightColorShimmer,
child: Container( child: Container(
width: 80, width: 80,
height: 15, height: 15,
...@@ -138,7 +157,8 @@ class ListTransaction extends StatelessWidget { ...@@ -138,7 +157,8 @@ class ListTransaction extends StatelessWidget {
) )
: Shimmer.fromColors( : Shimmer.fromColors(
baseColor: ColorManager.baseColorShimmer, baseColor: ColorManager.baseColorShimmer,
highlightColor: ColorManager.highlightColorShimmer, highlightColor:
ColorManager.highlightColorShimmer,
child: Container( child: Container(
margin: const EdgeInsets.only( margin: const EdgeInsets.only(
top: 10, top: 10,
...@@ -153,6 +173,7 @@ class ListTransaction extends StatelessWidget { ...@@ -153,6 +173,7 @@ class ListTransaction extends StatelessWidget {
), ),
], ],
), ),
),
) )
], ],
) )
......
...@@ -26,6 +26,7 @@ class ListTransactionModel { ...@@ -26,6 +26,7 @@ class ListTransactionModel {
String branchCode; String branchCode;
String bussinesDate; String bussinesDate;
String total; String total;
String branchName;
ListTransactionModel({ ListTransactionModel({
required this.id, required this.id,
...@@ -35,6 +36,7 @@ class ListTransactionModel { ...@@ -35,6 +36,7 @@ class ListTransactionModel {
required this.branchCode, required this.branchCode,
required this.bussinesDate, required this.bussinesDate,
required this.total, required this.total,
required this.branchName,
}); });
factory ListTransactionModel.json(Map<String, dynamic> json) { factory ListTransactionModel.json(Map<String, dynamic> json) {
...@@ -46,6 +48,7 @@ class ListTransactionModel { ...@@ -46,6 +48,7 @@ class ListTransactionModel {
branchCode: json['branch_code'], branchCode: json['branch_code'],
bussinesDate: json['business_date'], bussinesDate: json['business_date'],
total: json['total'], total: json['total'],
branchName: json['branch_name'] ?? "",
); );
} }
} }
...@@ -283,7 +283,7 @@ class _BodyWidgetState extends State<BodyWidget> { ...@@ -283,7 +283,7 @@ class _BodyWidgetState extends State<BodyWidget> {
date: dateLocal(transactions! date: dateLocal(transactions!
.listTransaction[index].bussinesDate), .listTransaction[index].bussinesDate),
title: title:
transactions!.listTransaction[index].brandCode, transactions!.listTransaction[index].branchName,
subtitle: subtitle:
"Rp ${parsingAmountBackend(transactions!.listTransaction[index].total)}", "Rp ${parsingAmountBackend(transactions!.listTransaction[index].total)}",
); );
......
...@@ -121,7 +121,7 @@ class _BodyWIdgetState extends State<BodyWIdget> { ...@@ -121,7 +121,7 @@ class _BodyWIdgetState extends State<BodyWIdget> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Welcome", "Selamat Datang",
style: getRegularStyle( style: getRegularStyle(
color: Colors.black, color: Colors.black,
fontFamily: FontConstants.mulish, fontFamily: FontConstants.mulish,
...@@ -187,7 +187,7 @@ class _BodyWIdgetState extends State<BodyWIdget> { ...@@ -187,7 +187,7 @@ class _BodyWIdgetState extends State<BodyWIdget> {
}, },
child: CardSectionHome( child: CardSectionHome(
title: "Reimburse", title: "Reimburse",
subtitle: "List Data Reimbursement", subtitle: "Riwayat Reimbursement",
logo: Assets.reimburseIcon, logo: Assets.reimburseIcon,
), ),
), ),
...@@ -202,7 +202,7 @@ class _BodyWIdgetState extends State<BodyWIdget> { ...@@ -202,7 +202,7 @@ class _BodyWIdgetState extends State<BodyWIdget> {
}, },
child: CardSectionHome( child: CardSectionHome(
title: "History", title: "History",
subtitle: "Riwayat Penjualan", subtitle: "Riwayat Transaksi",
logo: Assets.historyIcon, logo: Assets.historyIcon,
), ),
), ),
...@@ -239,8 +239,7 @@ class _BodyWIdgetState extends State<BodyWIdget> { ...@@ -239,8 +239,7 @@ class _BodyWIdgetState extends State<BodyWIdget> {
}, },
child: CardSectionHome( child: CardSectionHome(
title: "Profile", title: "Profile",
subtitle: subtitle: "",
"List Report Harian, Mingguan dan Bulanan",
logo: Assets.profileIcon, logo: Assets.profileIcon,
), ),
), ),
......
...@@ -116,6 +116,7 @@ class _BodyWidgetState extends State<BodyWidget> { ...@@ -116,6 +116,7 @@ class _BodyWidgetState extends State<BodyWidget> {
controller: widget.whatsappController, controller: widget.whatsappController,
labelText: "No. Whatsapp", labelText: "No. Whatsapp",
hintText: "628...", hintText: "628...",
inputType: TextInputType.number,
marginActive: false, marginActive: false,
onChanged: (val) { onChanged: (val) {
if (widget.whatsappController.text.length >= if (widget.whatsappController.text.length >=
...@@ -176,7 +177,7 @@ class _BodyWidgetState extends State<BodyWidget> { ...@@ -176,7 +177,7 @@ class _BodyWidgetState extends State<BodyWidget> {
), ),
), ),
CustomButton( CustomButton(
text: "Login", text: "Masuk",
colorButton: buttonLoginActive colorButton: buttonLoginActive
? ColorManager.primary ? ColorManager.primary
: Colors.grey, : Colors.grey,
......
// ignore_for_file: use_build_context_synchronously
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:js_interop';
import 'dart:js_util';
import 'package:file_picker/file_picker.dart'; // import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:image_picker/image_picker.dart';
import 'package:tour_travel_agr/api/all_api.dart'; import 'package:tour_travel_agr/api/all_api.dart';
import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart'; import 'package:tour_travel_agr/helper/components_widget/custom_appbar.dart';
import 'package:tour_travel_agr/helper/components_widget/widget_button.dart'; import 'package:tour_travel_agr/helper/components_widget/widget_button.dart';
...@@ -18,6 +24,9 @@ import 'package:tour_travel_agr/resource/routes.dart'; ...@@ -18,6 +24,9 @@ import 'package:tour_travel_agr/resource/routes.dart';
import 'package:tour_travel_agr/resource/size.dart'; import 'package:tour_travel_agr/resource/size.dart';
import 'package:tour_travel_agr/resource/strings.dart'; import 'package:tour_travel_agr/resource/strings.dart';
@JS('compressImage')
external dynamic compressImage(byte, quality);
class EditProfileView extends StatefulWidget { class EditProfileView extends StatefulWidget {
const EditProfileView({ const EditProfileView({
super.key, super.key,
...@@ -36,6 +45,7 @@ class _EditProfileViewState extends State<EditProfileView> { ...@@ -36,6 +45,7 @@ class _EditProfileViewState extends State<EditProfileView> {
TextEditingController nameController = TextEditingController(); TextEditingController nameController = TextEditingController();
TextEditingController nikController = TextEditingController(); TextEditingController nikController = TextEditingController();
TextEditingController hpController = TextEditingController(); TextEditingController hpController = TextEditingController();
List<String> allowedExt = ['jpg', 'png', 'jpeg'];
Uint8List? byteImage; Uint8List? byteImage;
String? base64Image; String? base64Image;
...@@ -50,6 +60,29 @@ class _EditProfileViewState extends State<EditProfileView> { ...@@ -50,6 +60,29 @@ class _EditProfileViewState extends State<EditProfileView> {
super.initState(); super.initState();
} }
// Uint8List compressImage(Uint8List imageBytes, int quality) {
// final image = img.decodeImage(imageBytes);
// // Mengompres gambar dengan kualitas yang ditentukan
// final compressedImage = img.encodeJpg(image!, quality: quality);
// return compressedImage;
// }
// Future<Uint8List> compressImage(Uint8List imageBytes, int quality) async {
// final jsObject =
// js.JsObject(js.context['compressImage'], [imageBytes, quality]);
// final compressedBytes = await jsObject.callMethod('compressImage');
// return Uint8List.fromList(compressedBytes);
// }
int maxSizeToCompare = 5242880;
int qualityCompare = 80;
Future<dynamic> compressImageJs(Uint8List imageBytes, int quality) async {
dynamic result = await promiseToFuture(compressImage(imageBytes, quality));
return result;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
...@@ -71,7 +104,7 @@ class _EditProfileViewState extends State<EditProfileView> { ...@@ -71,7 +104,7 @@ class _EditProfileViewState extends State<EditProfileView> {
), ),
child: Column( child: Column(
children: [ children: [
const CustomAppBar(text: "Edit Profile"), const CustomAppBar(text: "Edit Profil"),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
...@@ -79,24 +112,93 @@ class _EditProfileViewState extends State<EditProfileView> { ...@@ -79,24 +112,93 @@ class _EditProfileViewState extends State<EditProfileView> {
children: [ children: [
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
FilePickerResult? result = final imagePicker = ImagePicker();
await FilePicker.platform.pickFiles(); XFile? pickedImage = await imagePicker.pickImage(
if (result != null) { source: ImageSource.gallery);
PlatformFile file = result.files.first; if (pickedImage != null) {
Uint8List uint8 = await pickedImage.readAsBytes();
// print(file.name); String ext =
// print(file.bytes); pickedImage.name.split('.').last.toLowerCase();
// print(file.size); // print(compressImage(uint8, 50));
// print(file.extension); if (!allowedExt.contains(ext)) {
// print(file); modalDialogGlobal(
context: context,
title: "Informasi",
contentBody:
"Hanya mendukung gambar dengan format ${allowedExt.join(', ')}, silakan pilih file lainnya",
buttonText: "OK",
tapButton: () {
Navigator.pop(context);
},
);
return;
}
if (uint8.length > maxSizeToCompare) {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
dynamic resultCompress =
await compressImageJs(uint8, qualityCompare);
EasyLoading.dismiss();
if (resultCompress.runtimeType != Uint8List) {
modalDialogGlobal(
context: context,
title: "Informasi",
contentBody:
"Kesalahan saat melakukan deteksi gambar",
buttonText: "OK",
tapButton: () {
Navigator.pop(context);
},
);
}
setState(() { setState(() {
byteImage = file.bytes; byteImage = resultCompress;
base64Image = base64Encode(byteImage!); base64Image = base64Encode(byteImage!);
}); });
// print(file.path);
} else { } else {
// User canceled the picker setState(() {
byteImage = uint8;
base64Image = base64Encode(byteImage!);
});
} }
}
// FilePickerResult? result =
// await FilePicker.platform.pickFiles();
// if (result != null) {
// PlatformFile file = result.files.first;
// String ext = file.name.split('.').last.toLowerCase();
// if (!allowedExt.contains(ext)) {
// modalDialogGlobal(
// context: context,
// title: "Informasi",
// contentBody:
// "Hanya mendukung gambar dengan format ${allowedExt.join(', ')}, silakan pilih file lainnya",
// buttonText: "OK",
// tapButton: () {
// Navigator.pop(context);
// },
// );
// return;
// }
// // print(file.name);
// // print(file.bytes);
// // print(file.size);
// // print(file.extension);
// // print(file.path);
// if (file.size > 2097152) {
// await testComporessList(file.bytes!);
// } else {}
// setState(() {
// byteImage = file.bytes;
// base64Image = base64Encode(byteImage!);
// });
// // print(file.path);
// } else {
// // User canceled the picker
// }
}, },
child: Container( child: Container(
margin: EdgeInsets.only( margin: EdgeInsets.only(
...@@ -163,7 +265,7 @@ class _EditProfileViewState extends State<EditProfileView> { ...@@ -163,7 +265,7 @@ class _EditProfileViewState extends State<EditProfileView> {
Container( Container(
margin: const EdgeInsets.only(top: 30), margin: const EdgeInsets.only(top: 30),
child: CustomButton( child: CustomButton(
text: "Update", text: "Ubah",
onTap: () async { onTap: () async {
await EasyLoading.show( await EasyLoading.show(
status: Strings.pleaseWait, status: Strings.pleaseWait,
......
...@@ -38,6 +38,8 @@ class _RegisterViewState extends State<RegisterView> { ...@@ -38,6 +38,8 @@ class _RegisterViewState extends State<RegisterView> {
bool isChecked = false; bool isChecked = false;
bool buttonRegisterActive = false; bool buttonRegisterActive = false;
int nikAllowedLength = 16;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
...@@ -60,7 +62,7 @@ class _RegisterViewState extends State<RegisterView> { ...@@ -60,7 +62,7 @@ class _RegisterViewState extends State<RegisterView> {
child: Column( child: Column(
children: [ children: [
const CustomAppBar( const CustomAppBar(
text: "Register", text: "Daftar",
), ),
Expanded( Expanded(
child: SingleChildScrollView( child: SingleChildScrollView(
...@@ -83,6 +85,8 @@ class _RegisterViewState extends State<RegisterView> { ...@@ -83,6 +85,8 @@ class _RegisterViewState extends State<RegisterView> {
borderSideActive: true, borderSideActive: true,
hintText: "Nomor induk kependudukan", hintText: "Nomor induk kependudukan",
marginTop: AppMargin.m12, marginTop: AppMargin.m12,
inputType: TextInputType.number,
maxLength: nikAllowedLength,
), ),
InputTextField( InputTextField(
controller: noHpController, controller: noHpController,
...@@ -90,6 +94,7 @@ class _RegisterViewState extends State<RegisterView> { ...@@ -90,6 +94,7 @@ class _RegisterViewState extends State<RegisterView> {
labelColor: ColorManager.primary, labelColor: ColorManager.primary,
borderSideActive: true, borderSideActive: true,
hintText: "628...", hintText: "628...",
inputType: TextInputType.number,
marginTop: AppMargin.m12, marginTop: AppMargin.m12,
), ),
PasswordInput( PasswordInput(
...@@ -150,7 +155,7 @@ class _RegisterViewState extends State<RegisterView> { ...@@ -150,7 +155,7 @@ class _RegisterViewState extends State<RegisterView> {
bottom: AppMargin.m20, bottom: AppMargin.m20,
), ),
child: CustomButton( child: CustomButton(
text: "Register", text: "Daftar",
colorButton: buttonRegisterActive colorButton: buttonRegisterActive
? ColorManager.primary ? ColorManager.primary
: Colors.grey, : Colors.grey,
...@@ -170,7 +175,7 @@ class _RegisterViewState extends State<RegisterView> { ...@@ -170,7 +175,7 @@ class _RegisterViewState extends State<RegisterView> {
); );
return; return;
} }
if (nikController.text.length != 16) { if (nikController.text.length != nikAllowedLength) {
modalDialogGlobal( modalDialogGlobal(
context: context, context: context,
size: MediaQuery.of(context).size, size: MediaQuery.of(context).size,
......
...@@ -263,6 +263,7 @@ class _BodyWidgetState extends State<BodyWidget> { ...@@ -263,6 +263,7 @@ class _BodyWidgetState extends State<BodyWidget> {
subtitle: "Rp ${parsingAmountBackend( subtitle: "Rp ${parsingAmountBackend(
dataReimburse![index].comissionAmount, dataReimburse![index].comissionAmount,
)}", )}",
isCompletedShow: true,
); );
}, },
), ),
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
...@@ -5,10 +5,12 @@ ...@@ -5,10 +5,12 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import file_selector_macos
import package_info_plus import package_info_plus
import shared_preferences_foundation import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
} }
...@@ -41,6 +41,14 @@ packages: ...@@ -41,6 +41,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
charcode:
dependency: transitive
description:
name: charcode
sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
url: "https://pub.dev"
source: hosted
version: "1.3.1"
clock: clock:
dependency: transitive dependency: transitive
description: description:
...@@ -65,6 +73,14 @@ packages: ...@@ -65,6 +73,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.1.1"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
url: "https://pub.dev"
source: hosted
version: "0.3.3+4"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
...@@ -121,6 +137,38 @@ packages: ...@@ -121,6 +137,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.2" version: "5.3.2"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "770eb1ab057b5ae4326d1c24cc57710758b9a46026349d021d6311bd27580046"
url: "https://pub.dev"
source: hosted
version: "0.9.2"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: "7a6f1ae6107265664f3f7f89a66074882c4d506aef1441c9af313c1f7e6f41ce"
url: "https://pub.dev"
source: hosted
version: "0.9.3"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: "412705a646a0ae90f33f37acfae6a0f7cbc02222d6cd34e479421c3e74d3853c"
url: "https://pub.dev"
source: hosted
version: "2.6.0"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: "1372760c6b389842b77156203308940558a2817360154084368608413835fc26"
url: "https://pub.dev"
source: hosted
version: "0.9.3"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
...@@ -134,6 +182,38 @@ packages: ...@@ -134,6 +182,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.5"
flutter_image_compress:
dependency: "direct main"
description:
name: flutter_image_compress
sha256: "2babae2c69ee4849c3d3ae0f1f10c14a6b8132390e4583c5d3b1f02e8167a022"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
flutter_image_compress_common:
dependency: transitive
description:
name: flutter_image_compress_common
sha256: "88aae2219cd4507992643f19aee7882fe8ff82375ffa8cb4c876e3bfe3e7c3b6"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
flutter_image_compress_platform_interface:
dependency: transitive
description:
name: flutter_image_compress_platform_interface
sha256: dae0a3eb1fb7f38cf327cc2005dc287bc891becdd83c519277de4415fd9e065d
url: "https://pub.dev"
source: hosted
version: "1.0.1"
flutter_image_compress_web:
dependency: transitive
description:
name: flutter_image_compress_web
sha256: "677f02509bdf5fd71afb560a22f0444e82c9ee887d223cd006cb44fd145fcb17"
url: "https://pub.dev"
source: hosted
version: "0.1.3"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
...@@ -209,13 +289,77 @@ packages: ...@@ -209,13 +289,77 @@ packages:
source: hosted source: hosted
version: "4.0.2" version: "4.0.2"
image: image:
dependency: transitive dependency: "direct main"
description: description:
name: image name: image
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.17" version: "4.0.17"
image_picker:
dependency: "direct main"
description:
name: image_picker
sha256: b9603755b35253ccfad4be0762bb74d5e8bf9ff75edebf0ac3beec24fac1c5b5
url: "https://pub.dev"
source: hosted
version: "1.0.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: d2bab152deb2547ea6f53d82ebca9b7e77386bb706e5789e815d37e08ea475bb
url: "https://pub.dev"
source: hosted
version: "0.8.7+3"
image_picker_for_web:
dependency: "direct main"
description:
name: image_picker_for_web
sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: b3e2f21feb28b24dd73a35d7ad6e83f568337c70afab5eabac876e23803f264b
url: "https://pub.dev"
source: hosted
version: "0.8.8"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "02cbc21fe1706b97942b575966e5fbbeaac535e76deef70d3a242e4afb857831"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: cee2aa86c56780c13af2c77b5f2f72973464db204569e1ba2dd744459a065af4
url: "https://pub.dev"
source: hosted
version: "0.2.1"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "7c7b96bb9413a9c28229e717e6fd1e3edd1cc5569c1778fcca060ecf729b65ee"
url: "https://pub.dev"
source: hosted
version: "2.8.0"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: c3066601ea42113922232c7b7b3330a2d86f029f685bba99d82c30e799914952
url: "https://pub.dev"
source: hosted
version: "0.2.1"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -272,6 +416,14 @@ packages: ...@@ -272,6 +416,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
mime:
dependency: transitive
description:
name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
url: "https://pub.dev"
source: hosted
version: "1.0.4"
package_info_plus: package_info_plus:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -485,6 +637,14 @@ packages: ...@@ -485,6 +637,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.2" version: "1.3.2"
universal_html:
dependency: "direct main"
description:
name: universal_html
sha256: a5cc5a84188e5d3e58f3ed77fe3dd4575dc1f68aa7c89e51b5b4105b9aab3b9d
url: "https://pub.dev"
source: hosted
version: "2.2.3"
universal_io: universal_io:
dependency: transitive dependency: transitive
description: description:
......
...@@ -34,13 +34,18 @@ dependencies: ...@@ -34,13 +34,18 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_easyloading: ^3.0.5 flutter_easyloading: ^3.0.5
flutter_image_compress: ^2.0.3
flutter_native_splash: ^2.3.1 flutter_native_splash: ^2.3.1
go_router: ^7.1.1 go_router: ^7.1.1
http: ^1.0.0 http: ^1.0.0
image: ^4.0.17
image_picker: ^1.0.0
image_picker_for_web: ^2.2.0
intl: ^0.18.1 intl: ^0.18.1
package_info_plus: ^4.0.2 package_info_plus: ^4.0.2
shared_preferences: ^2.1.1 shared_preferences: ^2.1.1
shimmer: ^3.0.0 shimmer: ^3.0.0
universal_html: ^2.2.3
url_strategy: ^0.2.0 url_strategy: ^0.2.0
dev_dependencies: dev_dependencies:
......
function compressImage(imageBytes, quality) {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const image = new Image();
return new Promise((resolve, reject) => {
image.onload = () => {
const width = image.width;
const height = image.height;
canvas.width = width;
canvas.height = height;
context.clearRect(0, 0, width, height);
context.drawImage(image, 0, 0, width, height);
canvas.toBlob(
(blob) => {
const reader = new FileReader();
reader.onloadend = () => {
const compressedBytes = new Uint8List.fromList(reader.result);
resolve(compressedBytes);
};
reader.onerror = reject;
reader.readAsArrayBuffer(blob);
},
"image/jpeg",
quality / 100
);
};
image.onerror = reject;
image.src = URL.createObjectURL(
new Blob([imageBytes], { type: "image/jpeg" })
);
});
}
...@@ -173,6 +173,55 @@ ...@@ -173,6 +173,55 @@
return appRunner.runApp(); return appRunner.runApp();
}); });
}); });
function compressImage(imageBytes, quality) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function () {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// Set ukuran canvas sesuai ukuran gambar asli
canvas.width = img.width;
canvas.height = img.height;
// Gambar gambar asli ke canvas
ctx.drawImage(img, 0, 0);
// Dapatkan data URL dari canvas dengan kualitas yang ditentukan
const compressedDataUrl = canvas.toDataURL(
"image/jpeg",
quality / 100
);
// Konversi data URL menjadi Blob
const byteCharacters = atob(compressedDataUrl.split(",")[1]);
const byteArrays = [];
for (let i = 0; i < byteCharacters.length; i++) {
byteArrays.push(byteCharacters.charCodeAt(i));
}
const blob = new Blob([new Uint8Array(byteArrays)], {
type: "image/jpeg",
});
// Baca blob sebagai Uint8Array
const reader = new FileReader();
reader.onloadend = function () {
const compressedBytes = new Uint8Array(reader.result);
window.state = {
imagByte: compressedBytes,
};
resolve(compressedBytes);
};
reader.onerror = reject;
reader.readAsArrayBuffer(blob);
};
img.onerror = reject;
img.src = URL.createObjectURL(
new Blob([imageBytes], { type: "image/jpeg" })
);
});
}
</script> </script>
</body> </body>
</html> </html>
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <file_selector_windows/file_selector_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment