Showing
6 changed files
with
477 additions
and
184 deletions
| @@ -5,6 +5,7 @@ import 'package:one_key/constant/state.dart'; | @@ -5,6 +5,7 @@ import 'package:one_key/constant/state.dart'; | ||
| 5 | import 'package:one_key/provider/contant_show_model.dart'; | 5 | import 'package:one_key/provider/contant_show_model.dart'; |
| 6 | import 'package:one_key/provider/user_model.dart'; | 6 | import 'package:one_key/provider/user_model.dart'; |
| 7 | import 'package:one_key/res/colors.dart'; | 7 | import 'package:one_key/res/colors.dart'; |
| 8 | +import 'package:one_key/widgets/MyDivider.dart'; | ||
| 8 | 9 | ||
| 9 | import 'package:one_key/widgets/page_exception.dart'; | 10 | import 'package:one_key/widgets/page_exception.dart'; |
| 10 | import 'package:one_key/widgets/v_empty_view.dart'; | 11 | import 'package:one_key/widgets/v_empty_view.dart'; |
| @@ -41,66 +42,80 @@ class _ContantLeftPageState extends State<ContantLeftPage> { | @@ -41,66 +42,80 @@ class _ContantLeftPageState extends State<ContantLeftPage> { | ||
| 41 | @override | 42 | @override |
| 42 | Widget build(BuildContext context) { | 43 | Widget build(BuildContext context) { |
| 43 | contantShowModel = Provider.of<ContantShowModel>(context, listen: true); | 44 | contantShowModel = Provider.of<ContantShowModel>(context, listen: true); |
| 44 | - return Expanded( | ||
| 45 | - child: Consumer<ContantShowModel>( | ||
| 46 | - builder: (context, model, _) { | ||
| 47 | - if (model.pageStateLeft != PageState.Success) { | ||
| 48 | - return ExceptionPage( | ||
| 49 | - pageState: model.pageStateLeft, | ||
| 50 | - callback: () { | ||
| 51 | - // offset = 0; | ||
| 52 | - // getMessages(); | ||
| 53 | - _getContantData(); | ||
| 54 | - }, | ||
| 55 | - emptyMsg: "暂时没有联系人哦", | ||
| 56 | - emptyImg: "empty_search", | ||
| 57 | - showMsg: "加载中,请稍后...", | ||
| 58 | - ); | ||
| 59 | - } else { | ||
| 60 | - return EasyRefresh.custom( | ||
| 61 | - controller: _controller, | ||
| 62 | - slivers: [ | ||
| 63 | - SliverList(delegate: SliverChildBuilderDelegate( | ||
| 64 | - (BuildContext context, int index) { | ||
| 65 | - return Container( | ||
| 66 | - padding: EdgeInsets.symmetric( | ||
| 67 | - horizontal: ScreenUtil().setWidth(40), | ||
| 68 | - vertical: ScreenUtil().setWidth(30)), | ||
| 69 | - height: ScreenUtil().setWidth(74 * 2), | ||
| 70 | - decoration: BoxDecoration( | ||
| 71 | - border: Border( | ||
| 72 | - bottom: BorderSide( | ||
| 73 | - width: ScreenUtil().setWidth(2), | ||
| 74 | - color: MyColours.color_E0E0E0))), | ||
| 75 | - child: Column( | ||
| 76 | - crossAxisAlignment: CrossAxisAlignment.start, | ||
| 77 | - children: [ | ||
| 78 | - Text(model.userHistorys[index].rname, | ||
| 79 | - style: TextStyle( | ||
| 80 | - color: MyColours.color_333333, | ||
| 81 | - fontSize: ScreenUtil().setSp(32))), | ||
| 82 | - VEmptyView(10), | ||
| 83 | - Text(model.userHistorys[index].phone, | ||
| 84 | - style: TextStyle( | ||
| 85 | - color: MyColours.color_999999, | ||
| 86 | - fontSize: ScreenUtil().setSp(30))) | ||
| 87 | - ], | ||
| 88 | - ), | ||
| 89 | - ); | ||
| 90 | - })) | ||
| 91 | - ], | ||
| 92 | - // onRefresh: () async { | ||
| 93 | - // // offset = 0; | ||
| 94 | - // // getMessages(showLoading: false); | ||
| 95 | - // }, | ||
| 96 | - // onLoad: () async { | ||
| 97 | - // // offset++; | ||
| 98 | - // // getMessages(showLoading: false); | ||
| 99 | - // }, | ||
| 100 | - ); | ||
| 101 | - } | ||
| 102 | - }, | ||
| 103 | - ), | 45 | + return Consumer<ContantShowModel>( |
| 46 | + builder: (context, model, _) { | ||
| 47 | + if (model.pageStateLeft != PageState.Success) { | ||
| 48 | + return ExceptionPage( | ||
| 49 | + pageState: model.pageStateLeft, | ||
| 50 | + callback: () { | ||
| 51 | + // offset = 0; | ||
| 52 | + // getMessages(); | ||
| 53 | + _getContantData(); | ||
| 54 | + }, | ||
| 55 | + emptyMsg: "暂时没有联系人哦", | ||
| 56 | + emptyImg: "empty_search", | ||
| 57 | + showMsg: "加载中,请稍后...", | ||
| 58 | + ); | ||
| 59 | + } else { | ||
| 60 | + return ListView.builder( | ||
| 61 | + itemCount: model.userHistorys.length, | ||
| 62 | + itemBuilder: (BuildContext context, int index) { | ||
| 63 | + return Column( | ||
| 64 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 65 | + children: [ | ||
| 66 | + index == 0 | ||
| 67 | + ? MyDivider( | ||
| 68 | + double.infinity, | ||
| 69 | + ScreenUtil().setWidth(20), | ||
| 70 | + color: MyColours.color_f5f5f5, | ||
| 71 | + ) | ||
| 72 | + : Container(), | ||
| 73 | + Container( | ||
| 74 | + width: double.infinity, | ||
| 75 | + padding: EdgeInsets.symmetric( | ||
| 76 | + horizontal: ScreenUtil().setWidth(40), | ||
| 77 | + vertical: ScreenUtil().setWidth(30)), | ||
| 78 | + height: ScreenUtil().setWidth(74 * 2), | ||
| 79 | + decoration: BoxDecoration( | ||
| 80 | + border: Border( | ||
| 81 | + top: index == 0 | ||
| 82 | + ? BorderSide( | ||
| 83 | + width: ScreenUtil().setWidth(2), | ||
| 84 | + color: MyColours.color_E0E0E0) | ||
| 85 | + : BorderSide( | ||
| 86 | + width: 0, color: Colors.transparent), | ||
| 87 | + bottom: BorderSide( | ||
| 88 | + width: ScreenUtil().setWidth(2), | ||
| 89 | + color: MyColours.color_E0E0E0))), | ||
| 90 | + child: Column( | ||
| 91 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 92 | + children: [ | ||
| 93 | + Text(model.userHistorys[index].rname, | ||
| 94 | + style: TextStyle( | ||
| 95 | + color: MyColours.color_333333, | ||
| 96 | + fontSize: ScreenUtil().setSp(32))), | ||
| 97 | + VEmptyView(10), | ||
| 98 | + Text(model.userHistorys[index].phone, | ||
| 99 | + style: TextStyle( | ||
| 100 | + color: MyColours.color_999999, | ||
| 101 | + fontSize: ScreenUtil().setSp(30))) | ||
| 102 | + ], | ||
| 103 | + ), | ||
| 104 | + ) | ||
| 105 | + ]); | ||
| 106 | + }); | ||
| 107 | + | ||
| 108 | + // onRefresh: () async { | ||
| 109 | + // // offset = 0; | ||
| 110 | + // // getMessages(showLoading: false); | ||
| 111 | + // }, | ||
| 112 | + // onLoad: () async { | ||
| 113 | + // // offset++; | ||
| 114 | + // // getMessages(showLoading: false); | ||
| 115 | + // }, | ||
| 116 | + | ||
| 117 | + } | ||
| 118 | + }, | ||
| 104 | ); | 119 | ); |
| 105 | } | 120 | } |
| 106 | } | 121 | } |
| @@ -5,10 +5,17 @@ import 'package:contacts_service/contacts_service.dart'; | @@ -5,10 +5,17 @@ import 'package:contacts_service/contacts_service.dart'; | ||
| 5 | import 'package:flutter_screenutil/screenutil.dart'; | 5 | import 'package:flutter_screenutil/screenutil.dart'; |
| 6 | import 'package:intl/intl.dart'; | 6 | import 'package:intl/intl.dart'; |
| 7 | import 'package:one_key/pages/my/contant_left_page.dart'; | 7 | import 'package:one_key/pages/my/contant_left_page.dart'; |
| 8 | +import 'package:one_key/pages/my/contant_right_page.dart'; | ||
| 8 | import 'package:one_key/provider/contant_show_model.dart'; | 9 | import 'package:one_key/provider/contant_show_model.dart'; |
| 9 | import 'package:one_key/res/colors.dart'; | 10 | import 'package:one_key/res/colors.dart'; |
| 11 | +import 'package:one_key/utils/dialog_util.dart'; | ||
| 12 | +import 'package:one_key/utils/event_bus.dart'; | ||
| 13 | +import 'package:one_key/utils/misc.dart'; | ||
| 14 | +import 'package:one_key/widgets/MyDivider.dart'; | ||
| 10 | import 'package:one_key/widgets/custom_tab_indicator.dart'; | 15 | import 'package:one_key/widgets/custom_tab_indicator.dart'; |
| 11 | import 'package:one_key/widgets/system_app_bar.dart'; | 16 | import 'package:one_key/widgets/system_app_bar.dart'; |
| 17 | +import 'package:one_key/widgets/v_empty_view.dart'; | ||
| 18 | +import 'package:permission_handler/permission_handler.dart'; | ||
| 12 | import 'package:provider/provider.dart'; | 19 | import 'package:provider/provider.dart'; |
| 13 | 20 | ||
| 14 | class ContactListPage extends StatefulWidget { | 21 | class ContactListPage extends StatefulWidget { |
| @@ -16,111 +23,77 @@ class ContactListPage extends StatefulWidget { | @@ -16,111 +23,77 @@ class ContactListPage extends StatefulWidget { | ||
| 16 | _ContactListPageState createState() => _ContactListPageState(); | 23 | _ContactListPageState createState() => _ContactListPageState(); |
| 17 | } | 24 | } |
| 18 | 25 | ||
| 19 | -class _ContactListPageState extends State<ContactListPage> { | 26 | +class _ContactListPageState extends State<ContactListPage> |
| 27 | + with TickerProviderStateMixin { | ||
| 20 | List<Contact> _contacts; | 28 | List<Contact> _contacts; |
| 21 | List _tabBarTitle; | 29 | List _tabBarTitle; |
| 30 | + TabController tabController; | ||
| 22 | 31 | ||
| 23 | @override | 32 | @override |
| 24 | void initState() { | 33 | void initState() { |
| 25 | _tabBarTitle = ['预订联系人', '手机联系人']; | 34 | _tabBarTitle = ['预订联系人', '手机联系人']; |
| 26 | super.initState(); | 35 | super.initState(); |
| 27 | - refreshContacts(); | ||
| 28 | - } | ||
| 29 | - | ||
| 30 | - Future<void> refreshContacts() async { | ||
| 31 | - // Load without thumbnails initially. | ||
| 32 | - var contacts = (await ContactsService.getContacts( | ||
| 33 | - withThumbnails: false, iOSLocalizedLabels: false)) | ||
| 34 | - .toList(); | ||
| 35 | -// var contacts = (await ContactsService.getContactsForPhone("8554964652")) | ||
| 36 | -// .toList(); | ||
| 37 | - setState(() { | ||
| 38 | - _contacts = contacts; | ||
| 39 | - }); | ||
| 40 | - | ||
| 41 | - // Lazy load thumbnails after rendering initial contacts. | ||
| 42 | - for (final contact in contacts) { | ||
| 43 | - ContactsService.getAvatar(contact).then((avatar) { | ||
| 44 | - if (avatar == null) return; // Don't redraw if no change. | ||
| 45 | - setState(() => contact.avatar = avatar); | ||
| 46 | - }); | ||
| 47 | - } | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - void updateContact() async { | ||
| 51 | - Contact ninja = _contacts | ||
| 52 | - .toList() | ||
| 53 | - .firstWhere((contact) => contact.familyName.startsWith("Ninja")); | ||
| 54 | - ninja.avatar = null; | ||
| 55 | - await ContactsService.updateContact(ninja); | ||
| 56 | - | ||
| 57 | - refreshContacts(); | ||
| 58 | - } | ||
| 59 | - | ||
| 60 | - _openContactForm() async { | ||
| 61 | - try { | ||
| 62 | - var contact = | ||
| 63 | - await ContactsService.openContactForm(iOSLocalizedLabels: false); | ||
| 64 | - refreshContacts(); | ||
| 65 | - } on FormOperationException catch (e) { | ||
| 66 | - switch (e.errorCode) { | ||
| 67 | - case FormOperationErrorCode.FORM_OPERATION_CANCELED: | ||
| 68 | - case FormOperationErrorCode.FORM_COULD_NOT_BE_OPEN: | ||
| 69 | - case FormOperationErrorCode.FORM_OPERATION_UNKNOWN_ERROR: | ||
| 70 | - default: | ||
| 71 | - print(e.errorCode); | ||
| 72 | - } | ||
| 73 | - } | 36 | + tabController = TabController(length: 2, vsync: this); |
| 74 | } | 37 | } |
| 75 | 38 | ||
| 76 | @override | 39 | @override |
| 77 | Widget build(BuildContext context) { | 40 | Widget build(BuildContext context) { |
| 78 | return Scaffold( | 41 | return Scaffold( |
| 79 | backgroundColor: MyColours.color_ffffff, | 42 | backgroundColor: MyColours.color_ffffff, |
| 80 | - appBar: SystemAppBar('联系人'), | ||
| 81 | - body: SafeArea( | ||
| 82 | - child: DefaultTabController( | ||
| 83 | - length: 2, | ||
| 84 | - child: Stack( | 43 | + appBar: SystemAppBar( |
| 44 | + '联系人', | ||
| 45 | + onTap: () { | ||
| 46 | + EventBus().emit('changeStatusColor'); | ||
| 47 | + Navigator.of(context).pop(); | ||
| 48 | + }, | ||
| 49 | + ), | ||
| 50 | + body: WillPopScope( | ||
| 51 | + child: SafeArea( | ||
| 52 | + child: Column( | ||
| 53 | + children: <Widget>[ | ||
| 54 | + Container( | ||
| 55 | + padding: EdgeInsets.only(bottom: ScreenUtil().setWidth(10)), | ||
| 56 | + margin: EdgeInsets.symmetric( | ||
| 57 | + horizontal: ScreenUtil().setWidth(30)), | ||
| 58 | + child: TabBar( | ||
| 59 | + controller: tabController, | ||
| 60 | + indicator: CustomTabIndicator( | ||
| 61 | + radius: 0, | ||
| 62 | + ), | ||
| 63 | + indicatorColor: MyColours.color_199095, | ||
| 64 | + indicatorSize: TabBarIndicatorSize.tab, | ||
| 65 | + // indicatorPadding: EdgeInsets.symmetric( | ||
| 66 | + // horizontal: ScreenUtil().setWidth(12)), | ||
| 67 | + labelColor: MyColours.color_199095, | ||
| 68 | + labelStyle: TextStyle( | ||
| 69 | + fontSize: ScreenUtil().setSp(32), | ||
| 70 | + fontWeight: FontWeight.bold), | ||
| 71 | + labelPadding: EdgeInsets.zero, | ||
| 72 | + unselectedLabelStyle: | ||
| 73 | + TextStyle(fontWeight: FontWeight.normal), | ||
| 74 | + unselectedLabelColor: MyColours.color_999999, | ||
| 75 | + tabs: _tabBarTitle.map((value) { | ||
| 76 | + return Tab( | ||
| 77 | + child: Text(value), | ||
| 78 | + ); | ||
| 79 | + }).toList()), | ||
| 80 | + ), | ||
| 81 | + Expanded( | ||
| 82 | + child: TabBarView( | ||
| 83 | + controller: tabController, | ||
| 84 | + // physics: NeverScrollableScrollPhysics(), | ||
| 85 | children: <Widget>[ | 85 | children: <Widget>[ |
| 86 | - TabBarView( | ||
| 87 | - physics: NeverScrollableScrollPhysics(), | ||
| 88 | - children: <Widget>[ | ||
| 89 | - ChangeNotifierProvider<ContantShowModel>( | ||
| 90 | - create: (_) => ContantShowModel(), | ||
| 91 | - child: ContantLeftPage()), | ||
| 92 | - Container() | ||
| 93 | - ], | ||
| 94 | - ), | ||
| 95 | - Positioned( | ||
| 96 | - child: Container( | ||
| 97 | - padding: | ||
| 98 | - EdgeInsets.only(bottom: ScreenUtil().setWidth(10)), | ||
| 99 | - margin: EdgeInsets.symmetric( | ||
| 100 | - horizontal: ScreenUtil().setWidth(30)), | ||
| 101 | - child: TabBar( | ||
| 102 | - indicator: CustomTabIndicator( | ||
| 103 | - radius: 0, | ||
| 104 | - ), | ||
| 105 | - indicatorColor: MyColours.color_199095, | ||
| 106 | - indicatorSize: TabBarIndicatorSize.tab, | ||
| 107 | - // indicatorPadding: EdgeInsets.symmetric( | ||
| 108 | - // horizontal: ScreenUtil().setWidth(12)), | ||
| 109 | - labelColor: MyColours.color_199095, | ||
| 110 | - labelStyle: TextStyle( | ||
| 111 | - fontSize: ScreenUtil().setSp(32), | ||
| 112 | - fontWeight: FontWeight.bold), | ||
| 113 | - labelPadding: EdgeInsets.zero, | ||
| 114 | - unselectedLabelStyle: | ||
| 115 | - TextStyle(fontWeight: FontWeight.normal), | ||
| 116 | - unselectedLabelColor: MyColours.color_999999, | ||
| 117 | - tabs: _tabBarTitle.map((value) { | ||
| 118 | - return Tab( | ||
| 119 | - child: Text(value), | ||
| 120 | - ); | ||
| 121 | - }).toList()), | ||
| 122 | - )) | 86 | + ChangeNotifierProvider<ContantShowModel>( |
| 87 | + create: (_) => ContantShowModel(), | ||
| 88 | + child: ContantLeftPage()), | ||
| 89 | + ContantRightPage() | ||
| 123 | ], | 90 | ], |
| 124 | - )))); | 91 | + )), |
| 92 | + ], | ||
| 93 | + )), | ||
| 94 | + onWillPop: () async { | ||
| 95 | + EventBus().emit('changeStatusColor'); | ||
| 96 | + return true; | ||
| 97 | + })); | ||
| 125 | } | 98 | } |
| 126 | } | 99 | } |
lib/pages/my/contant_right_page.dart
0 → 100644
| 1 | +import 'dart:io'; | ||
| 2 | + | ||
| 3 | +import 'package:flutter/material.dart'; | ||
| 4 | + | ||
| 5 | +import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 6 | +import 'package:one_key/constant/state.dart'; | ||
| 7 | + | ||
| 8 | +import 'package:one_key/res/colors.dart'; | ||
| 9 | +import 'package:one_key/utils/dialog_util.dart'; | ||
| 10 | +import 'package:one_key/utils/misc.dart'; | ||
| 11 | +import 'package:one_key/widgets/MyDivider.dart'; | ||
| 12 | + | ||
| 13 | +import 'package:one_key/widgets/page_exception.dart'; | ||
| 14 | +import 'package:one_key/widgets/v_empty_view.dart'; | ||
| 15 | +import 'package:contacts_service/contacts_service.dart'; | ||
| 16 | +import 'package:permission_handler/permission_handler.dart'; | ||
| 17 | + | ||
| 18 | +class ContantRightPage extends StatefulWidget { | ||
| 19 | + ContantRightPage({Key key}) : super(key: key); | ||
| 20 | + | ||
| 21 | + @override | ||
| 22 | + _ContantRightPageState createState() => _ContantRightPageState(); | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +class _ContantRightPageState extends State<ContantRightPage> { | ||
| 26 | + PageState _pageState = PageState.Loading; | ||
| 27 | + List<Contact> _contacts; | ||
| 28 | + bool isNeed = false; | ||
| 29 | + bool goSetting = false; | ||
| 30 | + bool userNo = false; | ||
| 31 | + @override | ||
| 32 | + void initState() { | ||
| 33 | + super.initState(); | ||
| 34 | + _openAddressBook(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + // Future<void> _askPermissions() async { | ||
| 38 | + // PermissionStatus permissionStatus = await _getContactPermission(); | ||
| 39 | + // if (permissionStatus != PermissionStatus.granted) { | ||
| 40 | + // _handleInvalidPermissions(permissionStatus); | ||
| 41 | + // } | ||
| 42 | + // } | ||
| 43 | + | ||
| 44 | + _openAddressBook() async { | ||
| 45 | + if (!(await checkContactPermission())) { | ||
| 46 | + PermissionStatus permissionStatus = await contactPermissionStatus(); | ||
| 47 | + if (permissionStatus == PermissionStatus.permanentlyDenied) { | ||
| 48 | + //用户选择不在弹出权限提示框 | ||
| 49 | + print('never'); | ||
| 50 | + userNo = true; | ||
| 51 | + setState(() { | ||
| 52 | + _pageState = PageState.NoPermission; | ||
| 53 | + }); | ||
| 54 | + // DialogUtil.openAlertDialog( | ||
| 55 | + // context, '未获得通讯录权限', "请在手机的权限管理里,将通讯录权限开启", '去设置', 340.0, | ||
| 56 | + // onTap: () { | ||
| 57 | + // goSetting = true; | ||
| 58 | + // openSetting(); | ||
| 59 | + // Navigator.pop(context, ''); | ||
| 60 | + // }); | ||
| 61 | + } else { | ||
| 62 | + // 申请权限 | ||
| 63 | + bool canContacts = await requestContactPermission(); | ||
| 64 | + if (canContacts) { | ||
| 65 | + refreshContacts(); | ||
| 66 | + } else { | ||
| 67 | + setState(() { | ||
| 68 | + _pageState = PageState.NoPermission; | ||
| 69 | + }); | ||
| 70 | + //拒绝通讯录权限 , 苹果拒绝权限后,不再提示权限框,进入此处 | ||
| 71 | + // DialogUtil.openAlertDialog( | ||
| 72 | + // context, '未获得通讯录权限', "请在手机的权限管理里,将通讯录权限开启。", '去设置', 340.0, | ||
| 73 | + // onTap: () { | ||
| 74 | + // goSetting = true; | ||
| 75 | + // openSetting(); | ||
| 76 | + // Navigator.pop(context, ''); | ||
| 77 | + // }); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + } else { | ||
| 81 | + refreshContacts(); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + // Future<PermissionStatus> _getContactPermission() async { | ||
| 86 | + // PermissionStatus permission = await PermissionHandler() | ||
| 87 | + // .checkPermissionStatus(PermissionGroup.contacts); | ||
| 88 | + // if (permission != PermissionStatus.granted && | ||
| 89 | + // permission != PermissionStatus.disabled) { | ||
| 90 | + // Map<PermissionGroup, PermissionStatus> permissionStatus = | ||
| 91 | + // await PermissionHandler() | ||
| 92 | + // .requestPermissions([PermissionGroup.contacts]); | ||
| 93 | + // return permissionStatus[PermissionGroup.contacts] ?? | ||
| 94 | + // PermissionStatus.unknown; | ||
| 95 | + // } else { | ||
| 96 | + // return permission; | ||
| 97 | + // } | ||
| 98 | + // } | ||
| 99 | + | ||
| 100 | + // void _handleInvalidPermissions(PermissionStatus permissionStatus) { | ||
| 101 | + // if (permissionStatus == PermissionStatus.denied) { | ||
| 102 | + // throw PlatformException( | ||
| 103 | + // code: "PERMISSION_DENIED", | ||
| 104 | + // message: "Access to location data denied", | ||
| 105 | + // details: null); | ||
| 106 | + // } else if (permissionStatus == PermissionStatus.disabled) { | ||
| 107 | + // throw PlatformException( | ||
| 108 | + // code: "PERMISSION_DISABLED", | ||
| 109 | + // message: "Location data is not available on device", | ||
| 110 | + // details: null); | ||
| 111 | + // } | ||
| 112 | + // } | ||
| 113 | + | ||
| 114 | + Future<void> refreshContacts() async { | ||
| 115 | + // Load without thumbnails initially. | ||
| 116 | + var contacts = (await ContactsService.getContacts( | ||
| 117 | + withThumbnails: false, iOSLocalizedLabels: false)) | ||
| 118 | + .toList(); | ||
| 119 | +// var contacts = (await ContactsService.getContactsForPhone("8554964652")) | ||
| 120 | +// .toList(); | ||
| 121 | + setState(() { | ||
| 122 | + _contacts = contacts; | ||
| 123 | + if (_contacts.length > 0) { | ||
| 124 | + _pageState = PageState.Success; | ||
| 125 | + } else { | ||
| 126 | + _pageState = PageState.Empty; | ||
| 127 | + } | ||
| 128 | + }); | ||
| 129 | + | ||
| 130 | + // Lazy load thumbnails after rendering initial contacts. | ||
| 131 | + for (final contact in contacts) { | ||
| 132 | + ContactsService.getAvatar(contact).then((avatar) { | ||
| 133 | + if (avatar == null) return; // Don't redraw if no change. | ||
| 134 | + setState(() => contact.avatar = avatar); | ||
| 135 | + }); | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + void updateContact() async { | ||
| 140 | + Contact ninja = _contacts | ||
| 141 | + .toList() | ||
| 142 | + .firstWhere((contact) => contact.familyName.startsWith("Ninja")); | ||
| 143 | + ninja.avatar = null; | ||
| 144 | + await ContactsService.updateContact(ninja); | ||
| 145 | + | ||
| 146 | + refreshContacts(); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + _openContactForm() async { | ||
| 150 | + try { | ||
| 151 | + var contact = | ||
| 152 | + await ContactsService.openContactForm(iOSLocalizedLabels: false); | ||
| 153 | + refreshContacts(); | ||
| 154 | + } on FormOperationException catch (e) { | ||
| 155 | + switch (e.errorCode) { | ||
| 156 | + case FormOperationErrorCode.FORM_OPERATION_CANCELED: | ||
| 157 | + case FormOperationErrorCode.FORM_COULD_NOT_BE_OPEN: | ||
| 158 | + case FormOperationErrorCode.FORM_OPERATION_UNKNOWN_ERROR: | ||
| 159 | + default: | ||
| 160 | + print(e.errorCode); | ||
| 161 | + } | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + // /// app生命周期 | ||
| 166 | + // @override | ||
| 167 | + // void didChangeAppLifecycleState(AppLifecycleState state) async { | ||
| 168 | + // switch (state) { | ||
| 169 | + // case AppLifecycleState.resumed: // 应用程序可见,前台 | ||
| 170 | + // if (!Platform.isAndroid) { | ||
| 171 | + // if (isNeed) { | ||
| 172 | + // isNeed = false; | ||
| 173 | + // if (goSetting) { | ||
| 174 | + // _getContactPemisoin(); | ||
| 175 | + // } | ||
| 176 | + // } | ||
| 177 | + // } else { | ||
| 178 | + // if (goSetting) { | ||
| 179 | + // _getContactPemisoin(); | ||
| 180 | + // } | ||
| 181 | + // } | ||
| 182 | + // break; | ||
| 183 | + // case AppLifecycleState.paused: | ||
| 184 | + // print('paused'); | ||
| 185 | + // // if (!Platform.isAndroid) { | ||
| 186 | + // // if (!(await checkLocationPermission())) { | ||
| 187 | + // // //没有定位权限 | ||
| 188 | + // isNeed = true; | ||
| 189 | + // // } else { | ||
| 190 | + // // isNeed = false; | ||
| 191 | + // // } | ||
| 192 | + // // } | ||
| 193 | + | ||
| 194 | + // break; | ||
| 195 | + // default: | ||
| 196 | + // break; | ||
| 197 | + // } | ||
| 198 | + // } | ||
| 199 | + | ||
| 200 | + /// 程序进入前台刷新位置权限(来回切换位置权限,及时刷新页面) | ||
| 201 | + _getContactPemisoin() async { | ||
| 202 | + if (await checkContactPermission()) { | ||
| 203 | + userNo = false; | ||
| 204 | + } | ||
| 205 | + if (!userNo) { | ||
| 206 | + goSetting = false; | ||
| 207 | + _openAddressBook(); | ||
| 208 | + } | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + @override | ||
| 212 | + Widget build(BuildContext context) { | ||
| 213 | + return _pageState != PageState.Success | ||
| 214 | + ? ExceptionPage( | ||
| 215 | + pageState: _pageState, | ||
| 216 | + callback: () async { | ||
| 217 | + if (await checkContactPermission()) { | ||
| 218 | + _openAddressBook(); | ||
| 219 | + } else { | ||
| 220 | + goSetting = true; | ||
| 221 | + openSetting(); | ||
| 222 | + } | ||
| 223 | + ; | ||
| 224 | + }, | ||
| 225 | + emptyMsg: "暂时没有联系人哦", | ||
| 226 | + emptyImg: "empty_search", | ||
| 227 | + showMsg: "加载中,请稍后...", | ||
| 228 | + ) | ||
| 229 | + : ListView.builder( | ||
| 230 | + itemCount: _contacts?.length ?? 0, | ||
| 231 | + itemBuilder: (BuildContext context, int index) { | ||
| 232 | + Contact c = _contacts?.elementAt(index); | ||
| 233 | + return Column( | ||
| 234 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 235 | + children: [ | ||
| 236 | + index == 0 | ||
| 237 | + ? MyDivider( | ||
| 238 | + double.infinity, | ||
| 239 | + ScreenUtil().setWidth(20), | ||
| 240 | + color: MyColours.color_f5f5f5, | ||
| 241 | + ) | ||
| 242 | + : Container(), | ||
| 243 | + Container( | ||
| 244 | + width: double.infinity, | ||
| 245 | + padding: EdgeInsets.symmetric( | ||
| 246 | + horizontal: ScreenUtil().setWidth(40), | ||
| 247 | + vertical: ScreenUtil().setWidth(30)), | ||
| 248 | + height: ScreenUtil().setWidth(74 * 2), | ||
| 249 | + decoration: BoxDecoration( | ||
| 250 | + border: Border( | ||
| 251 | + top: index == 0 | ||
| 252 | + ? BorderSide( | ||
| 253 | + width: ScreenUtil().setWidth(2), | ||
| 254 | + color: MyColours.color_E0E0E0) | ||
| 255 | + : BorderSide( | ||
| 256 | + width: 0, color: Colors.transparent), | ||
| 257 | + bottom: BorderSide( | ||
| 258 | + width: ScreenUtil().setWidth(2), | ||
| 259 | + color: MyColours.color_E0E0E0))), | ||
| 260 | + child: Column( | ||
| 261 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 262 | + children: [ | ||
| 263 | + Text(c.displayName, | ||
| 264 | + style: TextStyle( | ||
| 265 | + color: MyColours.color_333333, | ||
| 266 | + fontSize: ScreenUtil().setSp(32))), | ||
| 267 | + VEmptyView(10), | ||
| 268 | + Text(c.phones.first.value, | ||
| 269 | + style: TextStyle( | ||
| 270 | + color: MyColours.color_999999, | ||
| 271 | + fontSize: ScreenUtil().setSp(30))) | ||
| 272 | + ], | ||
| 273 | + ), | ||
| 274 | + ) | ||
| 275 | + ]); | ||
| 276 | + }); | ||
| 277 | + } | ||
| 278 | +} |
| @@ -3,54 +3,73 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; | @@ -3,54 +3,73 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 3 | import 'package:one_key/res/colors.dart'; | 3 | import 'package:one_key/res/colors.dart'; |
| 4 | import 'package:one_key/widgets/v_empty_view.dart'; | 4 | import 'package:one_key/widgets/v_empty_view.dart'; |
| 5 | 5 | ||
| 6 | -class ErrorPage extends StatefulWidget{ | ||
| 7 | - | 6 | +class ErrorPage extends StatefulWidget { |
| 8 | final String content; | 7 | final String content; |
| 9 | 8 | ||
| 9 | + final String btnTitle; | ||
| 10 | + | ||
| 10 | final VoidCallback callback; | 11 | final VoidCallback callback; |
| 11 | 12 | ||
| 12 | - const ErrorPage({Key key, this.callback,this.content="哎呀~网络好像走失了呢"}) : super(key: key); | ||
| 13 | - | 13 | + const ErrorPage( |
| 14 | + {Key key, | ||
| 15 | + this.callback, | ||
| 16 | + this.content = "哎呀~网络好像走失了呢", | ||
| 17 | + this.btnTitle = '点击刷新'}) | ||
| 18 | + : super(key: key); | ||
| 19 | + | ||
| 14 | @override | 20 | @override |
| 15 | State<StatefulWidget> createState() { | 21 | State<StatefulWidget> createState() { |
| 16 | // TODO: implement createState | 22 | // TODO: implement createState |
| 17 | return new ErrorPageState(); | 23 | return new ErrorPageState(); |
| 18 | } | 24 | } |
| 19 | - | ||
| 20 | } | 25 | } |
| 21 | 26 | ||
| 22 | -class ErrorPageState extends State<ErrorPage>{ | 27 | +class ErrorPageState extends State<ErrorPage> { |
| 23 | @override | 28 | @override |
| 24 | Widget build(BuildContext context) { | 29 | Widget build(BuildContext context) { |
| 25 | // TODO: implement build | 30 | // TODO: implement build |
| 26 | return Container( | 31 | return Container( |
| 27 | - width: double.infinity, | ||
| 28 | - height: double.infinity, | ||
| 29 | - child: Column( | ||
| 30 | - mainAxisSize: MainAxisSize.min, | ||
| 31 | - children: <Widget>[ | ||
| 32 | - VEmptyView(120), | ||
| 33 | - Image.asset("assets/bg_error.png",width: ScreenUtil().setWidth(520),height: ScreenUtil().setWidth(384),), | ||
| 34 | - VEmptyView(40), | ||
| 35 | - Text("${widget.content}",style: TextStyle(fontSize: ScreenUtil().setSp(28),color: MyColours.color_353535),), | ||
| 36 | - VEmptyView(20), | ||
| 37 | - widget.callback!=null?GestureDetector( | ||
| 38 | - onTap: widget.callback, | ||
| 39 | - child: Container( | ||
| 40 | - width: ScreenUtil().setWidth(152), | ||
| 41 | - height: ScreenUtil().setWidth(58), | ||
| 42 | - decoration: BoxDecoration( | ||
| 43 | - color: MyColours.app_main, | ||
| 44 | - borderRadius: BorderRadius.all(Radius.circular(ScreenUtil().setWidth(28))) | ||
| 45 | - ), | ||
| 46 | - child: Center( | ||
| 47 | - child: Text("点击刷新",style: TextStyle(fontSize: ScreenUtil().setSp(28),color: MyColours.color_ffffff),), | ||
| 48 | - ), | 32 | + width: double.infinity, |
| 33 | + height: double.infinity, | ||
| 34 | + child: Column( | ||
| 35 | + mainAxisSize: MainAxisSize.min, | ||
| 36 | + children: <Widget>[ | ||
| 37 | + VEmptyView(120), | ||
| 38 | + Image.asset( | ||
| 39 | + "assets/bg_error.png", | ||
| 40 | + width: ScreenUtil().setWidth(520), | ||
| 41 | + height: ScreenUtil().setWidth(384), | ||
| 42 | + ), | ||
| 43 | + VEmptyView(40), | ||
| 44 | + Text( | ||
| 45 | + "${widget.content}", | ||
| 46 | + style: TextStyle( | ||
| 47 | + fontSize: ScreenUtil().setSp(28), | ||
| 48 | + color: MyColours.color_353535), | ||
| 49 | ), | 49 | ), |
| 50 | - ):Container() | ||
| 51 | - ], | ||
| 52 | - ) | ||
| 53 | - ); | 50 | + VEmptyView(20), |
| 51 | + widget.callback != null | ||
| 52 | + ? GestureDetector( | ||
| 53 | + onTap: widget.callback, | ||
| 54 | + child: Container( | ||
| 55 | + width: ScreenUtil().setWidth(152), | ||
| 56 | + height: ScreenUtil().setWidth(58), | ||
| 57 | + decoration: BoxDecoration( | ||
| 58 | + color: MyColours.app_main, | ||
| 59 | + borderRadius: BorderRadius.all( | ||
| 60 | + Radius.circular(ScreenUtil().setWidth(28)))), | ||
| 61 | + child: Center( | ||
| 62 | + child: Text( | ||
| 63 | + widget.btnTitle, | ||
| 64 | + style: TextStyle( | ||
| 65 | + fontSize: ScreenUtil().setSp(28), | ||
| 66 | + color: MyColours.color_ffffff), | ||
| 67 | + ), | ||
| 68 | + ), | ||
| 69 | + ), | ||
| 70 | + ) | ||
| 71 | + : Container() | ||
| 72 | + ], | ||
| 73 | + )); | ||
| 54 | } | 74 | } |
| 55 | - | ||
| 56 | } | 75 | } |
| @@ -69,6 +69,13 @@ class ExceptionPageState extends State<ExceptionPage> { | @@ -69,6 +69,13 @@ class ExceptionPageState extends State<ExceptionPage> { | ||
| 69 | color: Colors.white, | 69 | color: Colors.white, |
| 70 | ); | 70 | ); |
| 71 | break; | 71 | break; |
| 72 | + case PageState.NoPermission: | ||
| 73 | + page = ErrorPage( | ||
| 74 | + content: "未获取到通讯录权限", | ||
| 75 | + callback: widget.callback, | ||
| 76 | + btnTitle: '开启权限', | ||
| 77 | + ); | ||
| 78 | + break; | ||
| 72 | default: | 79 | default: |
| 73 | page = ErrorPage( | 80 | page = ErrorPage( |
| 74 | content: "哎呀~网络好像走失了呢", | 81 | content: "哎呀~网络好像走失了呢", |
-
Please register or login to post a comment