feat: change ui

This commit is contained in:
Greek-Cp 2025-03-23 00:50:37 +07:00
parent 357bdfe60d
commit 77fc37ee52
19 changed files with 3279 additions and 479 deletions

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

44
ios/Podfile Normal file
View File

@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:harvest_guard_app/routes/app_routes.dart';
import 'dart:math' as math;
class SplashScreen extends StatefulWidget {
const SplashScreen({super.key});
@ -9,81 +10,193 @@ class SplashScreen extends StatefulWidget {
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
class _SplashScreenState extends State<SplashScreen>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _rotationAnimation;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
// Tunggu selama 3 detik kemudian navigasi ke Dashboard dengan AppRoutes
// Animation controller
_controller = AnimationController(
duration: const Duration(seconds: 3),
vsync: this,
);
// Rotation animation
_rotationAnimation = Tween<double>(
begin: 0,
end: 2 * math.pi,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
// Scale animation
_scaleAnimation = Tween<double>(
begin: 0.8,
end: 1.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.elasticOut,
));
// Start animation
_controller.forward();
// Navigate to intro screen after 3 seconds
Future.delayed(const Duration(seconds: 3), () {
Get.offNamed(
AppRoutes.dashboard); // Menggunakan konstanta route dari AppRoutes
Get.offNamed(AppRoutes.intro); // Change to intro route
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
children: [
// Spacer untuk menjaga tampilan di tengah
const Spacer(flex: 2),
// Logo tanaman menggunakan Image.asset
Center(
body: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Colors.green.shade100,
Colors.green.shade300,
Colors.green.shade500,
],
stops: [0.0, 0.5 + _controller.value * 0.2, 1.0],
),
),
child: SafeArea(
child: Column(
children: [
Image.asset(
'assets/images/plant.png',
height: 60,
width: 60,
const Spacer(flex: 2),
// Logo dengan animasi
Center(
child: Column(
children: [
ScaleTransition(
scale: _scaleAnimation,
child: RotationTransition(
turns: _rotationAnimation,
child: Container(
height: 80,
width: 80,
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
spreadRadius: 2,
),
],
),
child: const Icon(
Icons.eco_rounded,
size: 50,
color: Colors.green,
),
),
),
),
const SizedBox(height: 25),
// Teks Harvest - Guard dengan animasi
AnimatedOpacity(
opacity: _controller.value,
duration: const Duration(milliseconds: 800),
child: const Text(
'Harvest - Guard',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 1.2,
shadows: [
Shadow(
color: Colors.black26,
offset: Offset(1, 1),
blurRadius: 3,
),
],
),
),
),
const SizedBox(height: 10),
// Sub text
FadeTransition(
opacity: _controller,
child: const Text(
'Proteksi Tanaman Padi Anda',
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
const SizedBox(height: 20),
const Spacer(flex: 3),
// Teks Harvest - Guard
const Text(
'Harvest - Guard',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black,
// Teks "Developed by" dengan animasi
FadeTransition(
opacity: _controller,
child: const Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Text(
'Developed by',
style: TextStyle(
fontSize: 14,
color: Colors.white70,
),
),
),
),
// Nama developer dengan animasi
FadeTransition(
opacity: _controller,
child: const Padding(
padding: EdgeInsets.only(bottom: 32.0),
child: Text(
'Bahrudin Ayub',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 0.5,
),
),
),
),
],
),
),
// Spacer untuk mendorong "Developed by" ke bagian bawah
const Spacer(flex: 3),
// Teks "Developed by"
const Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Text(
'Developed by',
style: TextStyle(
fontSize: 14,
color: Colors.black,
),
),
),
// Nama developer
const Padding(
padding: EdgeInsets.only(bottom: 32.0),
child: Text(
'Bahrudin Ayub',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
],
),
);
},
),
);
}

View File

@ -1,34 +1,109 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:harvest_guard_app/periksa/model_controller.dart';
import 'package:harvest_guard_app/routes/app_routes.dart';
class DashboardController extends GetxController {
class DashboardController extends GetxController
with GetSingleTickerProviderStateMixin {
// User name state
var userName = "Petani".obs;
// Reference to ModelController for scan history
late final ModelController modelController;
// Animation controller
late AnimationController animationController;
// Animation status
var animationCompleted = false.obs;
@override
void onInit() {
super.onInit();
// Get ModelController instance
if (!Get.isRegistered<ModelController>()) {
Get.put(ModelController());
}
modelController = Get.find<ModelController>();
// Initialize animation controller - hanya jalankan sekali
animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 2000), // Durasi total animasi
);
// Tambahkan listener untuk memastikan nilai dalam batas
animationController.addListener(() {
// Pastikan nilai animasi selalu dalam rentang 0.0 - 1.0
if (animationController.value < 0.0 || animationController.value > 1.0) {
animationController.value = animationController.value.clamp(0.0, 1.0);
}
});
// Mulai animasi sekali ketika halaman dimuat
// Pastikan animasi hanya jalan sekali dan tidak repeat
animationController.forward().then((_) {
animationCompleted.value = true;
});
}
@override
void onClose() {
animationController.dispose();
super.onClose();
}
// Fungsi untuk memulai pemindaian dan navigasi ke PeriksaScreen
void startScanning() {
// Navigasi ke PeriksaScreen menggunakan AppRoutes
Get.toNamed(AppRoutes.periksa);
// Haptic feedback
HapticFeedback.mediumImpact();
// Animasi transisi custom
Get.toNamed(
AppRoutes.periksa,
);
}
// Navigate to scan history detail screen
void navigateToScanHistoryDetail() {
Get.toNamed(AppRoutes.scanHistory);
// Haptic feedback
HapticFeedback.lightImpact();
Get.toNamed(
AppRoutes.scanHistory,
);
}
}
// Open history item detail
void openHistoryDetail(dynamic historyItem) {
// Haptic feedback
HapticFeedback.lightImpact();
// Implement detail view navigation
Get.toNamed(
'${AppRoutes.scanHistory}/${historyItem.id}',
arguments: historyItem,
);
}
// Switch user profile
void switchUserProfile() {
// Haptic feedback
HapticFeedback.lightImpact();
// Placeholder untuk fitur profil multiple
final profiles = ["Petani", "Ahmad", "Budi", "Citra"];
final currentIndex = profiles.indexOf(userName.value);
final nextIndex = (currentIndex + 1) % profiles.length;
userName.value = profiles[nextIndex];
}
// Reset animasi ketika halaman muncul kembali
void resetAnimation() {
animationController.reset();
animationController.forward();
}
}

File diff suppressed because it is too large Load Diff

282
lib/intro/page_intro.dart Normal file
View File

@ -0,0 +1,282 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:harvest_guard_app/routes/app_routes.dart';
class IntroScreen extends StatefulWidget {
const IntroScreen({super.key});
@override
State<IntroScreen> createState() => _IntroScreenState();
}
class _IntroScreenState extends State<IntroScreen> {
final PageController _pageController = PageController();
int _currentPage = 0;
final List<IntroPage> _introPages = [
IntroPage(
title: 'Pilih Varietas Padi',
description:
'Pilih jenis padi yang ingin Anda periksa dari daftar varietas yang tersedia',
icon: Icons.grass_rounded,
color: Colors.green.shade400,
),
IntroPage(
title: 'Scan Tanaman Padi',
description:
'Arahkan kamera ponsel Anda ke bagian tanaman padi yang ingin diperiksa',
icon: Icons.document_scanner_rounded,
color: Colors.blue.shade400,
),
IntroPage(
title: 'Cek Hasil Diagnosis',
description:
'Dapatkan hasil diagnosis penyakit dan rekomendasi penanganannya',
icon: Icons.checklist_rounded,
color: Colors.orange.shade400,
),
];
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// Background animasi bergerak
AnimatedPositioned(
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
top: -100 + (_currentPage * 50),
right: -100 + (_currentPage * 40),
child: Container(
height: 300,
width: 300,
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [
_introPages[_currentPage].color.withOpacity(0.7),
_introPages[_currentPage].color.withOpacity(0.0),
],
stops: const [0.1, 1.0],
),
shape: BoxShape.circle,
),
),
),
AnimatedPositioned(
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
bottom: -80 + (_currentPage * 30),
left: -50 + (_currentPage * 20),
child: Container(
height: 250,
width: 250,
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [
_introPages[_currentPage].color.withOpacity(0.5),
_introPages[_currentPage].color.withOpacity(0.0),
],
stops: const [0.1, 1.0],
),
shape: BoxShape.circle,
),
),
),
// Content
Column(
children: [
Expanded(
child: PageView.builder(
controller: _pageController,
itemCount: _introPages.length,
onPageChanged: (int page) {
setState(() {
_currentPage = page;
});
},
itemBuilder: (context, index) {
return _buildIntroPage(_introPages[index]);
},
),
),
// Pagination indicator
Container(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
_introPages.length,
(index) => _buildDotIndicator(index),
),
),
),
// Bottom buttons
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Next/Finish button
ElevatedButton(
onPressed: () {
if (_currentPage < _introPages.length - 1) {
_pageController.nextPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
} else {
Get.offNamed(AppRoutes.dashboard);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: _introPages[_currentPage].color,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
child: Text(
_currentPage < _introPages.length - 1
? 'Lanjut'
: 'Mulai',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
],
),
],
),
);
}
Widget _buildIntroPage(IntroPage page) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Icon with animated container
TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 600),
builder: (context, value, child) {
return Transform.scale(
scale: value,
child: Container(
padding: const EdgeInsets.all(25),
decoration: BoxDecoration(
color: page.color.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Icon(
page.icon,
size: 80,
color: page.color,
),
),
);
},
),
const SizedBox(height: 40),
// Title
TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 800),
builder: (context, value, child) {
return Opacity(
opacity: value,
child: Transform.translate(
offset: Offset(0, 20 * (1 - value)),
child: Text(
page.title,
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
textAlign: TextAlign.center,
),
),
);
},
),
const SizedBox(height: 20),
// Description
TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 1000),
builder: (context, value, child) {
return Opacity(
opacity: value,
child: Transform.translate(
offset: Offset(0, 30 * (1 - value)),
child: Text(
page.description,
style: const TextStyle(
fontSize: 16,
color: Colors.black54,
height: 1.5,
),
textAlign: TextAlign.center,
),
),
);
},
),
],
),
);
}
Widget _buildDotIndicator(int index) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.symmetric(horizontal: 5),
height: 8,
width: _currentPage == index ? 24 : 8,
decoration: BoxDecoration(
color: _currentPage == index
? _introPages[_currentPage].color
: Colors.grey.shade300,
borderRadius: BorderRadius.circular(4),
),
);
}
}
class IntroPage {
final String title;
final String description;
final IconData icon;
final Color color;
IntroPage({
required this.title,
required this.description,
required this.icon,
required this.color,
});
}

View File

@ -8,17 +8,14 @@ import 'package:hive_flutter/adapters.dart';
Future<void> main() async {
runApp(const MainApp());
WidgetsFlutterBinding.ensureInitialized();
// Initialize Hive
await Hive.initFlutter();
// Register adapters
Hive.registerAdapter(ScanHistoryAdapter());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});

View File

@ -1,129 +1,756 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:harvest_guard_app/periksa/periksa_controller.dart';
import 'dart:math' as math;
class PeriksaScreen extends StatelessWidget {
class PeriksaScreen extends StatefulWidget {
const PeriksaScreen({super.key});
@override
State<PeriksaScreen> createState() => _PeriksaScreenState();
}
class _PeriksaScreenState extends State<PeriksaScreen>
with SingleTickerProviderStateMixin {
late final PeriksaController controller;
late AnimationController _animationController;
late Animation<double> _fadeInAnimation;
late Animation<double> _slideAnimation;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
// Inisialisasi controller
controller = Get.put(PeriksaController());
// Setup animasi
_animationController = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
_fadeInAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.6, curve: Curves.easeOut),
),
);
_slideAnimation = Tween<double>(begin: 50.0, end: 0.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.6, curve: Curves.easeOut),
),
);
_scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.2, 0.8, curve: Curves.elasticOut),
),
);
// Mulai animasi
_animationController.forward();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final PeriksaController controller = Get.put(PeriksaController());
final Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('Periksa Kesehatan Padi'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Get.back(),
),
body: Stack(
children: [
// Background dengan efek gradient dan elemen dekoratif
_buildAnimatedBackground(),
// Konten utama
SafeArea(
child: Column(
children: [
// App Bar custom
_buildCustomAppBar(),
// Konten utama dengan scroll
Expanded(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 10),
// Judul utama dengan animasi
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Opacity(
opacity: _fadeInAnimation.value,
child: Transform.translate(
offset: Offset(0, _slideAnimation.value),
child: child,
),
);
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 12),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.green.shade400,
Colors.green.shade600,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color:
Colors.green.shade200.withOpacity(0.5),
blurRadius: 15,
offset: const Offset(0, 5),
),
],
),
child: const Text(
'Periksa Kesehatan Padimu',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.white,
letterSpacing: 0.5,
),
),
),
),
const SizedBox(height: 40),
// Ilustrasi
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Transform.scale(
scale: _scaleAnimation.value,
child: child,
);
},
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: Colors.green.shade50,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
spreadRadius: 2,
),
],
),
child: Center(
child: Stack(
alignment: Alignment.center,
children: [
Icon(
Icons.eco_rounded,
size: 120,
color: Colors.green.shade300,
),
Positioned(
top: 50,
right: 45,
child: Icon(
Icons.search,
size: 60,
color: Colors.green.shade700
.withOpacity(0.8),
),
),
],
),
),
),
),
const SizedBox(height: 40),
// Subtitle
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
final delayedOpacity =
_animationController.value > 0.3
? (((_animationController.value - 0.3) /
0.7) *
1.0)
.clamp(0.0, 1.0)
: 0.0;
return Opacity(
opacity: delayedOpacity,
child: Transform.translate(
offset: Offset(0, 20 * (1 - delayedOpacity)),
child: child,
),
);
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.06),
blurRadius: 8,
offset: const Offset(0, 3),
),
],
),
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.info_outline,
size: 20,
color: Colors.green.shade700,
),
const SizedBox(width: 8),
const Text(
'Panduan Scanning',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
],
),
const SizedBox(height: 8),
const Text(
'Pastikan foto dengan jelas di bagian daun padi untuk hasil deteksi optimal',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
color: Colors.black54,
height: 1.4,
),
),
],
),
),
),
const SizedBox(height: 40),
// Tombol Ambil Foto
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
final delayedOpacity =
_animationController.value > 0.4
? (((_animationController.value - 0.4) /
0.6) *
1.0)
.clamp(0.0, 1.0)
: 0.0;
return Opacity(
opacity: delayedOpacity,
child: Transform.translate(
offset: Offset(0, 30 * (1 - delayedOpacity)),
child: child,
),
);
},
child: GestureDetector(
onTap: () => controller.takePhoto(),
child: Container(
width: 150,
height: 150,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.green.shade500,
Colors.green.shade700,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.green.shade300
.withOpacity(0.5),
blurRadius: 15,
spreadRadius: 5,
offset: const Offset(0, 8),
),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
shape: BoxShape.circle,
),
child: const Icon(
Icons.camera_alt_rounded,
color: Colors.white,
size: 40,
),
),
const SizedBox(height: 8),
const Text(
'Ambil Foto',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
letterSpacing: 0.5,
),
),
],
),
),
),
),
const SizedBox(height: 30),
// Divider dengan "atau"
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
final delayedOpacity =
_animationController.value > 0.5
? (((_animationController.value - 0.5) /
0.5) *
1.0)
.clamp(0.0, 1.0)
: 0.0;
return Opacity(
opacity: delayedOpacity,
child: child,
);
},
child: Row(
children: [
Expanded(
child: Container(
height: 1,
color: Colors.grey.shade300,
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.green.shade50,
borderRadius: BorderRadius.circular(20),
),
child: const Text(
'atau',
style: TextStyle(
fontSize: 14,
color: Colors.green,
fontWeight: FontWeight.w500,
),
),
),
),
Expanded(
child: Container(
height: 1,
color: Colors.grey.shade300,
),
),
],
),
),
const SizedBox(height: 30),
// Tombol Pilih dari Galeri
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
final delayedOpacity =
_animationController.value > 0.6
? (((_animationController.value - 0.6) /
0.4) *
1.0)
.clamp(0.0, 1.0)
: 0.0;
return Opacity(
opacity: delayedOpacity,
child: Transform.translate(
offset: Offset(0, 20 * (1 - delayedOpacity)),
child: child,
),
);
},
child: GestureDetector(
onTap: () => controller.pickFromGallery(),
child: Container(
width: double.infinity,
height: 70,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
spreadRadius: 1,
offset: const Offset(0, 4),
),
],
border: Border.all(
color: Colors.green.shade200,
width: 1.5,
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20.0),
child: Row(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.green.shade50,
shape: BoxShape.circle,
),
child: Icon(
Icons.photo_library_rounded,
size: 24,
color: Colors.green.shade600,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
const Text(
'Pilih dari Galeri',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
const SizedBox(height: 4),
Text(
'Format: JPG, JPEG, PNG',
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade600,
),
),
],
),
),
Icon(
Icons.arrow_forward_ios,
size: 16,
color: Colors.grey.shade600,
),
],
),
),
),
),
),
const SizedBox(height: 40),
],
),
),
),
),
],
),
),
],
),
body: SingleChildScrollView(
);
}
// Custom App Bar dengan efek transparan
Widget _buildCustomAppBar() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: Row(
children: [
// Back button dengan efek glassmorphism
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.8),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 5,
spreadRadius: 1,
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () => Get.back(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.arrow_back_ios_new_rounded,
size: 20,
color: Colors.green.shade700,
),
),
),
),
),
const Spacer(),
// Info icon dengan efek glassmorphism
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.8),
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
blurRadius: 5,
spreadRadius: 1,
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () {
_showInfoDialog();
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.help_outline_rounded,
size: 20,
color: Colors.green.shade700,
),
),
),
),
),
],
),
);
}
// Animated Background dengan elemen dekoratif
Widget _buildAnimatedBackground() {
return Stack(
children: [
// Gradient background
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.green.shade50,
Colors.white,
Colors.white,
],
stops: const [0.0, 0.3, 1.0],
),
),
),
// Decorative top blob
Positioned(
top: -80,
right: -50,
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [
Colors.green.shade200.withOpacity(0.6),
Colors.green.shade200.withOpacity(0.0),
],
stops: const [0.2, 1.0],
),
shape: BoxShape.circle,
),
),
),
// Decorative bottom blob
Positioned(
bottom: 100,
left: -30,
child: Container(
height: 150,
width: 150,
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [
Colors.green.shade200.withOpacity(0.4),
Colors.green.shade200.withOpacity(0.0),
],
stops: const [0.2, 1.0],
),
shape: BoxShape.circle,
),
),
),
// Decorative elements
for (int i = 0; i < 5; i++)
Positioned(
top: 150 + (i * 120),
left: (i % 2 == 0) ? 20 : null,
right: (i % 2 == 0) ? null : 20,
child: AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
final delayedStart = 0.1 * i;
final localProgress =
((_animationController.value - delayedStart) /
(1 - delayedStart))
.clamp(0.0, 1.0);
return Opacity(
opacity: localProgress * 0.3,
child: Transform.translate(
offset: Offset(
0,
20 * (1 - localProgress),
),
child: Icon(
Icons.eco,
size: 20 + (i * 2),
color: Colors.green.shade300.withOpacity(0.3),
),
),
);
},
),
),
],
);
}
void _showInfoDialog() {
Get.dialog(
Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 20),
// Judul utama
const Center(
child: Text(
'Periksa Kesehatan\nPadimu Sekarang',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.green.shade100,
shape: BoxShape.circle,
),
child: Icon(
Icons.tips_and_updates_rounded,
color: Colors.green.shade700,
size: 24,
),
),
),
),
const SizedBox(height: 40),
// Subtitle
const Center(
child: Text(
'Foto di bagian daun padi',
style: TextStyle(
fontSize: 16,
color: Colors.black87,
),
),
),
const SizedBox(height: 20),
// Tombol Ambil Foto (lingkaran hijau)
GestureDetector(
onTap: () => controller.takePhoto(),
child: Container(
width: 150,
height: 150,
decoration: const BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Ikon kamera dengan border putih
Container(
padding: const EdgeInsets.all(8),
child: const Icon(
Icons.center_focus_strong_outlined,
color: Colors.white,
size: 40,
),
const SizedBox(width: 16),
const Expanded(
child: Text(
'Tips Foto yang Baik',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
const SizedBox(height: 5),
const Text(
'Ambil Foto',
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
],
),
),
),
),
const SizedBox(height: 30),
const Text(
'atau',
style: TextStyle(
fontSize: 16,
color: Colors.black54,
),
],
),
const SizedBox(height: 20),
// Tombol Pilih dari Galeri
GestureDetector(
onTap: () => controller.pickFromGallery(),
child: Container(
width: double.infinity,
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
_buildTipItem(
Icons.brightness_5_rounded,
'Foto dengan pencahayaan yang cukup',
),
const SizedBox(height: 10),
_buildTipItem(
Icons.center_focus_strong_rounded,
'Fokus pada bagian daun yang menunjukkan gejala',
),
const SizedBox(height: 10),
_buildTipItem(
Icons.crop_rounded,
'Hindari bayangan atau jari di foto',
),
const SizedBox(height: 10),
_buildTipItem(
Icons.filter_rounded,
'Jangan menggunakan filter kamera',
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => Get.back(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green.shade600,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Pilih dari Galeri\n*JPG, JPEG, PNG',
style: TextStyle(
fontSize: 16,
color: Colors.black87,
),
),
const Icon(
Icons.insert_drive_file_outlined,
size: 30,
color: Colors.black87,
),
],
),
minimumSize: const Size(double.infinity, 45),
),
child: const Text(
'Mengerti',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
@ -133,4 +760,26 @@ class PeriksaScreen extends StatelessWidget {
),
);
}
Widget _buildTipItem(IconData icon, String text) {
return Row(
children: [
Icon(
icon,
size: 18,
color: Colors.green.shade600,
),
const SizedBox(width: 12),
Expanded(
child: Text(
text,
style: TextStyle(
fontSize: 14,
color: Colors.grey.shade700,
),
),
),
],
);
}
}

View File

@ -8,6 +8,7 @@ import 'package:harvest_guard_app/components/scan_history_screen.dart';
import 'package:harvest_guard_app/components/splashscreen.dart';
import 'package:harvest_guard_app/dashboard/dashboard_binding.dart';
import 'package:harvest_guard_app/dashboard/dashboard_page.dart';
import 'package:harvest_guard_app/intro/page_intro.dart';
import 'package:harvest_guard_app/periksa/periksa_binding.dart';
import 'package:harvest_guard_app/periksa/periksa_controller.dart';
import 'package:harvest_guard_app/periksa/periksa_page.dart';
@ -18,9 +19,14 @@ class AppRoutes {
static const String dashboard = '/dashboard';
static const String periksa = '/periksa';
static const String scanHistory = '/scan-history';
static const String intro = '/intro';
// Daftar route aplikasi
static final List<GetPage> pages = [
GetPage(
name: intro,
page: () => const IntroScreen(),
),
GetPage(
name: splash,
page: () => const SplashScreen(),

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

43
macos/Podfile Normal file
View File

@ -0,0 +1,43 @@
platform :osx, '10.14'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

35
macos/Podfile.lock Normal file
View File

@ -0,0 +1,35 @@
PODS:
- file_selector_macos (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- tflite_flutter (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- tflite_flutter (from `Flutter/ephemeral/.symlinks/plugins/tflite_flutter/macos`)
EXTERNAL SOURCES:
file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
FlutterMacOS:
:path: Flutter/ephemeral
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
tflite_flutter:
:path: Flutter/ephemeral/.symlinks/plugins/tflite_flutter/macos
SPEC CHECKSUMS:
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
tflite_flutter: d1496f2e968aa5a142fb282da8f5d754fcee5613
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
COCOAPODS: 1.16.2

View File

@ -21,12 +21,14 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
20B381EA337542C3DD4070EA /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F97A4A17003EFDF1E242E694 /* Pods_RunnerTests.framework */; };
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
6B879622470369E8A2157860 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AA04D75EBF536695C72D258 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -60,11 +62,14 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1B9D8C324CD0CFDF976861A8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
1CF9B9D9A8593095E96C87F7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
2E0747B455219D8FC5CEB350 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* harvest_guard_app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "harvest_guard_app.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* harvest_guard_app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = harvest_guard_app.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@ -76,8 +81,13 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
4148578F2DB7C29BE1987901 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
7AA04D75EBF536695C72D258 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
91A000F3F01E65B9710933E2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
EFB6CD8707FA4682E67D3D53 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
F97A4A17003EFDF1E242E694 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
20B381EA337542C3DD4070EA /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -92,6 +103,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6B879622470369E8A2157860 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -125,6 +137,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
B682B58076B3E8A496768CE4 /* Pods */,
);
sourceTree = "<group>";
};
@ -172,9 +185,25 @@
path = Runner;
sourceTree = "<group>";
};
B682B58076B3E8A496768CE4 /* Pods */ = {
isa = PBXGroup;
children = (
EFB6CD8707FA4682E67D3D53 /* Pods-Runner.debug.xcconfig */,
1CF9B9D9A8593095E96C87F7 /* Pods-Runner.release.xcconfig */,
1B9D8C324CD0CFDF976861A8 /* Pods-Runner.profile.xcconfig */,
2E0747B455219D8FC5CEB350 /* Pods-RunnerTests.debug.xcconfig */,
91A000F3F01E65B9710933E2 /* Pods-RunnerTests.release.xcconfig */,
4148578F2DB7C29BE1987901 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
7AA04D75EBF536695C72D258 /* Pods_Runner.framework */,
F97A4A17003EFDF1E242E694 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -186,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
F0F4B0455EC8BDC1BB981526 /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
@ -204,11 +234,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
82D07F52A88D609488332DD1 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
569AD5714DA21E30963986D5 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -329,6 +361,67 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
569AD5714DA21E30963986D5 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
82D07F52A88D609488332DD1 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
F0F4B0455EC8BDC1BB981526 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -380,6 +473,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2E0747B455219D8FC5CEB350 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@ -394,6 +488,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 91A000F3F01E65B9710933E2 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@ -408,6 +503,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4148578F2DB7C29BE1987901 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;

View File

@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -798,10 +798,10 @@ packages:
dependency: "direct main"
description:
name: tflite_flutter
sha256: ffb8651fdb116ab0131d6dc47ff73883e0f634ad1ab12bb2852eef1bbeab4a6a
sha256: "48e6fde2ad97162bb66a16a142f4c4698add9e8cd397ce9d1cc7451b55537ac1"
url: "https://pub.dev"
source: hosted
version: "0.10.4"
version: "0.11.0"
timing:
dependency: transitive
description:

View File

@ -12,7 +12,7 @@ dependencies:
get: ^4.7.2
image_cropper: ^9.0.0
image_picker: ^1.1.2
tflite_flutter: ^0.10.0
tflite_flutter: ^0.11.0
path_provider: ^2.1.0
image: ^4.1.0
hive_flutter: ^1.1.0