view.dart 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. import 'dart:io';
  2. import 'package:electronic_assistant/base/base_page.dart';
  3. import 'package:electronic_assistant/module/record/constants.dart';
  4. import 'package:electronic_assistant/module/record/controller.dart';
  5. import 'package:electronic_assistant/resource/colors.gen.dart';
  6. import 'package:electronic_assistant/utils/expand.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:flutter/services.dart';
  9. import 'package:flutter_screenutil/flutter_screenutil.dart';
  10. import 'package:get/get.dart';
  11. import 'package:lottie/lottie.dart';
  12. import '../../resource/assets.gen.dart';
  13. class RecordPage extends BasePage<RecordController> {
  14. const RecordPage({super.key});
  15. @override
  16. bool immersive() {
  17. return true;
  18. }
  19. @override
  20. bool statusBarDarkFont() {
  21. return false;
  22. }
  23. @override
  24. Color backgroundColor() {
  25. return ColorName.recordBackgroundColor;
  26. }
  27. @override
  28. Color navigationBarColor() {
  29. return "#4A4F67".color;
  30. }
  31. @override
  32. Widget buildBody(BuildContext context) {
  33. return Stack(alignment: Alignment.bottomCenter, children: [
  34. _buildBottomGradient(),
  35. Scaffold(
  36. appBar: AppBar(
  37. leading: IconButton(
  38. icon: const Icon(Icons.arrow_back_ios_new_rounded),
  39. color: ColorName.white,
  40. onPressed: () {
  41. controller.onBackClick();
  42. },
  43. ),
  44. scrolledUnderElevation: 0,
  45. backgroundColor: ColorName.transparent,
  46. systemOverlayStyle: SystemUiOverlayStyle.light,
  47. actions: [
  48. _buildAddShortcut(true),
  49. ],
  50. ),
  51. backgroundColor: ColorName.transparent,
  52. body: Flex(
  53. direction: Axis.vertical,
  54. children: [
  55. _buildRecordStatus(),
  56. const Spacer(flex: 271),
  57. _buildRecordAnim(),
  58. const Spacer(flex: 407),
  59. _buildRecordControl(),
  60. ],
  61. ),
  62. ),
  63. _buildAvailableTimeRemind(),
  64. ]);
  65. }
  66. Widget _buildAvailableTimeRemind() {
  67. return Obx(() {
  68. int? electric = controller.userInfo?.memberInfo?.electric;
  69. return Visibility(
  70. visible: electric != null &&
  71. electric < 12 &&
  72. !controller.isHideIntegrationInsufficient.value,
  73. child: IntrinsicHeight(
  74. child: Align(
  75. alignment: Alignment.bottomCenter,
  76. child: Container(
  77. margin: EdgeInsets.only(
  78. left: 16.w,
  79. right: 16.w,
  80. bottom: 200.h,
  81. ),
  82. child: Stack(
  83. children: [
  84. Align(
  85. alignment: Alignment.bottomCenter,
  86. child: Container(
  87. width: double.infinity,
  88. height: 48.w,
  89. decoration: BoxDecoration(
  90. borderRadius: BorderRadius.circular(10.w),
  91. gradient: LinearGradient(colors: [
  92. '#8671FF'.color,
  93. '#3E55FF'.color,
  94. '#7E80FE'.color,
  95. ], stops: const [
  96. 0.0,
  97. 0.7,
  98. 1
  99. ]),
  100. ),
  101. child: Stack(
  102. children: [
  103. Align(
  104. alignment: const Alignment(-0.05, -0.15),
  105. child: Assets
  106. .images.iconRecordIntegrationInsufficient
  107. .image(width: 153.w, height: 20.w),
  108. ),
  109. Align(
  110. alignment: Alignment.centerRight,
  111. child: GestureDetector(
  112. onTap: () =>
  113. controller.onAvailableTimeClick(),
  114. child: Container(
  115. padding: EdgeInsets.symmetric(
  116. horizontal: 10.w, vertical: 4.w),
  117. decoration: BoxDecoration(
  118. gradient: RadialGradient(
  119. center: Alignment.centerRight,
  120. colors: [
  121. "#E7F2FF".toColor(),
  122. "#FFFFFF".toColor(),
  123. "#F9E8FF".toColor()
  124. ],
  125. radius: 2),
  126. borderRadius:
  127. BorderRadius.circular(100.w),
  128. ),
  129. margin: EdgeInsets.only(right: 12.w),
  130. child: Assets.images.iconRecordRecharge
  131. .image(width: 39.w, height: 19.w)),
  132. ))
  133. ],
  134. ),
  135. ),
  136. ),
  137. Assets.images.iconRecordAvailableTime
  138. .image(width: 88.w, height: 77.w),
  139. Align(
  140. alignment: Alignment.topRight,
  141. child: GestureDetector(
  142. onTap: () {
  143. controller.onCloseAvailableTimeClick();
  144. },
  145. child: Assets
  146. .images.iconRecordIntegrationInsufficientClose
  147. .image(width: 18.w, height: 18.w),
  148. ),
  149. )
  150. ],
  151. ))),
  152. ),
  153. );
  154. });
  155. }
  156. Widget _buildAddShortcut(bool visible) {
  157. return GestureDetector(
  158. onTap: () {
  159. controller.addShortcut();
  160. },
  161. child: Visibility(
  162. visible: visible,
  163. child: Row(
  164. children: [
  165. Image(
  166. image: Assets.images.iconRecordAddShortcut.provider(),
  167. width: 24.w,
  168. height: 24.w),
  169. Padding(
  170. padding: EdgeInsets.only(left: 8.w, right: 16.w),
  171. child: Text(
  172. Platform.isIOS ? '添加到快捷方式' : '添加到桌面',
  173. style: TextStyle(color: ColorName.white, fontSize: 14.w),
  174. ),
  175. )
  176. ],
  177. ),
  178. ),
  179. );
  180. }
  181. Widget _buildRecordStatus() {
  182. return Container(
  183. padding: EdgeInsets.symmetric(horizontal: 16.w),
  184. margin: EdgeInsets.only(top: 20.w),
  185. child: Row(
  186. children: [
  187. Container(
  188. margin: EdgeInsets.only(right: 8.w),
  189. child: Image(
  190. image: Assets.images.iconRecordLogo.provider(),
  191. width: 45.w,
  192. height: 48.w),
  193. ),
  194. Obx(() {
  195. return Text(
  196. controller.currentStatus.value.desc,
  197. style: TextStyle(color: ColorName.white, fontSize: 17.w),
  198. );
  199. }),
  200. ],
  201. ),
  202. );
  203. }
  204. Widget _buildRecordAnim() {
  205. return Obx(() {
  206. return AnimatedOpacity(
  207. opacity:
  208. controller.currentStatus.value == RecordStatus.recording ? 1 : 0,
  209. duration: const Duration(milliseconds: 520),
  210. child: SizedBox(
  211. width: 360.w,
  212. height: 180.w,
  213. child: Lottie.asset(Assets.anim.animRecordingLottie)),
  214. );
  215. });
  216. }
  217. Widget _buildRecordControl() {
  218. return Stack(
  219. alignment: Alignment.bottomCenter,
  220. children: [
  221. Container(
  222. padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 30.w),
  223. decoration: BoxDecoration(
  224. color: "#4A4F67".color,
  225. borderRadius: BorderRadius.only(
  226. topLeft: Radius.circular(40.w),
  227. topRight: Radius.circular(40.w)),
  228. ),
  229. child: Row(
  230. children: [
  231. GestureDetector(
  232. onTap: controller.onCancelClick,
  233. child: Obx(() {
  234. return Image(
  235. image: controller.currentStatus.value.cancelButtonImage,
  236. width: 56.w,
  237. height: 56.w);
  238. }),
  239. ),
  240. const Spacer(),
  241. GestureDetector(
  242. onTap: controller.onSaveClick,
  243. child: Obx(() {
  244. return Image(
  245. image: controller.currentStatus.value.saveButtonImage,
  246. width: 56.w,
  247. height: 56.w);
  248. }),
  249. ),
  250. ],
  251. ),
  252. ),
  253. Column(
  254. children: [
  255. GestureDetector(
  256. onTap: () {
  257. controller.onActionClick();
  258. },
  259. child: Obx(
  260. () => Image(
  261. image: controller.currentStatus.value.actionButtonImage,
  262. width: 92.w,
  263. height: 92.w),
  264. )),
  265. Padding(
  266. padding: EdgeInsets.only(top: 10.w, bottom: 35.w),
  267. child: Obx(() => Text(
  268. formatDuration(controller.currentDuration.value),
  269. style: TextStyle(
  270. color: ColorName.white,
  271. fontSize: 16.w,
  272. ),
  273. )),
  274. )
  275. ],
  276. )
  277. ],
  278. );
  279. }
  280. Widget _buildBottomGradient() {
  281. return Container(
  282. height: 0.38.sh,
  283. decoration: BoxDecoration(
  284. gradient: LinearGradient(
  285. begin: Alignment.topCenter,
  286. end: Alignment.bottomCenter,
  287. colors: [
  288. "#006177F2".color,
  289. "#806177F2".color,
  290. ],
  291. ),
  292. ),
  293. );
  294. }
  295. String formatDuration(double value) {
  296. int hour = (value / 3600).floor();
  297. int minute = ((value - hour * 3600) / 60).floor();
  298. int second = (value - hour * 3600 - minute * 60).floor();
  299. return '${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}:${second.toString().padLeft(2, '0')}';
  300. }
  301. }