apply_code_screen.dart 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import "package:flutter/material.dart";
  2. import "package:logging/logging.dart";
  3. import "package:photos/extensions/input_formatter.dart";
  4. import "package:photos/services/storage_bonus_service.dart";
  5. import "package:photos/theme/ente_theme.dart";
  6. import "package:photos/ui/components/button_widget.dart";
  7. import "package:photos/ui/components/icon_button_widget.dart";
  8. import "package:photos/ui/components/models/button_type.dart";
  9. import "package:photos/ui/components/title_bar_title_widget.dart";
  10. import "package:photos/ui/components/title_bar_widget.dart";
  11. import "package:photos/utils/dialog_util.dart";
  12. class ApplyCodeScreen extends StatefulWidget {
  13. const ApplyCodeScreen({super.key});
  14. @override
  15. State<ApplyCodeScreen> createState() => _ApplyCodeScreenState();
  16. }
  17. class _ApplyCodeScreenState extends State<ApplyCodeScreen> {
  18. late TextEditingController _textController;
  19. late FocusNode textFieldFocusNode;
  20. String code = "";
  21. @override
  22. void initState() {
  23. _textController = TextEditingController();
  24. textFieldFocusNode = FocusNode();
  25. super.initState();
  26. }
  27. @override
  28. void dispose() {
  29. _textController.dispose();
  30. textFieldFocusNode.dispose();
  31. super.dispose();
  32. }
  33. @override
  34. Widget build(BuildContext context) {
  35. final colorScheme = getEnteColorScheme(context);
  36. final textStyle = getEnteTextTheme(context);
  37. textFieldFocusNode.requestFocus();
  38. return Scaffold(
  39. body: CustomScrollView(
  40. primary: false,
  41. slivers: <Widget>[
  42. TitleBarWidget(
  43. flexibleSpaceTitle: const TitleBarTitleWidget(
  44. title: "Apply code",
  45. ),
  46. actionIcons: [
  47. IconButtonWidget(
  48. icon: Icons.close_outlined,
  49. iconButtonType: IconButtonType.secondary,
  50. onTap: () {
  51. // Go three screen back, similar to pop thrice
  52. Navigator.of(context)
  53. ..pop()
  54. ..pop()
  55. ..pop();
  56. },
  57. ),
  58. ],
  59. ),
  60. SliverList(
  61. delegate: SliverChildBuilderDelegate(
  62. (delegateBuildContext, index) {
  63. return Padding(
  64. padding: const EdgeInsets.symmetric(horizontal: 16),
  65. child: Padding(
  66. padding: const EdgeInsets.symmetric(vertical: 20),
  67. child: Column(
  68. mainAxisSize: MainAxisSize.min,
  69. children: [
  70. Column(
  71. children: [
  72. Text(
  73. "Enter the code provided by your friend to "
  74. "claim free storage for both of you",
  75. style: textStyle.small
  76. .copyWith(color: colorScheme.textMuted),
  77. ),
  78. const SizedBox(height: 24),
  79. _getInputField(),
  80. // Container with 8 border radius and red color
  81. ],
  82. ),
  83. ],
  84. ),
  85. ),
  86. );
  87. },
  88. childCount: 1,
  89. ),
  90. ),
  91. SliverFillRemaining(
  92. child: SafeArea(
  93. child: Padding(
  94. padding: const EdgeInsets.all(12.0),
  95. child: Column(
  96. mainAxisAlignment: MainAxisAlignment.end,
  97. children: [
  98. ButtonWidget(
  99. buttonType: ButtonType.neutral,
  100. buttonSize: ButtonSize.large,
  101. labelText: "Apply",
  102. isDisabled: code.trim().length < 4,
  103. onTap: () async {
  104. try {
  105. await StorageBonusService.instance
  106. .getGateway()
  107. .claimReferralCode(code.trim().toUpperCase());
  108. Navigator.of(context).pop();
  109. } catch (e) {
  110. Logger('$runtimeType')
  111. .severe("failed to apply referral", e);
  112. showErrorDialogForException(
  113. context: context,
  114. exception: e as Exception,
  115. );
  116. }
  117. },
  118. )
  119. ],
  120. ),
  121. ),
  122. ),
  123. ),
  124. ],
  125. ),
  126. );
  127. }
  128. Widget _getInputField() {
  129. return TextFormField(
  130. controller: _textController,
  131. focusNode: textFieldFocusNode,
  132. style: getEnteTextTheme(context).body,
  133. inputFormatters: [UpperCaseTextFormatter()],
  134. textCapitalization: TextCapitalization.sentences,
  135. decoration: InputDecoration(
  136. focusedBorder: OutlineInputBorder(
  137. borderRadius: const BorderRadius.all(Radius.circular(4.0)),
  138. borderSide:
  139. BorderSide(color: getEnteColorScheme(context).strokeMuted),
  140. ),
  141. fillColor: getEnteColorScheme(context).fillFaint,
  142. filled: true,
  143. hintText: 'Enter referral code',
  144. contentPadding: const EdgeInsets.symmetric(
  145. horizontal: 16,
  146. vertical: 14,
  147. ),
  148. border: UnderlineInputBorder(
  149. borderSide: BorderSide.none,
  150. borderRadius: BorderRadius.circular(8),
  151. ),
  152. ),
  153. onChanged: (value) {
  154. code = value.trim();
  155. setState(() {});
  156. },
  157. autocorrect: false,
  158. keyboardType: TextInputType.emailAddress,
  159. textInputAction: TextInputAction.next,
  160. );
  161. }
  162. }