Files
Remever/lib/screens/crud_collection/widgets/crud_collection_fullscreen_field.dart

310 lines
9.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:auto_route/auto_route.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_keyboard_size/flutter_keyboard_size.dart';
import 'package:remever/common/functions.dart';
import 'package:remever/common/resources.dart';
import 'package:remever/common/widgets/typography.dart';
import 'package:remever/common/widgets/wspace.dart';
import 'package:remever/components/extensions/context.dart';
import 'package:remever/gen/assets.gen.dart';
import 'package:remever/screens/dialogs/alert_dialog.dart';
@RoutePage()
class CrudCollectionFullscreenField extends StatefulWidget {
const CrudCollectionFullscreenField({
super.key,
this.title = '',
this.hint,
this.content,
this.height = 92,
required this.onEditingComplete,
});
final String title;
final double height;
final String? hint;
final String? content;
final void Function(String?) onEditingComplete;
@override
State<CrudCollectionFullscreenField> createState() =>
_CrudCollectionFullscreenFieldState();
}
class _CrudCollectionFullscreenFieldState
extends State<CrudCollectionFullscreenField> {
final TextEditingController _controller = TextEditingController();
@override
void initState() {
if (widget.content != null) {
_controller.text = widget.content!;
}
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return KeyboardSizeProvider(
child: SafeArea(
top: false,
child: Scaffold(
backgroundColor: AppColors.gray_bg,
appBar: _buildAppBar(context),
body: _buildMainBody(context),
),
),
);
}
/// Построение основного тела экрана
Widget _buildMainBody(BuildContext context) {
return Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16).r,
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const HSpace(16),
_buildField(context),
if (widget.hint != null) ...[
const HSpace(16),
AppTypography(
widget.hint!,
type: Regular14px(),
color: AppColors.disabled,
),
],
const HSpace(50),
],
),
),
),
Align(alignment: Alignment.bottomCenter, child: _buildMenu()),
],
);
}
/// Построение интерактивной плашки меню
Widget _buildMenu() {
return Consumer<ScreenHeight>(
builder: (context, screenHeight, _) {
return AnimatedOpacity(
// opacity: screenHeight.isOpen ? 1 : 0,
opacity: 1,
duration: const Duration(milliseconds: 500),
child: Container(
height: 64.h,
decoration: BoxDecoration(
color: AppColors.white,
border: Border(
top: BorderSide(color: AppColors.gray, width: 1.w),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildPasteButton(),
_buildCopyButton(),
_buildSubmitButton(),
],
),
),
);
},
);
}
/// Кнопка "Вставить из буфера обмена"
Widget _buildPasteButton() {
return GestureDetector(
onTap: _onPasteTap,
child: Assets.icons.typePaste.image(height: 24.h, width: 24.w),
);
}
/// Обработка нажатия на кнопку "Вставить"
void _onPasteTap() async {
try {
final ClipboardData? data = await Clipboard.getData('text/plain');
if (data?.text == null || data!.text!.isEmpty) {
showErrorToast('Не удалось получить текст из буфера обмена');
return;
}
_controller.text += ' ${data.text}';
showSuccessToast('Текст вставлен из буфера обмена');
} catch (e) {
showErrorToast('Ошибка при вставке текста: $e');
}
}
/// Кнопка "Скопировать в буфер обмена"
Widget _buildCopyButton() {
return GestureDetector(
onTap: _onCopyTap,
child: Assets.icons.typeCopy.image(height: 24.h, width: 24.w),
);
}
/// Обработка нажатия на кнопку "Копировать"
void _onCopyTap() async {
if (_controller.text.isEmpty) {
showErrorToast('Нет содержимого для отправки в буфер обмена');
return;
}
try {
await Clipboard.setData(ClipboardData(text: _controller.text));
showSuccessToast('Текст скопирован в буфер обмена');
} catch (e) {
showErrorToast('Ошибка при копировании текста: $e');
}
}
/// Кнопка "Подтвердить"
Widget _buildSubmitButton() {
return GestureDetector(
onTap: _onSubmitTap,
child: SizedBox.square(
dimension: 32.r,
child: DecoratedBox(
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: AppColors.primary,
),
child: Center(
child: Assets.icons.typeCheck.image(
height: 24.h,
width: 24.w,
color: AppColors.white,
),
),
),
),
);
}
/// Обработка нажатия на кнопку "Подтвердить"
void _onSubmitTap() {
if (_controller.text.isEmpty) {
showErrorToast(
'Для создания публичной коллекции добавьте описание и тэги',
);
return;
}
widget.onEditingComplete(_controller.text);
context.back();
}
/// Построение поля ввода
Widget _buildField(BuildContext context) {
return SizedBox(
height: widget.height.h,
child: DecoratedBox(
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(12).r,
),
child: Padding(
padding: const EdgeInsets.all(12).r,
child: TextField(
autofocus: true,
controller: _controller,
textCapitalization: TextCapitalization.sentences,
maxLines: 99,
maxLength: 250,
cursorColor: AppColors.danger,
decoration: const InputDecoration.collapsed(
hintText: 'Введите содержимое',
hintStyle: TextStyle(color: AppColors.gray),
),
),
),
),
);
}
/// Построение шапки
AppBar _buildAppBar(BuildContext context) {
return AppBar(
toolbarHeight: 56.h,
backgroundColor: AppColors.white,
shadowColor: Colors.transparent,
leading: IconButton(
onPressed: () => _handleBackPress(context),
icon: const Icon(CupertinoIcons.left_chevron, color: Colors.black),
),
centerTitle: true,
title: GestureDetector(
// onLongPress: () => _showExitDialog(context),
child: AppTypography(
widget.title,
type: SemiBold20px(),
color: AppColors.body_text,
),
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 16).r,
child: GestureDetector(
onTap: () => _showResetDialog(context),
child: Assets.icons.typeTrash.image(
height: 24.h,
width: 24.w,
color: AppColors.danger,
),
),
),
],
);
}
/// Обработка нажатия на кнопку "Назад"
void _handleBackPress(BuildContext context) async {
// final bool? shouldExit = await _showExitDialog(context);
// if (shouldExit ?? false) {
context.back();
// }
}
/// Показать диалог выхода
Future<bool?> _showExitDialog(BuildContext context) async {
return showCuperModalBottomSheet(
context: context,
height: 262.h,
builder:
(context) => const AlertInfoDialog(
title: 'Вы хотите выйти из режима создания описания коллекции?',
acceptTitle: 'Выйти, не сохранять',
declineTitle: 'Сохранить и выйти',
),
);
}
/// Показать диалог сброса
void _showResetDialog(BuildContext context) {
// showCuperModalBottomSheet(
// context: context,
// height: 262.h,
// builder:
// (context) => const AlertInfoDialog(
// title: 'Вы хотите сбросить все внесенные изменения?',
// acceptTitle: 'Да, сбросить',
// declineTitle: 'Нет, оставить',
// ),
// );
}
}