2025-03-11 21:17:14 +08:00

221 lines
6.5 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:image_picker/image_picker.dart';
import 'package:lamiter/Class/Question/question.dart';
import 'package:lamiter/Class/Question/question_layout_attributes.dart';
import 'package:lamiter/Extension/build_context.dart';
import 'package:lamiter/Component/q_title.dart';
import 'package:lamiter/Extension/iterable.dart';
import 'package:lamiter/Provider/Form/form_provider.dart';
import 'package:lamiter/Provider/Language/language_provider.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
// ignore: must_be_immutable
class IQ<T extends FormProvider> extends Question<String> {
final GlobalKey<IQLayoutState> IQKey = GlobalKey<IQLayoutState>();
final IQLayoutAttributes attributes;
IQ({
super.key,
required super.id,
required super.required,
super.answer,
required this.attributes,
});
@override
void setAnswerLayout(String? _answer) {
answer = _answer;
IQKey.currentState?.setAnswer(_answer);
}
@override
void lockAnswerLayouot() {
IQKey.currentState?.lockAnswer();
}
@override
Widget build(BuildContext context) {
void layoutSetAnswer(String? layoutAnswer) {
answer = layoutAnswer;
context.read<T>().refresh();
}
return _Layout(
key: IQKey,
attributes: attributes,
setAnswer: layoutSetAnswer,
);
}
}
enum IQLayoutShape { circle, rectangle }
class IQLayoutAttributes extends QuestionLayoutAttributes {
final num sizeWidthFactor;
final IQLayoutShape shape;
IQLayoutAttributes({
super.title,
required super.required,
required this.sizeWidthFactor,
this.shape = IQLayoutShape.circle,
});
}
class _Layout extends StatefulWidget {
// Short description question
final IQLayoutAttributes attributes;
final Function(String?) setAnswer;
const _Layout({
super.key,
required this.attributes,
required this.setAnswer,
});
@override
State<_Layout> createState() => IQLayoutState();
}
class IQLayoutState extends State<_Layout> {
bool _readOnly = false;
String? _answer;
void setAnswer(String? img64) {
_answer = img64;
setState(() {});
}
void lockAnswer() {
_readOnly = true;
setState(() {});
}
Future<void> imageHandler(ImageSource source) async {
final returnedImage = await ImagePicker().pickImage(source: source);
if (returnedImage == null) return;
final bytes = await File(returnedImage.path).readAsBytes();
_answer = base64Encode(bytes);
widget.setAnswer(_answer);
setState(() {});
//File(returnedImage.path)
}
Container noImageContainer(double size, IQLayoutShape shape) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(
color: context.secondary.withOpacity(0.15),
shape: shape == IQLayoutShape.circle
? BoxShape.circle
: BoxShape.rectangle,
border: Border.all(color: context.tertiary),
borderRadius:
shape == IQLayoutShape.circle ? null : BorderRadius.circular(5.sp),
),
child: Icon(
Icons.camera_alt_rounded,
size: size / 4.5,
color: context.primary,
),
);
}
Container hasImageContainer(String img64, double size, IQLayoutShape shape) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(base64Decode(img64), scale: 1), //todo
fit: BoxFit.cover,
),
shape: shape == IQLayoutShape.circle
? BoxShape.circle
: BoxShape.rectangle,
border: Border.all(color: context.tertiary),
borderRadius:
shape == IQLayoutShape.circle ? null : BorderRadius.circular(5.sp),
),
);
}
@override
Widget build(BuildContext context) {
final languageProvider = Provider.of<LanguageProvider>(context);
return Form(
child: Column(
children: [
widget.attributes.title != null && widget.attributes.title!.isNotEmpty
? QTitle(
title: languageProvider
.getLocaleString(widget.attributes.title!),
readOnly: _readOnly,
required: widget.attributes.required,
)
: const SizedBox.shrink(),
GestureDetector(
onTap: () {
if (_readOnly) return;
showCupertinoModalPopup(
context: context,
builder: (BuildContext context) => CupertinoActionSheet(
actions: [
CupertinoActionSheetAction(
child: Text(AppLocalizations.of(context).use_camera),
onPressed: () {
Navigator.pop(context);
imageHandler(ImageSource.camera);
},
),
CupertinoActionSheetAction(
child: Text(AppLocalizations.of(context).browse_gallery),
onPressed: () {
Navigator.pop(context);
imageHandler(ImageSource.gallery);
},
),
],
cancelButton: CupertinoActionSheetAction(
isDefaultAction: true,
child: const Text('取消'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
},
// todo
// onScaleStart: (details) {
// print(details);
// },
// onScaleUpdate: (details) {
// print(details);
// },
child: AspectRatio(
aspectRatio: 1,
child: _answer == null
? noImageContainer(
context
.width(widget.attributes.sizeWidthFactor.toDouble()),
widget.attributes.shape)
: hasImageContainer(
_answer!,
context
.width(widget.attributes.sizeWidthFactor.toDouble()),
widget.attributes.shape),
),
),
].separator(SizedBox(height: 3.sp)).toList(),
),
);
}
}