home_social_list.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. import 'dart:convert';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:flutter_svg/svg.dart';
  5. import 'package:get/get.dart';
  6. import 'package:link/view/preview.dart';
  7. import 'package:url_launcher/url_launcher.dart';
  8. import 'dart:js' as js;
  9. import '../model/model.dart';
  10. import '../utils/api.dart';
  11. import '../utils/global.dart';
  12. import '../utils/http_utils.dart';
  13. import '../utils/size_fit.dart';
  14. import '../utils/util.dart';
  15. import 'component/button.dart';
  16. import 'component/toast.dart';
  17. class SocialList extends StatefulWidget {
  18. UserBean userBean;
  19. Map<String, dynamic> styles;
  20. GlobalKey? _itemkey;
  21. List socials;
  22. bool isMyPage;
  23. bool canDrag;
  24. double scale;
  25. SocialList(
  26. {Key? key,
  27. required this.userBean,
  28. required this.styles,
  29. required this.isMyPage,
  30. required this.socials,
  31. required this.canDrag,
  32. required this.scale,
  33. GlobalKey? itemkey})
  34. : super(key: key){
  35. if (itemkey!=null){
  36. _itemkey = itemkey;
  37. }
  38. }
  39. @override
  40. State<SocialList> createState() => _SocialListState();
  41. }
  42. class _SocialListState extends State<SocialList> {
  43. lauchURL(url) async {
  44. js.context.callMethod('open', [url,'_self']);
  45. // js.context.callMethod('aaa',['hisss']);
  46. // if (await canLaunch(url)) {
  47. // await launch(url);
  48. // }
  49. // if (!await launchUrl(url)) {
  50. // throw 'Could not launch $url';
  51. // }
  52. // lauchURL(url);
  53. // Get.toNamed('web');
  54. }
  55. copy(url) async{
  56. Clipboard.setData(ClipboardData(text: url));
  57. Toast().showSuccessText('已复制到剪切板', context: context);
  58. }
  59. socialListWidget({bool disable = false}) {
  60. var socialObj = widget.styles['social_item'];
  61. String strColor = socialObj['background_color'].substring(1, 9);
  62. int value = int.parse(strColor, radix: 16);
  63. double borderWidth = 0.0;
  64. String borderColor = '#00000000';
  65. if (socialObj['border_width'] != null) {
  66. borderWidth = double.parse(socialObj['border_width']);
  67. borderColor = socialObj['border_color'];
  68. }
  69. List<BoxShadow> shadows = [];
  70. if (socialObj['top_shadow'] != null) {
  71. String shadowColor =
  72. socialObj['top_shadow']['shadow_color'].substring(1, 9);
  73. int valueShadow = int.parse(shadowColor, radix: 16);
  74. shadows.add(BoxShadow(
  75. color: Color(valueShadow),
  76. blurRadius: double.parse(socialObj['top_shadow']['shadow_radius'])*widget.scale,
  77. offset: Offset(double.parse(socialObj['top_shadow']['offset_x'])*widget.scale,
  78. double.parse(socialObj['top_shadow']['offset_y'])*widget.scale)));
  79. }
  80. if (socialObj['bottom_shadow'] != null) {
  81. String shadowColor =
  82. socialObj['bottom_shadow']['shadow_color'].substring(1, 9);
  83. int valueShadow = int.parse(shadowColor, radix: 16);
  84. shadows.add(BoxShadow(
  85. color: Color(valueShadow),
  86. blurRadius: double.parse(socialObj['bottom_shadow']['shadow_radius'])*widget.scale,
  87. offset: Offset(double.parse(socialObj['bottom_shadow']['offset_x'])*widget.scale,
  88. double.parse(socialObj['bottom_shadow']['offset_y'])*widget.scale)));
  89. }
  90. Color copyColor = const Color(0xFF131314);
  91. Color qrColor = const Color(0xFF131314);
  92. if (socialObj['copylink_icon_color']!=null){
  93. copyColor = Util().stringToColor(socialObj['copylink_icon_color']);
  94. }
  95. if (socialObj['qr_icon_color']!=null){
  96. qrColor = Util().stringToColor(socialObj['qr_icon_color']);
  97. }
  98. return List<Widget>.generate(widget.userBean.socials!.length, (index) {
  99. SocialBean socialBean = widget.userBean.socials![index];
  100. return Button(
  101. // key: ValueKey(index),
  102. key: (index == 0 && disable == false)
  103. ? (widget._itemkey ?? ValueKey(index))
  104. : ValueKey(index),
  105. callback: (() {
  106. Global().eventBus!.fire('update');
  107. if (disable) {
  108. return;
  109. }
  110. if (socialBean.type == 'QR') {
  111. Toast().showText('长按图片识别或保存', context: context);
  112. showDialog(
  113. context: context,
  114. barrierDismissible: false,
  115. barrierColor: Colors.transparent,
  116. useSafeArea: false,
  117. builder: (BuildContext context) {
  118. return Preview(
  119. url: socialBean.userUrl,
  120. );
  121. });
  122. return;
  123. }
  124. lauchURL(socialBean.userUrl);
  125. }),
  126. child: Container(
  127. width: double.parse(socialObj['width']).px*widget.scale + borderWidth.px * 2*widget.scale,
  128. height: double.parse(socialObj['height']).px*widget.scale + borderWidth.px * 2*widget.scale,
  129. margin: EdgeInsets.only(
  130. bottom: double.parse((socialObj['space_height'])).px*widget.scale),
  131. decoration: BoxDecoration(
  132. boxShadow: shadows,
  133. border: Border.all(
  134. color: Util().stringToColor(borderColor),
  135. width: borderWidth.px*widget.scale),
  136. borderRadius: BorderRadius.circular(
  137. double.parse(socialObj['border_radius']).px*widget.scale +
  138. borderWidth.px*widget.scale)),
  139. child: Container(
  140. width: double.parse(socialObj['width']).px*widget.scale,
  141. height: double.parse(socialObj['height']).px*widget.scale,
  142. padding: EdgeInsets.only(
  143. left: double.parse(socialObj['padding_horizontal']).px*widget.scale,
  144. right: double.parse(socialObj['padding_horizontal']).px*widget.scale),
  145. decoration: BoxDecoration(
  146. color: Color(value),
  147. borderRadius: BorderRadius.all(Radius.circular(
  148. double.parse(socialObj['border_radius']).px*widget.scale))),
  149. child: Row(
  150. crossAxisAlignment: CrossAxisAlignment.center,
  151. children: [
  152. ClipRRect(
  153. borderRadius: BorderRadius.circular(6.px*widget.scale),
  154. child: socialBean.logo == null
  155. ? SvgPicture.asset(
  156. 'assets/icons/other_link.svg',
  157. width: 24.px*widget.scale,
  158. height: 24.px*widget.scale,
  159. )
  160. :
  161. // ImageNetwork(image: socialBean.logo!, height: 24.px, width: 24.px)
  162. // WebImage(url: 'assets/images/1.png', width: 24.px, height: 24.px)
  163. Image.network(
  164. socialBean.logo!,
  165. width: 24.px*widget.scale,
  166. height: 24.px*widget.scale,
  167. fit: BoxFit.cover,
  168. ),
  169. // WebImage(
  170. // url: socialBean.logo!, width: 24.px, height: 24.px),
  171. ),
  172. SizedBox(
  173. width: 10.px*widget.scale,
  174. ),
  175. Expanded(
  176. child: Column(
  177. mainAxisAlignment: MainAxisAlignment.center,
  178. crossAxisAlignment: CrossAxisAlignment.start,
  179. children: [
  180. Row(
  181. crossAxisAlignment: CrossAxisAlignment.center,
  182. children: [
  183. Text(
  184. socialBean.userNick!.isEmpty
  185. ? socialBean.name!
  186. : socialBean.userNick!,
  187. softWrap: true,
  188. overflow: TextOverflow.ellipsis,
  189. maxLines: 1,
  190. style: TextStyle(
  191. color: Util()
  192. .stringToColor(socialObj['text_color']),
  193. fontSize:
  194. double.parse(socialObj['font_size']).px*widget.scale,
  195. fontWeight: socialObj['font_weight'] == 'bold'
  196. ? FontWeight.bold
  197. : FontWeight.normal),
  198. ),
  199. SizedBox(
  200. width: 2.px*widget.scale,
  201. ),
  202. if (!widget.isMyPage)
  203. GestureDetector(
  204. onTap: (){
  205. Global().eventBus!.fire('update');
  206. copy(socialBean.userNick!);
  207. },
  208. child: SvgPicture.asset(
  209. 'assets/icons/home_copy.svg',
  210. width: 12.px*widget.scale,
  211. height: 12.px*widget.scale,
  212. color: copyColor,
  213. ),
  214. )
  215. ],
  216. ),
  217. if (socialBean.description!.isNotEmpty)
  218. Text(
  219. socialBean.description!,
  220. textAlign: TextAlign.left,
  221. softWrap: true,
  222. overflow: TextOverflow.ellipsis,
  223. maxLines: 1,
  224. style: TextStyle(
  225. color: Util().stringToColor(socialObj['desc_color']), fontSize: 10.px*widget.scale),
  226. )
  227. ],
  228. )),
  229. if (widget.isMyPage)
  230. GestureDetector(
  231. onTap: () {
  232. Global().eventBus!.fire('update');
  233. // ignore: prefer_typing_uninitialized_variables
  234. var obj;
  235. for (int i = 0; i < widget.socials.length; i++) {
  236. if (widget.socials[i]['id'] == socialBean.socialId) {
  237. obj = widget.socials[i];
  238. }
  239. }
  240. obj ??= {
  241. "id": "",
  242. "name": socialBean.name,
  243. "logo": "",
  244. "types": ["LINK", "QR"],
  245. "description_example": "",
  246. "url_example": ""
  247. };
  248. Get.toNamed('/edit_link', parameters: {
  249. 'id': socialBean.id!,
  250. 'social': jsonEncode(obj),
  251. });
  252. },
  253. child: Container(
  254. padding: EdgeInsets.all(5.px*widget.scale),
  255. child: SvgPicture.asset(
  256. 'assets/icons/edit_link.svg',
  257. width: 16.px*widget.scale,
  258. height: 16.px*widget.scale,
  259. color: Util().stringToColor(socialObj['arrow_color']),
  260. ),
  261. ),
  262. ),
  263. SizedBox(
  264. width: 9.px,
  265. ),
  266. if (socialBean.type == 'QR')
  267. Container(
  268. color: Colors.transparent,
  269. child: GestureDetector(
  270. child: SvgPicture.asset(
  271. 'assets/icons/qrcode.svg',
  272. width: 16.px*widget.scale,
  273. height: 16.px*widget.scale,
  274. color: qrColor,
  275. ),
  276. ),
  277. ),
  278. Container(
  279. color: Colors.transparent,
  280. child: SvgPicture.asset(
  281. 'assets/icons/arrow_right.svg',
  282. width: 16.px*widget.scale,
  283. height: 16.px*widget.scale,
  284. color: Util().stringToColor(socialObj['arrow_color']),
  285. ))
  286. ],
  287. ),
  288. ),
  289. ));
  290. });
  291. }
  292. Future updateSocialsOrder() async {
  293. List ids = [];
  294. for (int i = 0; i < widget.userBean.socials!.length; i++) {
  295. SocialBean bean = widget.userBean.socials![i];
  296. ids.add(bean.id!);
  297. }
  298. await HttpUtils.put(Api.userSocials, data: {'ids': ids});
  299. }
  300. @override
  301. Widget build(BuildContext context) {
  302. SizeFit.initialize(context);
  303. if (widget.canDrag) {
  304. return ReorderableListView(
  305. // buildDefaultDragHandles: false,
  306. physics: const NeverScrollableScrollPhysics(),
  307. children: socialListWidget(),
  308. onReorderStart: (index) {
  309. print('aaaa');
  310. },
  311. onReorderEnd: (index) {
  312. Global().eventBus!.fire('update');
  313. },
  314. onReorder: (int oldIndex, int newIndex) {
  315. if (oldIndex < newIndex) {
  316. newIndex -= 1;
  317. }
  318. var child = widget.userBean.socials!.removeAt(oldIndex);
  319. widget.userBean.socials!.insert(newIndex, child);
  320. setState(() {});
  321. updateSocialsOrder();
  322. },
  323. );
  324. }
  325. return Column(
  326. children: socialListWidget(),
  327. );
  328. }
  329. }