file_caption_widget.dart 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import 'package:flutter/material.dart';
  2. import 'package:photos/core/constants.dart';
  3. import 'package:photos/models/file.dart';
  4. import 'package:photos/theme/ente_theme.dart';
  5. import 'package:photos/utils/magic_util.dart';
  6. class FileCaptionWidget extends StatefulWidget {
  7. final File file;
  8. const FileCaptionWidget({required this.file, super.key});
  9. @override
  10. State<FileCaptionWidget> createState() => _FileCaptionWidgetState();
  11. }
  12. class _FileCaptionWidgetState extends State<FileCaptionWidget> {
  13. int maxLength = 280;
  14. int currentLength = 0;
  15. final _textController = TextEditingController();
  16. final _focusNode = FocusNode();
  17. String? editedCaption;
  18. String hintText = fileCaptionDefaultHint;
  19. @override
  20. void initState() {
  21. _focusNode.addListener(() {
  22. final caption = widget.file.caption;
  23. if (_focusNode.hasFocus && caption != null) {
  24. _textController.text = caption;
  25. editedCaption = caption;
  26. }
  27. });
  28. editedCaption = widget.file.caption;
  29. if (editedCaption != null && editedCaption!.isNotEmpty) {
  30. hintText = editedCaption!;
  31. }
  32. super.initState();
  33. }
  34. @override
  35. void dispose() {
  36. if (editedCaption != null) {
  37. editFileCaption(null, widget.file, editedCaption);
  38. }
  39. _textController.dispose();
  40. _focusNode.removeListener(() {});
  41. super.dispose();
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. final colorScheme = getEnteColorScheme(context);
  46. final textTheme = getEnteTextTheme(context);
  47. return TextField(
  48. onSubmitted: (value) async {
  49. if (editedCaption != null) {
  50. final isSuccesful =
  51. await editFileCaption(context, widget.file, editedCaption);
  52. if (isSuccesful) {
  53. if (mounted) {
  54. Navigator.pop(context);
  55. }
  56. }
  57. }
  58. },
  59. controller: _textController,
  60. focusNode: _focusNode,
  61. decoration: InputDecoration(
  62. counterStyle: textTheme.mini.copyWith(color: colorScheme.textMuted),
  63. counterText: currentLength > 99
  64. ? currentLength.toString() + " / " + maxLength.toString()
  65. : "",
  66. contentPadding: const EdgeInsets.all(16),
  67. border: OutlineInputBorder(
  68. borderRadius: BorderRadius.circular(2),
  69. borderSide: const BorderSide(
  70. width: 0,
  71. style: BorderStyle.none,
  72. ),
  73. ),
  74. focusedBorder: OutlineInputBorder(
  75. borderRadius: BorderRadius.circular(2),
  76. borderSide: const BorderSide(
  77. width: 0,
  78. style: BorderStyle.none,
  79. ),
  80. ),
  81. filled: true,
  82. fillColor: colorScheme.fillFaint,
  83. hintText: hintText,
  84. hintStyle: hintText == fileCaptionDefaultHint
  85. ? textTheme.small.copyWith(color: colorScheme.textMuted)
  86. : textTheme.small,
  87. ),
  88. style: textTheme.small,
  89. cursorWidth: 1.5,
  90. maxLength: maxLength,
  91. minLines: 1,
  92. maxLines: 6,
  93. textCapitalization: TextCapitalization.sentences,
  94. keyboardType: TextInputType.text,
  95. onChanged: (value) {
  96. setState(() {
  97. hintText = fileCaptionDefaultHint;
  98. currentLength = value.length;
  99. editedCaption = value;
  100. });
  101. },
  102. );
  103. }
  104. }