first commit

This commit is contained in:
2026-01-20 16:34:54 +07:00
commit 2ac772b6de
4186 changed files with 123824 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:photobooth_mobile_app/core/camera/camera_service.dart';
import 'package:photobooth_mobile_app/modules/camera/outside_dim_mask.dart';
import 'package:photobooth_mobile_app/modules/preview/preview_screen.dart';
class CameraCaptureScreen extends StatefulWidget {
final String frameAsset;
const CameraCaptureScreen({super.key, required this.frameAsset});
@override
State<CameraCaptureScreen> createState() => _CameraCaptureScreenState();
}
class _CameraCaptureScreenState extends State<CameraCaptureScreen> {
final CameraService _cameraService = CameraService();
bool _ready = false;
@override
void initState() {
super.initState();
_init();
}
Future<void> _init() async {
await _cameraService.init();
setState(() => _ready = true);
}
@override
void dispose() {
_cameraService.dispose();
super.dispose();
}
Future<void> _takePicture() async {
final XFile raw = await _cameraService.takePicture();
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (_) => PreviewScreen(
imagePath: raw.path,
frameAsset: widget.frameAsset,
isFrontCamera: _cameraService.isFront,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: !_ready
? const Center(child: CupertinoActivityIndicator())
: Column(
children: [
Stack(
children: [
CameraPreview(_cameraService.controller!),
const Positioned.fill(child: OutsideDimMask(opacity: 1)),
Positioned.fill(
child: IgnorePointer(
child: AspectRatio(
aspectRatio: 148 / 210,
child: Image.asset(
widget.frameAsset,
fit: BoxFit.contain,
),
),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
icon: Icon(
Icons.cameraswitch,
color: Colors.white,
size: 28,
),
onPressed: () async {
await _cameraService.switchCamera();
setState(() {});
},
),
GestureDetector(
onTap: _takePicture,
child: Container(
width: 72,
height: 72,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 4),
),
),
),
IconButton(
onPressed: () => Navigator.pop(context),
icon: Icon(Icons.close, color: Colors.white, size: 28),
),
],
),
],
),
),
);
}
}

View File

@@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
class OutsideDimMask extends StatelessWidget {
final double opacity;
const OutsideDimMask({super.key, this.opacity = 0.6});
@override
Widget build(BuildContext context) {
const a5Ratio = 148 / 210;
return LayoutBuilder(
builder: (context, constraints) {
final width = constraints.maxWidth;
final height = constraints.maxHeight;
double frameWidth;
double frameHeight;
if (width / height > a5Ratio) {
frameHeight = height;
frameWidth = height * a5Ratio;
} else {
frameWidth = width;
frameHeight = width / a5Ratio;
}
final left = (width - frameWidth) / 2;
final top = (height - frameHeight) / 2;
return Stack(
children: [
// Top
Positioned(
left: 0,
right: 0,
top: 0,
height: top,
child: Container(color: Colors.black.withOpacity(opacity)),
),
// Bottom
Positioned(
left: 0,
right: 0,
bottom: 0,
height: top,
child: Container(color: Colors.black.withOpacity(opacity)),
),
// Left
Positioned(
left: 0,
top: top,
width: left,
height: frameHeight,
child: Container(color: Colors.black.withOpacity(opacity)),
),
// Right
Positioned(
right: 0,
top: top,
width: left,
height: frameHeight,
child: Container(color: Colors.black.withOpacity(opacity)),
),
],
);
},
);
}
}