autocomplete.dart 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import 'dart:convert';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_hbb/common/formatter/id_formatter.dart';
  4. import '../../../models/platform_model.dart';
  5. import 'package:flutter_hbb/models/peer_model.dart';
  6. import 'package:flutter_hbb/common.dart';
  7. import 'package:flutter_hbb/common/widgets/peer_card.dart';
  8. Future<List<Peer>> getAllPeers() async {
  9. Map<String, dynamic> recentPeers = jsonDecode(bind.mainLoadRecentPeersSync());
  10. Map<String, dynamic> lanPeers = jsonDecode(bind.mainLoadLanPeersSync());
  11. Map<String, dynamic> combinedPeers = {};
  12. void mergePeers(Map<String, dynamic> peers) {
  13. if (peers.containsKey("peers")) {
  14. dynamic peerData = peers["peers"];
  15. if (peerData is String) {
  16. try {
  17. peerData = jsonDecode(peerData);
  18. } catch (e) {
  19. print("Error decoding peers: $e");
  20. return;
  21. }
  22. }
  23. if (peerData is List) {
  24. for (var peer in peerData) {
  25. if (peer is Map && peer.containsKey("id")) {
  26. String id = peer["id"];
  27. if (!combinedPeers.containsKey(id)) {
  28. combinedPeers[id] = peer;
  29. }
  30. }
  31. }
  32. }
  33. }
  34. }
  35. mergePeers(recentPeers);
  36. mergePeers(lanPeers);
  37. for (var p in gFFI.abModel.allPeers()) {
  38. if (!combinedPeers.containsKey(p.id)) {
  39. combinedPeers[p.id] = p.toJson();
  40. }
  41. }
  42. for (var p in gFFI.groupModel.peers.map((e) => Peer.copy(e)).toList()) {
  43. if (!combinedPeers.containsKey(p.id)) {
  44. combinedPeers[p.id] = p.toJson();
  45. }
  46. }
  47. List<Peer> parsedPeers = [];
  48. for (var peer in combinedPeers.values) {
  49. parsedPeers.add(Peer.fromJson(peer));
  50. }
  51. return parsedPeers;
  52. }
  53. class AutocompletePeerTile extends StatefulWidget {
  54. final VoidCallback onSelect;
  55. final Peer peer;
  56. const AutocompletePeerTile({
  57. Key? key,
  58. required this.onSelect,
  59. required this.peer,
  60. }) : super(key: key);
  61. @override
  62. AutocompletePeerTileState createState() => AutocompletePeerTileState();
  63. }
  64. class AutocompletePeerTileState extends State<AutocompletePeerTile> {
  65. List _frontN<T>(List list, int n) {
  66. if (list.length <= n) {
  67. return list;
  68. } else {
  69. return list.sublist(0, n);
  70. }
  71. }
  72. @override
  73. Widget build(BuildContext context) {
  74. final double tileRadius = 5;
  75. final name =
  76. '${widget.peer.username}${widget.peer.username.isNotEmpty && widget.peer.hostname.isNotEmpty ? '@' : ''}${widget.peer.hostname}';
  77. final greyStyle = TextStyle(
  78. fontSize: 11,
  79. color: Theme.of(context).textTheme.titleLarge?.color?.withOpacity(0.6));
  80. final child = GestureDetector(
  81. onTap: () => widget.onSelect(),
  82. child: Padding(
  83. padding: EdgeInsets.only(left: 5, right: 5),
  84. child: Container(
  85. height: 42,
  86. margin: EdgeInsets.only(bottom: 5),
  87. child: Row(
  88. mainAxisSize: MainAxisSize.max,
  89. children: [
  90. Container(
  91. decoration: BoxDecoration(
  92. color: str2color(
  93. '${widget.peer.id}${widget.peer.platform}', 0x7f),
  94. borderRadius: BorderRadius.only(
  95. topLeft: Radius.circular(tileRadius),
  96. bottomLeft: Radius.circular(tileRadius),
  97. ),
  98. ),
  99. alignment: Alignment.center,
  100. width: 42,
  101. height: null,
  102. child: Padding(
  103. padding: EdgeInsets.all(6),
  104. child: getPlatformImage(widget.peer.platform,
  105. size: 30))),
  106. Expanded(
  107. child: Container(
  108. padding: EdgeInsets.only(left: 10),
  109. decoration: BoxDecoration(
  110. color: Theme.of(context).colorScheme.background,
  111. borderRadius: BorderRadius.only(
  112. topRight: Radius.circular(tileRadius),
  113. bottomRight: Radius.circular(tileRadius),
  114. ),
  115. ),
  116. child: Row(
  117. children: [
  118. Expanded(
  119. child: Container(
  120. margin: EdgeInsets.only(top: 2),
  121. child: Container(
  122. margin: EdgeInsets.only(top: 2),
  123. child: Column(
  124. children: [
  125. Container(
  126. margin:
  127. EdgeInsets.only(top: 2),
  128. child: Row(children: [
  129. getOnline(
  130. 8, widget.peer.online),
  131. Expanded(
  132. child: Text(
  133. widget.peer.alias.isEmpty
  134. ? formatID(
  135. widget.peer.id)
  136. : widget.peer.alias,
  137. overflow:
  138. TextOverflow.ellipsis,
  139. style: Theme.of(context)
  140. .textTheme
  141. .titleSmall,
  142. )),
  143. widget.peer.alias.isNotEmpty
  144. ? Padding(
  145. padding:
  146. const EdgeInsets
  147. .only(
  148. left: 5,
  149. right: 5),
  150. child: Text(
  151. "(${widget.peer.id})",
  152. style: greyStyle,
  153. overflow:
  154. TextOverflow
  155. .ellipsis,
  156. ))
  157. : Container(),
  158. ])),
  159. Align(
  160. alignment: Alignment.centerLeft,
  161. child: Text(
  162. name,
  163. style: greyStyle,
  164. textAlign: TextAlign.start,
  165. overflow:
  166. TextOverflow.ellipsis,
  167. ),
  168. ),
  169. ],
  170. )))),
  171. ],
  172. )),
  173. )
  174. ],
  175. ))));
  176. final colors = _frontN(widget.peer.tags, 25)
  177. .map((e) => gFFI.abModel.getCurrentAbTagColor(e))
  178. .toList();
  179. return Tooltip(
  180. message: !(isDesktop || isWebDesktop)
  181. ? ''
  182. : widget.peer.tags.isNotEmpty
  183. ? '${translate('Tags')}: ${widget.peer.tags.join(', ')}'
  184. : '',
  185. child: Stack(children: [
  186. child,
  187. if (colors.isNotEmpty)
  188. Positioned(
  189. top: 5,
  190. right: 10,
  191. child: CustomPaint(
  192. painter: TagPainter(radius: 3, colors: colors),
  193. ),
  194. )
  195. ]),
  196. );
  197. }
  198. }