index.dart 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:math';
  4. import 'dart:typed_data';
  5. import 'package:event_bus/event_bus.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:flutter_svg/svg.dart';
  8. import 'package:link/model/model.dart';
  9. import 'package:link/utils/api.dart';
  10. import 'package:link/utils/global.dart';
  11. import 'package:link/utils/storage.dart';
  12. import 'package:link/utils/util.dart';
  13. import 'package:link/view/home_add_link.dart';
  14. import 'package:link/view/home_content.dart';
  15. import 'package:link/view/share.dart';
  16. import 'package:link/view/home_social_list.dart';
  17. import 'package:url_launcher/url_launcher.dart';
  18. import '../constants.dart';
  19. import '../utils/http_utils.dart';
  20. import '../utils/size_fit.dart';
  21. import 'package:get/get.dart';
  22. import 'package:screenshot/screenshot.dart';
  23. import 'component/link_btn.dart';
  24. import 'component/menu.dart';
  25. import 'component/toast.dart';
  26. import 'component/top_container.dart';
  27. import 'guide.dart';
  28. import 'package:dio/dio.dart';
  29. import 'package:dio/dio.dart' as adio;
  30. import 'dart:js' as js;
  31. class IndexScreen extends StatefulWidget {
  32. const IndexScreen({Key? key}) : super(key: key);
  33. @override
  34. State<IndexScreen> createState() => _IndexScreenState();
  35. }
  36. class _IndexScreenState extends State<IndexScreen>
  37. with RouteAware, SingleTickerProviderStateMixin {
  38. ScreenshotController screenshotController = ScreenshotController();
  39. double alpha = 0.0;
  40. late AnimationController controller;
  41. late Animation animation;
  42. Uint8List? byteData;
  43. Uint8List? qrcodeData;
  44. Widget? demoWidget;
  45. UserBean? userBean;
  46. Map<String, dynamic>? styles;
  47. bool showMenu = false;
  48. bool isMyPage = false;
  49. GlobalKey addLinkkey = GlobalKey();
  50. GlobalKey itemkey = GlobalKey();
  51. bool showGuide = false;
  52. Offset itemOffset = const Offset(0, 0);
  53. Offset guideOffset = const Offset(0, 0);
  54. int guideStep = 0;
  55. String uid = '';
  56. bool showGuideLink = false;
  57. bool showGuideMore = false;
  58. bool showGuideDrag = false;
  59. bool showWelcome = false;
  60. List socials = [];
  61. @override
  62. void initState() {
  63. // TODO: implement initState
  64. super.initState();
  65. if (Global().eventBus == null) {
  66. Global().eventBus = EventBus();
  67. }
  68. checkToken();
  69. controller = AnimationController(
  70. vsync: this, duration: const Duration(milliseconds: 100));
  71. animation = Tween(begin: 0.0, end: 1.0)
  72. .animate(CurvedAnimation(parent: controller, curve: Curves.easeOut));
  73. controller.addListener(() {
  74. setState(() {});
  75. });
  76. // getUserInfo();
  77. Map<String, dynamic> data = Get.parameters;
  78. if (data.isNotEmpty) {
  79. if (data['u'] != null) {
  80. uid = data['u'];
  81. Global().uid = uid;
  82. if (StorageUtil().getJSON('userInfo')!=null && StorageUtil().getJSON('userInfo')['id'] == uid) {
  83. isMyPage = true;
  84. }
  85. }
  86. if (data['code']!=null){
  87. Global().code = data['code'];
  88. }
  89. } else {
  90. if (Global().hasLogin) {
  91. isMyPage = true;
  92. }
  93. }
  94. getUserInfo();
  95. if (isMyPage) {
  96. Util().setPageTitle('我的主页');
  97. getQRCode();
  98. }
  99. // getQRCode();
  100. }
  101. Future getQRCode() async {
  102. Dio dio = Dio();
  103. // 注意:这里使用bytes
  104. dio.options.responseType = ResponseType.bytes;
  105. // 如果headers有东西,则添加
  106. Map<String, dynamic> headers = {
  107. 'Authorization': 'Bearer ${Global().token}'
  108. };
  109. dio.options.headers = headers;
  110. try {
  111. String url = 'https://h5.link.dev.liveplus.fun/?u=' + uid;
  112. String path = Api.baseUrl + Api.qr + '?data=$url';
  113. adio.Response response = await dio.get(path);
  114. final Uint8List bytes = consolidateHttpClientResponseBytes(response.data);
  115. setState(() {
  116. qrcodeData = bytes;
  117. });
  118. } catch (e) {
  119. return await null;
  120. }
  121. }
  122. consolidateHttpClientResponseBytes(List<int> data) {
  123. final List<List<int>> chunks = <List<int>>[];
  124. int contentLength = 0;
  125. chunks.add(data);
  126. contentLength += data.length;
  127. final Uint8List bytes = Uint8List(contentLength);
  128. int offset = 0;
  129. for (List<int> chunk in chunks) {
  130. bytes.setRange(offset, offset + chunk.length, chunk);
  131. offset += chunk.length;
  132. }
  133. return bytes;
  134. }
  135. Future checkToken() async {
  136. if (Global().token.isNotEmpty){
  137. var data = await HttpUtils.get(Api.token,params: {'token':Global().token});
  138. if (data['success']==false){
  139. Get.toNamed('/login');
  140. return;
  141. }
  142. }
  143. var jsonUserStep0 = StorageUtil().getJSON('tempUser0');
  144. if (jsonUserStep0!=null){
  145. Get.toNamed('/edit_nick_info');
  146. return;
  147. }
  148. var jsonUserStep1 = StorageUtil().getJSON('tempUser1');
  149. if (jsonUserStep1!=null){
  150. Get.toNamed('/edit_base_info');
  151. return;
  152. }
  153. var jsonLink0 = StorageUtil().getJSON('tempGuideLink0');
  154. if (jsonLink0!=null){
  155. Get.toNamed('/begin_add_first_link');
  156. return;
  157. }
  158. var jsonLink1 = StorageUtil().getJSON('tempGuideLink1');
  159. if (jsonLink1!=null){
  160. Get.toNamed('/add_link',
  161. parameters: {'social': jsonEncode(jsonLink1['social'])});
  162. return;
  163. }
  164. var json = StorageUtil().getJSON('tempLink');
  165. if (json != null) {
  166. Get.toNamed('/add_link',
  167. parameters: {'social': jsonEncode(json['social']), 'add_more': '1'});
  168. return;
  169. }
  170. }
  171. getSize() {
  172. if (!isMyPage) {
  173. return;
  174. }
  175. if (showGuideLink || showGuideMore || showGuideDrag) {
  176. Offset offset;
  177. if (userBean!.socials!.isEmpty) {
  178. offset = Offset.zero;
  179. } else {
  180. RenderBox widget =
  181. itemkey.currentContext!.findRenderObject() as RenderBox;
  182. offset = widget.localToGlobal(Offset.zero);
  183. }
  184. if (addLinkkey.currentContext==null){
  185. return;
  186. }
  187. RenderBox widget2 =
  188. addLinkkey.currentContext!.findRenderObject() as RenderBox;
  189. setState(() {
  190. showGuide = true;
  191. itemOffset = offset;
  192. guideOffset = widget2.localToGlobal(Offset.zero);
  193. });
  194. }
  195. }
  196. @override
  197. void dispose() {
  198. // TODO: implement dispose
  199. controller.dispose();
  200. super.dispose();
  201. }
  202. @override
  203. void didChangeDependencies() {
  204. // TODO: implement didChangeDependencies
  205. super.didChangeDependencies();
  206. Global().routeObserver!.subscribe(this, ModalRoute.of(context)!);
  207. }
  208. @override
  209. void didPopNext() {
  210. // TODO: implement didPopNext
  211. getUserInfo();
  212. super.didPopNext();
  213. }
  214. Future getUserInfo() async {
  215. Map<String, dynamic> data;
  216. Map<String, dynamic> styleObj;
  217. if (uid.isNotEmpty && (StorageUtil().getJSON('userInfo')==null||StorageUtil().getJSON('userInfo')['id'] != uid)) {
  218. data = await HttpUtils.get('users/$uid/info');
  219. styleObj = await HttpUtils.get('users/$uid/styles');
  220. } else {
  221. data = await HttpUtils.get(Api.userSocials);
  222. styleObj = await HttpUtils.get(Api.userStyles);
  223. uid = data['id'];
  224. Global().uid = uid;
  225. }
  226. var data2 = await HttpUtils.get(Api.socials);
  227. // print(data.toString());
  228. if (data2['data'] is List) {
  229. setState(() {
  230. userBean = UserBean.fromJson(data);
  231. Global().userBean = userBean;
  232. styles = styleObj;
  233. socials = data2['data'];
  234. Global().socials = socials;
  235. });
  236. } else {
  237. setState(() {
  238. userBean = UserBean.fromJson(data);
  239. Global().userBean = userBean;
  240. styles = styleObj;
  241. });
  242. }
  243. Global().themeId = data['theme_style_id'];
  244. if (Global().hasLogin) {
  245. Map<String, dynamic> data2 = await HttpUtils.get(Api.frontData,
  246. params: {'code': 'guide_first_link'});
  247. Map<String, dynamic> data3 =
  248. await HttpUtils.get(Api.frontData, params: {'code': 'guide_more'});
  249. Map<String, dynamic> data4 =
  250. await HttpUtils.get(Api.frontData, params: {'code': 'guide_drag'});
  251. var newData = await HttpUtils.get(Api.frontDatas,params: {'codes':"guide_first_link,guide_more,guide_drag"});
  252. Timer(const Duration(seconds: 1), () {
  253. getSize();
  254. });
  255. setState(() {
  256. if (data2['value'].length == 0 &&
  257. data3['value'].length == 0 &&
  258. data4['value'].length == 0) {
  259. showWelcome = true;
  260. guideStep = 0;
  261. } else {
  262. guideStep = 1;
  263. }
  264. if (userBean!.socials!.isEmpty) {
  265. if (data2['value'].length == 0) {
  266. showGuideLink = true;
  267. }
  268. } else if (userBean!.socials!.length == 1) {
  269. if (data3['value'].length == 0) {
  270. showGuideMore = true;
  271. }
  272. } else if (userBean!.socials!.length > 1) {
  273. if (data4['value'].length == 0) {
  274. showGuideDrag = true;
  275. }
  276. }
  277. });
  278. }
  279. if (!isMyPage) {
  280. Util().setPageTitle(userBean!.nickname!);
  281. }
  282. getQRCode();
  283. }
  284. Future updateGuideData(var data) async {
  285. await HttpUtils.post(Api.frontData, data: data);
  286. }
  287. openMenu() {
  288. setState(() {
  289. showMenu = true;
  290. });
  291. controller.forward();
  292. }
  293. closeMenu() {
  294. controller.reverse();
  295. Timer(const Duration(milliseconds: 300), () {
  296. setState(() {
  297. showMenu = false;
  298. });
  299. });
  300. }
  301. lauchURL(url) async {
  302. // js.context.callMethod('aaa',['hisss']);
  303. if (await canLaunch(url)) {
  304. await launch(url);
  305. }
  306. }
  307. Widget guideItem() {
  308. String title = '开始探索 2/4';
  309. String content = '这是我刚添加的第1个链接,点击跳转查看;如需调整,仍可继续编辑';
  310. if (guideStep == 2) {
  311. title = '开始探索 3/4';
  312. content = '添加更多链接,让世界更好地了解我!';
  313. } else if (guideStep == 3) {
  314. title = '开始探索 4/4';
  315. content = '这里汇集了更多主题风格,快去探索并装点我的主页吧!未来将会支持个性化样式,敬请期待~';
  316. } else if (guideStep == 4) {
  317. title = '完成';
  318. content = '预览主页效果,所见即是我确认后,分享至会话或群聊,是时候让世界认识我了!';
  319. }
  320. if (guideStep == 3) {
  321. return Stack(
  322. children: [
  323. Positioned(left: 0, width: 120.px, top: 0, bottom: 0, child: Menu()),
  324. Container(
  325. margin: EdgeInsets.only(left: 80.px, top: 15.px),
  326. child: Row(
  327. mainAxisAlignment: MainAxisAlignment.start,
  328. crossAxisAlignment: CrossAxisAlignment.start,
  329. children: [
  330. Container(
  331. padding: EdgeInsets.only(left: 8.px),
  332. child:
  333. GuideTip(content: content, direction: 2, width: 258.px),
  334. ),
  335. Container(
  336. margin: EdgeInsets.only(top: 90.px),
  337. // alignment: Alignment.centerLeft,
  338. transform: Matrix4.translationValues(-20.px - 258.px, 0, 0),
  339. child: Transform.rotate(
  340. angle: pi / 2.0,
  341. child: Image.asset(
  342. 'assets/images/arrow_corner.png',
  343. width: 28.px,
  344. height: 14.px,
  345. )),
  346. )
  347. // Positioned(
  348. // left: 0,
  349. // top: 0,
  350. // bottom: 0,
  351. // child: Container(
  352. // alignment: Alignment.centerLeft,
  353. // transform: Matrix4.translationValues(-12.px-258.px, 0, 0),
  354. // child: Transform.rotate(
  355. // angle: pi / 2.0,
  356. // child: Image.asset(
  357. // 'assets/images/arrow_corner.png',
  358. // width: 28.px,
  359. // height: 14.px,
  360. // )),
  361. // ))
  362. ],
  363. ),
  364. ),
  365. Column(
  366. children: [
  367. Expanded(child: Container()),
  368. LinkButton(
  369. title: title,
  370. btnWidth: 172.px,
  371. disable: false,
  372. isBlack: false,
  373. callback: () {
  374. setState(() {
  375. guideStep = guideStep + 1;
  376. if (guideStep > 4) {
  377. showGuide = false;
  378. }
  379. // showGuide = false;
  380. });
  381. }),
  382. SizedBox(
  383. height: 64.px,
  384. )
  385. ],
  386. )
  387. ],
  388. );
  389. }
  390. if (guideStep == 4) {
  391. return Container(
  392. width: 375.px,
  393. color: Colors.transparent,
  394. child: Column(
  395. children: [
  396. Container(
  397. width: 375.px,
  398. height: 72.px,
  399. decoration: const BoxDecoration(
  400. gradient: LinearGradient(
  401. begin: Alignment.centerLeft,
  402. end: Alignment.centerRight,
  403. colors: [
  404. Color(0x00FFF700),
  405. Color(0x00FFF700),
  406. Color(0xFFFFF700),
  407. ],
  408. stops: [
  409. 0,
  410. 0.25,
  411. 1
  412. ]),
  413. ),
  414. ),
  415. Container(
  416. width: 375.px,
  417. height: 300.px,
  418. transform: Matrix4.translationValues(0, -20.px, 0),
  419. child: Stack(
  420. children: [
  421. Positioned(
  422. top: 13.5.px,
  423. right: 8.px,
  424. child:
  425. GuideTip(content: content, direction: 2, width: 276.px),
  426. ),
  427. Positioned(
  428. right: 60.px,
  429. child: Transform.rotate(
  430. angle: pi,
  431. child: Image.asset(
  432. 'assets/images/arrow_corner.png',
  433. width: 28.px,
  434. height: 14.px,
  435. // color: const Color(0xFF0000FF),
  436. )
  437. // SvgPicture.asset(
  438. // 'assets/icons/arrow_corner.svg',
  439. // width: 28.px,
  440. // height: 14.px,
  441. // color: const Color(0xFF0000FF),
  442. // )
  443. ))
  444. ],
  445. ),
  446. ),
  447. Expanded(child: Container()),
  448. LinkButton(
  449. title: title,
  450. btnWidth: 172.px,
  451. disable: false,
  452. isBlack: false,
  453. callback: () {
  454. setState(() {
  455. guideStep = guideStep + 1;
  456. if (guideStep > 4) {
  457. showGuide = false;
  458. showGuideMore = false;
  459. updateGuideData({"code": "guide_more", "value": "1"});
  460. }
  461. // showGuide = false;
  462. });
  463. }),
  464. SizedBox(
  465. height: 64.px,
  466. )
  467. ],
  468. ),
  469. );
  470. }
  471. if (showGuide) {
  472. return Container(
  473. color: Colors.transparent,
  474. child: Column(
  475. children: [
  476. Container(
  477. height: guideStep == 1 ? itemOffset.dy : guideOffset.dy,
  478. alignment: Alignment.bottomCenter,
  479. child: Column(
  480. children: [
  481. Expanded(child: Container()),
  482. GuideTip(content: content, direction: 2, width: 316.px),
  483. Image.asset(
  484. 'assets/images/arrow_corner.png',
  485. width: 28.px,
  486. height: 14.px,
  487. )
  488. // SvgPicture.asset(
  489. // 'assets/icons/arrow_corner.svg',
  490. // width: 28.px,
  491. // height: 14.px,
  492. // color: const Color(0xFF0000FF),
  493. // )
  494. ],
  495. ),
  496. ),
  497. if (guideStep == 1)
  498. SocialList(
  499. userBean: userBean!,
  500. styles: styles!,
  501. itemkey: itemkey,
  502. isMyPage: isMyPage,
  503. socials: socials,
  504. canDrag: false,
  505. scale: 1.0,
  506. ),
  507. if (guideStep == 2)
  508. HomeAddLink(
  509. socialObj: styles!['social_item'],
  510. addLinkkey: addLinkkey,
  511. scale: 1.0,
  512. ),
  513. Expanded(child: Container()),
  514. LinkButton(
  515. title: title,
  516. btnWidth: 172.px,
  517. disable: false,
  518. isBlack: false,
  519. callback: () {
  520. setState(() {
  521. guideStep = guideStep + 1;
  522. if (guideStep > 4) {
  523. showGuide = false;
  524. showGuideMore = false;
  525. updateGuideData({"code": "guide_more", "value": "1"});
  526. }
  527. // showGuide = false;
  528. });
  529. }),
  530. SizedBox(
  531. height: 64.px,
  532. )
  533. ],
  534. ),
  535. );
  536. }
  537. return Container();
  538. }
  539. Widget guideAddLink() {
  540. if (showGuide) {
  541. return Container(
  542. color: Colors.transparent,
  543. child: Column(
  544. children: [
  545. Container(
  546. height: guideOffset.dy,
  547. alignment: Alignment.bottomCenter,
  548. child: Column(
  549. children: [
  550. Expanded(child: Container()),
  551. GuideTip(
  552. content: '快去添加我的第1个链接,让世界认识我!添加后解锁「切换主题」、「预览&分享」等更多功能',
  553. direction: 2,
  554. width: 316.px),
  555. Image.asset(
  556. 'assets/images/arrow_corner.png',
  557. width: 28.px,
  558. height: 14.px,
  559. // color: const Color(0xFF0000FF),
  560. )
  561. ],
  562. ),
  563. ),
  564. // addLinkWidget(disable: true),
  565. HomeAddLink(
  566. socialObj: styles!['social_item'],
  567. addLinkkey: addLinkkey,
  568. disable: true,
  569. scale: 1.0,
  570. ),
  571. Expanded(child: Container()),
  572. LinkButton(
  573. title: '完成',
  574. btnWidth: 172.px,
  575. disable: false,
  576. isBlack: false,
  577. callback: () {
  578. setState(() {
  579. showGuide = false;
  580. showGuideLink = false;
  581. updateGuideData({"code": "guide_first_link", "value": "1"});
  582. });
  583. }),
  584. SizedBox(
  585. height: 64.px,
  586. )
  587. ],
  588. ),
  589. );
  590. }
  591. return Container();
  592. }
  593. guideDrag() {
  594. return Container(
  595. color: Colors.transparent,
  596. child: Column(
  597. children: [
  598. Container(
  599. height: guideStep == 1 ? itemOffset.dy : guideOffset.dy,
  600. alignment: Alignment.bottomCenter,
  601. child: Column(
  602. children: [
  603. Expanded(child: Container()),
  604. GuideTip(content: '长按激活,上下拖拽调整排序', direction: 2, width: 316.px),
  605. // SvgPicture.asset(
  606. // 'assets/icons/arrow_corner.svg',
  607. // width: 28.px,
  608. // height: 14.px,
  609. // color: const Color(0xFF0000FF),
  610. // )
  611. Image.asset(
  612. 'assets/images/arrow_corner.png',
  613. width: 28.px,
  614. height: 14.px,
  615. )
  616. ],
  617. ),
  618. ),
  619. if (guideStep == 1)
  620. SocialList(
  621. userBean: userBean!,
  622. styles: styles!,
  623. itemkey: itemkey,
  624. isMyPage: isMyPage,
  625. socials: socials,
  626. canDrag: false,
  627. scale: 1.0,
  628. ),
  629. Expanded(child: Container()),
  630. LinkButton(
  631. title: '完成',
  632. btnWidth: 172.px,
  633. disable: false,
  634. isBlack: false,
  635. callback: () {
  636. setState(() {
  637. showGuide = false;
  638. showGuideDrag = false;
  639. updateGuideData({"code": "guide_drag", "value": "1"});
  640. // showGuide = false;
  641. });
  642. }),
  643. SizedBox(
  644. height: 64.px,
  645. )
  646. ],
  647. ),
  648. );
  649. }
  650. test() {
  651. String title = '开始探索 2/4';
  652. String content = '这是我刚添加的第1个链接,点击跳转查看;如需调整,仍可继续编辑';
  653. return Positioned(
  654. left: 0,
  655. right: 0,
  656. top: 0,
  657. bottom: 0,
  658. child: Container(
  659. color: const Color(0xBF000000),
  660. child: Stack(
  661. children: [
  662. Positioned(
  663. left: 0, width: 120.px, top: 0, bottom: 0, child: Menu()),
  664. Container(
  665. margin: EdgeInsets.only(left: 80.px, top: 15.px),
  666. child: Stack(
  667. children: [
  668. Container(
  669. padding: EdgeInsets.only(left: 8.px),
  670. child: GuideTip(
  671. content: content, direction: 2, width: 260.px),
  672. ),
  673. Positioned(
  674. left: 0,
  675. top: 0,
  676. bottom: 0,
  677. child: Container(
  678. alignment: Alignment.centerLeft,
  679. transform: Matrix4.translationValues(-12.px, 0, 0),
  680. child: Transform.rotate(
  681. angle: pi / 2.0,
  682. child: Image.asset(
  683. 'assets/images/arrow_corner.png',
  684. width: 28.px,
  685. height: 14.px,
  686. )),
  687. ))
  688. ],
  689. )),
  690. Column(
  691. children: [
  692. Expanded(child: Container()),
  693. LinkButton(
  694. title: title,
  695. btnWidth: 172.px,
  696. disable: false,
  697. isBlack: false,
  698. callback: () {
  699. setState(() {
  700. guideStep = guideStep + 1;
  701. if (guideStep > 4) {
  702. showGuide = false;
  703. }
  704. // showGuide = false;
  705. });
  706. }),
  707. SizedBox(
  708. height: 64.px,
  709. )
  710. ],
  711. )
  712. ],
  713. ),
  714. ));
  715. }
  716. guideContent() {
  717. return Positioned(
  718. left: 0,
  719. right: 0,
  720. top: 0,
  721. bottom: 0,
  722. child: Container(
  723. color: guideStep == 0 ? Colors.transparent : const Color(0xBF000000),
  724. // color: const Color(0xBF000000),
  725. child: Stack(
  726. children: [
  727. if (guideStep == 0)
  728. IndexWelcome(
  729. close: () {
  730. setState(() {
  731. guideStep = 1;
  732. });
  733. },
  734. ),
  735. if (guideStep != 0 && showGuideMore) guideItem(),
  736. if (guideStep != 0 && showGuideLink) guideAddLink(),
  737. if (guideStep != 0 && showGuideDrag) guideDrag(),
  738. // guideItem()
  739. // guideAddLink()
  740. // Container(
  741. // width: 375.px,
  742. // height: 72.px,
  743. // decoration: const BoxDecoration(
  744. // gradient: LinearGradient(
  745. // begin: Alignment.centerLeft,
  746. // end: Alignment.centerRight,
  747. // colors: [
  748. // Color(0x00FFF700),
  749. // Color(0x00FFF700),
  750. // Color(0xFFFFF700),
  751. // ],
  752. // stops: [0,0.25,1]
  753. // ),
  754. // ),
  755. // ),
  756. ],
  757. ),
  758. ));
  759. }
  760. tapShare() {
  761. // width: MediaQuery.of(context).size.width,
  762. // height: MediaQuery.of(context).size.height,
  763. // js.context.callMethod('capture', [0, 0, MediaQuery.of(context).size.width, MediaQuery.of(context).size.height]);
  764. // final canvas = html.CanvasElement(width: 300, height: 300);
  765. // var context = canvas.context2D;
  766. // context.draw...(); // do whatever drawing you need
  767. // final blob = await canvas.toBlob('image/jpeg', 0.8);
  768. screenshotController.capture().then((value) {
  769. Toast().showText('长按图片识别或保存', context: context);
  770. setState(() {
  771. byteData = value as Uint8List;
  772. });
  773. showDialog(
  774. context: context,
  775. barrierDismissible: false,
  776. barrierColor: const Color(0xBF000000),
  777. useSafeArea: false,
  778. builder: (BuildContext context) {
  779. return Share(byteData: value as Uint8List);
  780. });
  781. }).catchError((error) {
  782. Toast().showText(error.toString(), context: context);
  783. });
  784. }
  785. content() {
  786. return Material(
  787. child: Stack(
  788. children: [
  789. Opacity(
  790. opacity: 0.01,
  791. child: Screenshot(
  792. controller: screenshotController,
  793. child: Stack(children: [
  794. HomeContent(
  795. userBean: userBean!,
  796. styles: styles!,
  797. socials: socials,
  798. scale: 1.0,
  799. isPreview: true,
  800. ),
  801. Positioned(
  802. left: 0,
  803. right: 0,
  804. bottom: 0,
  805. height: 200.px,
  806. child: Container(
  807. padding: EdgeInsets.only(top: 30.px),
  808. decoration: const BoxDecoration(
  809. gradient: LinearGradient(
  810. begin: Alignment.topCenter,
  811. end: Alignment.bottomCenter,
  812. colors: [
  813. Color(0x00000000),
  814. Color(0x33000000),
  815. Color(0xFF131314),
  816. Color(0xFF131314)
  817. ],
  818. stops: [
  819. 0,
  820. 0.18,
  821. 0.51,
  822. 1
  823. ])),
  824. child: Row(
  825. children: [
  826. SizedBox(
  827. width: 32.px,
  828. ),
  829. Column(
  830. children: [
  831. if (qrcodeData != null)
  832. Image.memory(
  833. qrcodeData!,
  834. width: 100.px,
  835. height: 100.px,
  836. // color: Colors.pink,
  837. ),
  838. SizedBox(
  839. height: 8.px,
  840. ),
  841. Text(
  842. '长按识别二维码\n进入我的LinkBaeBae主页',
  843. textAlign: TextAlign.center,
  844. style: TextStyle(
  845. color: Colors.white, fontSize: 10.px),
  846. )
  847. ],
  848. ),
  849. SizedBox(
  850. width: 38.px,
  851. ),
  852. Container(
  853. margin: EdgeInsets.only(top: 40.px),
  854. child: Image.asset(
  855. 'assets/images/logo.png',
  856. width: 155.px,
  857. fit: BoxFit.cover,
  858. ),
  859. ),
  860. ],
  861. ),
  862. ))
  863. ])),
  864. ),
  865. HomeContent(
  866. userBean: userBean!,
  867. styles: styles!,
  868. socials: socials,
  869. itemkey: itemkey,
  870. addLinkkey: addLinkkey,
  871. scale: 1.0,
  872. share: () {
  873. tapShare();
  874. },
  875. openMenu: () {
  876. openMenu();
  877. },
  878. ),
  879. // Container(
  880. // width: MediaQuery.of(context).size.width * 0.3,
  881. // height: MediaQuery.of(context).size.height * 0.3,
  882. // child: HomeContent(
  883. // userBean: userBean!,
  884. // styles: styles!,
  885. // socials: socials,
  886. // itemkey: itemkey1,
  887. // addLinkkey: addLinkkey1,
  888. // scale: 0.3,
  889. // ),
  890. // ),
  891. // copyrightWidget(),
  892. if (showMenu)
  893. Positioned(
  894. child: Opacity(
  895. opacity: animation.value,
  896. child: Container(
  897. color: const Color(0xBF000000),
  898. ),
  899. )),
  900. if (showMenu)
  901. Positioned(
  902. left: 0,
  903. right: 0,
  904. top: 0,
  905. bottom: 0,
  906. child: Container(
  907. color: Colors.transparent,
  908. width: 375.px,
  909. transform: Matrix4.translationValues(
  910. -220.px + animation.value * 220.px, 0, 0),
  911. child: Row(
  912. children: [
  913. Menu(
  914. isEnable: true,
  915. closeMenu: () {
  916. closeMenu();
  917. },
  918. ),
  919. Expanded(
  920. child: GestureDetector(
  921. onTap: () {
  922. closeMenu();
  923. },
  924. child: Container(
  925. color: Colors.transparent,
  926. )),
  927. )
  928. // child: Expanded(child: SizedBox(width: 1,)),
  929. // )
  930. ],
  931. ),
  932. )),
  933. if (showGuide) guideContent(),
  934. // test(),
  935. if (showGuide && guideStep == 4)
  936. Row(
  937. children: [
  938. const Expanded(
  939. child: SizedBox(
  940. height: 1.0,
  941. )),
  942. if (isMyPage)
  943. GestureDetector(
  944. child: Container(
  945. margin: EdgeInsets.only(right: 0.px),
  946. child: SvgPicture.asset(
  947. 'assets/icons/preview.svg',
  948. width: 36.px,
  949. height: 24.px,
  950. color: Util().stringToColor(
  951. styles!['toolbar']['right_icon']['color']),
  952. )),
  953. ),
  954. GestureDetector(
  955. child: Container(
  956. height: 72.px,
  957. padding: EdgeInsets.only(left: 24.px, right: 24.px),
  958. child: SvgPicture.asset(
  959. 'assets/icons/navi_share.svg',
  960. width: 24.px,
  961. height: 24.px,
  962. color: Util().stringToColor(
  963. styles!['toolbar']['right_icon']['color']),
  964. ),
  965. ),
  966. )
  967. ],
  968. ),
  969. ],
  970. ));
  971. }
  972. @override
  973. Widget build(BuildContext context) {
  974. SizeFit.initialize(context);
  975. if (styles == null) {
  976. return Container();
  977. }
  978. return Material(
  979. child: TopContainer(
  980. child:content()));
  981. // return content();
  982. // return Screenshot(controller: screenshotController, child: content());
  983. }
  984. }