my_group.dart 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_hbb/common/hbbs/hbbs.dart';
  4. import 'package:flutter_hbb/common/widgets/login.dart';
  5. import 'package:flutter_hbb/common/widgets/peers_view.dart';
  6. import 'package:flutter_hbb/models/state_model.dart';
  7. import 'package:get/get.dart';
  8. import '../../common.dart';
  9. class MyGroup extends StatefulWidget {
  10. final EdgeInsets? menuPadding;
  11. const MyGroup({Key? key, this.menuPadding}) : super(key: key);
  12. @override
  13. State<StatefulWidget> createState() {
  14. return _MyGroupState();
  15. }
  16. }
  17. class _MyGroupState extends State<MyGroup> {
  18. RxString get selectedUser => gFFI.groupModel.selectedUser;
  19. RxString get searchUserText => gFFI.groupModel.searchUserText;
  20. static TextEditingController searchUserController = TextEditingController();
  21. @override
  22. Widget build(BuildContext context) {
  23. return Obx(() {
  24. if (!gFFI.userModel.isLogin) {
  25. return Center(
  26. child: ElevatedButton(
  27. onPressed: loginDialog, child: Text(translate("Login"))));
  28. } else if (gFFI.userModel.networkError.isNotEmpty) {
  29. return netWorkErrorWidget();
  30. } else if (gFFI.groupModel.groupLoading.value && gFFI.groupModel.emtpy) {
  31. return const Center(
  32. child: CircularProgressIndicator(),
  33. );
  34. }
  35. return Column(
  36. children: [
  37. buildErrorBanner(context,
  38. loading: gFFI.groupModel.groupLoading,
  39. err: gFFI.groupModel.groupLoadError,
  40. retry: null,
  41. close: () => gFFI.groupModel.groupLoadError.value = ''),
  42. Expanded(
  43. child: Obx(() => stateGlobal.isPortrait.isTrue
  44. ? _buildPortrait()
  45. : _buildLandscape())),
  46. ],
  47. );
  48. });
  49. }
  50. Widget _buildLandscape() {
  51. return Row(
  52. children: [
  53. Container(
  54. decoration: BoxDecoration(
  55. borderRadius: BorderRadius.circular(12),
  56. border:
  57. Border.all(color: Theme.of(context).colorScheme.background)),
  58. child: Container(
  59. width: 150,
  60. height: double.infinity,
  61. child: Column(
  62. children: [
  63. _buildLeftHeader(),
  64. Expanded(
  65. child: Container(
  66. width: double.infinity,
  67. height: double.infinity,
  68. child: _buildUserContacts(),
  69. ),
  70. )
  71. ],
  72. ),
  73. ),
  74. ).marginOnly(right: 12.0),
  75. Expanded(
  76. child: Align(
  77. alignment: Alignment.topLeft,
  78. child: MyGroupPeerView(
  79. menuPadding: widget.menuPadding,
  80. )),
  81. )
  82. ],
  83. );
  84. }
  85. Widget _buildPortrait() {
  86. return Column(
  87. children: [
  88. Container(
  89. decoration: BoxDecoration(
  90. borderRadius: BorderRadius.circular(6),
  91. border:
  92. Border.all(color: Theme.of(context).colorScheme.background)),
  93. child: Container(
  94. child: Column(
  95. mainAxisSize: MainAxisSize.min,
  96. children: [
  97. _buildLeftHeader(),
  98. Container(
  99. width: double.infinity,
  100. child: _buildUserContacts(),
  101. )
  102. ],
  103. ),
  104. ),
  105. ).marginOnly(bottom: 12.0),
  106. Expanded(
  107. child: Align(
  108. alignment: Alignment.topLeft,
  109. child: MyGroupPeerView(
  110. menuPadding: widget.menuPadding,
  111. )),
  112. )
  113. ],
  114. );
  115. }
  116. Widget _buildLeftHeader() {
  117. final fontSize = 14.0;
  118. return Row(
  119. children: [
  120. Expanded(
  121. child: TextField(
  122. controller: searchUserController,
  123. onChanged: (value) {
  124. searchUserText.value = value;
  125. },
  126. textAlignVertical: TextAlignVertical.center,
  127. style: TextStyle(fontSize: fontSize),
  128. decoration: InputDecoration(
  129. filled: false,
  130. prefixIcon: Icon(
  131. Icons.search_rounded,
  132. color: Theme.of(context).hintColor,
  133. ).paddingOnly(top: 2),
  134. hintText: translate("Search"),
  135. hintStyle: TextStyle(fontSize: fontSize),
  136. border: InputBorder.none,
  137. isDense: true,
  138. ),
  139. )),
  140. ],
  141. );
  142. }
  143. Widget _buildUserContacts() {
  144. return Obx(() {
  145. final items = gFFI.groupModel.users.where((p0) {
  146. if (searchUserText.isNotEmpty) {
  147. return p0.name
  148. .toLowerCase()
  149. .contains(searchUserText.value.toLowerCase());
  150. }
  151. return true;
  152. }).toList();
  153. listView(bool isPortrait) => ListView.builder(
  154. shrinkWrap: isPortrait,
  155. itemCount: items.length,
  156. itemBuilder: (context, index) => _buildUserItem(items[index]));
  157. var maxHeight = max(MediaQuery.of(context).size.height / 6, 100.0);
  158. return Obx(() => stateGlobal.isPortrait.isFalse
  159. ? listView(false)
  160. : LimitedBox(maxHeight: maxHeight, child: listView(true)));
  161. });
  162. }
  163. Widget _buildUserItem(UserPayload user) {
  164. final username = user.name;
  165. return InkWell(onTap: () {
  166. if (selectedUser.value != username) {
  167. selectedUser.value = username;
  168. } else {
  169. selectedUser.value = '';
  170. }
  171. }, child: Obx(
  172. () {
  173. bool selected = selectedUser.value == username;
  174. final isMe = username == gFFI.userModel.userName.value;
  175. final colorMe = MyTheme.color(context).me!;
  176. return Container(
  177. decoration: BoxDecoration(
  178. color: selected ? MyTheme.color(context).highlight : null,
  179. border: Border(
  180. bottom: BorderSide(
  181. width: 0.7,
  182. color: Theme.of(context).dividerColor.withOpacity(0.1))),
  183. ),
  184. child: Container(
  185. child: Row(
  186. children: [
  187. Container(
  188. width: 20,
  189. height: 20,
  190. decoration: BoxDecoration(
  191. color: str2color(username, 0xAF),
  192. shape: BoxShape.circle,
  193. ),
  194. child: Align(
  195. alignment: Alignment.center,
  196. child: Center(
  197. child: Text(
  198. username.characters.first.toUpperCase(),
  199. style: TextStyle(color: Colors.white),
  200. textAlign: TextAlign.center,
  201. ),
  202. ),
  203. ),
  204. ).marginOnly(right: 4),
  205. if (isMe) Flexible(child: Text(username)),
  206. if (isMe)
  207. Flexible(
  208. child: Container(
  209. margin: EdgeInsets.only(left: 5),
  210. padding: EdgeInsets.symmetric(horizontal: 3, vertical: 1),
  211. decoration: BoxDecoration(
  212. color: colorMe.withAlpha(20),
  213. borderRadius: BorderRadius.all(Radius.circular(2)),
  214. border: Border.all(color: colorMe.withAlpha(100))),
  215. child: Text(
  216. translate('Me'),
  217. style: TextStyle(
  218. color: colorMe.withAlpha(200), fontSize: 12),
  219. ),
  220. ),
  221. ),
  222. if (!isMe) Expanded(child: Text(username)),
  223. ],
  224. ).paddingSymmetric(vertical: 4),
  225. ),
  226. );
  227. },
  228. )).marginSymmetric(horizontal: 12).marginOnly(bottom: 6);
  229. }
  230. }