Showing
15 changed files
with
581 additions
and
339 deletions
| ... | @@ -4,13 +4,16 @@ import 'package:Parlando/generated/json/user_entity.g.dart'; | ... | @@ -4,13 +4,16 @@ import 'package:Parlando/generated/json/user_entity.g.dart'; |
| 4 | 4 | ||
| 5 | @JsonSerializable() | 5 | @JsonSerializable() |
| 6 | class UserEntity { | 6 | class UserEntity { |
| 7 | - late int id; | 7 | + String? status; |
| 8 | - late String name; | 8 | + int? code; |
| 9 | - late String avatar; | 9 | + String? message; |
| 10 | + UserData? data; | ||
| 11 | + UserError? error; | ||
| 10 | 12 | ||
| 11 | UserEntity(); | 13 | UserEntity(); |
| 12 | 14 | ||
| 13 | - factory UserEntity.fromJson(Map<String, dynamic> json) => $UserEntityFromJson(json); | 15 | + factory UserEntity.fromJson(Map<String, dynamic> json) => |
| 16 | + $UserEntityFromJson(json); | ||
| 14 | 17 | ||
| 15 | Map<String, dynamic> toJson() => $UserEntityToJson(this); | 18 | Map<String, dynamic> toJson() => $UserEntityToJson(this); |
| 16 | 19 | ||
| ... | @@ -18,4 +21,49 @@ class UserEntity { | ... | @@ -18,4 +21,49 @@ class UserEntity { |
| 18 | String toString() { | 21 | String toString() { |
| 19 | return jsonEncode(this); | 22 | return jsonEncode(this); |
| 20 | } | 23 | } |
| 24 | +} | ||
| 25 | + | ||
| 26 | +@JsonSerializable() | ||
| 27 | +class UserData { | ||
| 28 | + int? id; | ||
| 29 | + dynamic nickname; | ||
| 30 | + dynamic mobile; | ||
| 31 | + String? email; | ||
| 32 | + String? avatar; | ||
| 33 | + String? gender; | ||
| 34 | + dynamic provider; | ||
| 35 | + @JSONField(name: "provider_id") | ||
| 36 | + dynamic providerId; | ||
| 37 | + String? state; | ||
| 38 | + @JSONField(name: "created_at") | ||
| 39 | + String? createdAt; | ||
| 40 | + @JSONField(name: "updated_at") | ||
| 41 | + String? updatedAt; | ||
| 42 | + | ||
| 43 | + UserData(); | ||
| 44 | + | ||
| 45 | + factory UserData.fromJson(Map<String, dynamic> json) => | ||
| 46 | + $UserDataFromJson(json); | ||
| 47 | + | ||
| 48 | + Map<String, dynamic> toJson() => $UserDataToJson(this); | ||
| 49 | + | ||
| 50 | + @override | ||
| 51 | + String toString() { | ||
| 52 | + return jsonEncode(this); | ||
| 53 | + } | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +@JsonSerializable() | ||
| 57 | +class UserError { | ||
| 58 | + UserError(); | ||
| 59 | + | ||
| 60 | + factory UserError.fromJson(Map<String, dynamic> json) => | ||
| 61 | + $UserErrorFromJson(json); | ||
| 62 | + | ||
| 63 | + Map<String, dynamic> toJson() => $UserErrorToJson(this); | ||
| 64 | + | ||
| 65 | + @override | ||
| 66 | + String toString() { | ||
| 67 | + return jsonEncode(this); | ||
| 68 | + } | ||
| 21 | } | 69 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | -import 'package:Parlando/net/dio_utils.dart'; | 1 | +import 'package:Parlando/account/models/user_entity.dart'; |
| 2 | -import 'package:Parlando/net/http_api.dart'; | 2 | +import 'package:Parlando/account/view_models/account_view_model.dart'; |
| 3 | +import 'package:Parlando/apis/api_response.dart'; | ||
| 4 | +import 'package:Parlando/login/login_router.dart'; | ||
| 3 | import 'package:Parlando/res/constant.dart'; | 5 | import 'package:Parlando/res/constant.dart'; |
| 4 | -import 'package:Parlando/util/toast_utils.dart'; | 6 | +import 'package:flustars/flustars.dart'; |
| 5 | import 'package:flutter/material.dart'; | 7 | import 'package:flutter/material.dart'; |
| 6 | import 'package:Parlando/membership/membership_router.dart'; | 8 | import 'package:Parlando/membership/membership_router.dart'; |
| 7 | import 'package:Parlando/poem/poem_router.dart'; | 9 | import 'package:Parlando/poem/poem_router.dart'; |
| 8 | import 'package:Parlando/routers/fluro_navigator.dart'; | 10 | import 'package:Parlando/routers/fluro_navigator.dart'; |
| 9 | import 'package:Parlando/setting/setting_router.dart'; | 11 | import 'package:Parlando/setting/setting_router.dart'; |
| 10 | import 'package:Parlando/tiktok/style/style.dart'; | 12 | import 'package:Parlando/tiktok/style/style.dart'; |
| 13 | +import 'package:provider/provider.dart'; | ||
| 11 | import 'package:tapped/tapped.dart'; | 14 | import 'package:tapped/tapped.dart'; |
| 12 | import 'package:flutter_gen/gen_l10n/Parlando_localizations.dart'; | 15 | import 'package:flutter_gen/gen_l10n/Parlando_localizations.dart'; |
| 13 | 16 | ||
| ... | @@ -38,207 +41,221 @@ class _AccountPageState extends State<AccountPage> { | ... | @@ -38,207 +41,221 @@ class _AccountPageState extends State<AccountPage> { |
| 38 | void initState() { | 41 | void initState() { |
| 39 | super.initState(); | 42 | super.initState(); |
| 40 | 43 | ||
| 41 | - //todo MVVM? | 44 | + if (SpUtil.containsKey(Constant.userToken)!) { |
| 42 | - Map<String, String> params = <String, String>{ | 45 | + Provider.of<AccountViewProvider>(context, listen: false) |
| 43 | - "profile": "1", | 46 | + .setSelectedAccount(null); |
| 44 | - }; | 47 | + Provider.of<AccountViewProvider>(context, listen: false) |
| 45 | - DioUtils.instance.asyncRequestNetwork( | 48 | + .fetchAccountData('0'); |
| 46 | - Method.post, | 49 | + } else { |
| 47 | - HttpApi.login, | 50 | + NavigatorUtils.push(context, LoginRouter.loginPage, replace: true); |
| 48 | - queryParameters: params, | 51 | + } |
| 49 | - onSuccess: (data) {}, | ||
| 50 | - onError: (code, msg) { | ||
| 51 | - Toast.show(msg.toString()); | ||
| 52 | - }, | ||
| 53 | - ); | ||
| 54 | } | 52 | } |
| 55 | 53 | ||
| 56 | @override | 54 | @override |
| 57 | Widget build(BuildContext context) { | 55 | Widget build(BuildContext context) { |
| 58 | - Widget likeButton = Container( | 56 | + ApiResponse apiResponse = |
| 59 | - color: ColorPlate.white, | 57 | + Provider.of<AccountViewProvider>(context).response; |
| 60 | - child: Row( | 58 | + switch (apiResponse.status) { |
| 61 | - crossAxisAlignment: CrossAxisAlignment.start, | 59 | + case Status.LOADING: |
| 62 | - mainAxisAlignment: MainAxisAlignment.end, | 60 | + return const Center(child: CircularProgressIndicator()); |
| 63 | - children: <Widget>[ | 61 | + case Status.COMPLETED: |
| 64 | - Tapped( | 62 | + UserData _user = apiResponse.data as UserData; |
| 65 | - onTap: () { | 63 | + Widget likeButton = Container( |
| 66 | - NavigatorUtils.push(context, MembershipRouter.membershipPage); | 64 | + color: ColorPlate.white, |
| 67 | - }, | 65 | + child: Row( |
| 68 | - child: const _MembershipButton( | 66 | + crossAxisAlignment: CrossAxisAlignment.start, |
| 69 | - title: '会员中心', | 67 | + mainAxisAlignment: MainAxisAlignment.end, |
| 70 | - ), | 68 | + children: <Widget>[ |
| 69 | + Tapped( | ||
| 70 | + onTap: () { | ||
| 71 | + NavigatorUtils.push(context, MembershipRouter.membershipPage); | ||
| 72 | + }, | ||
| 73 | + child: const _MembershipButton( | ||
| 74 | + title: '会员中心', | ||
| 75 | + ), | ||
| 76 | + ), | ||
| 77 | + ], | ||
| 71 | ), | 78 | ), |
| 72 | - ], | 79 | + ); |
| 73 | - ), | 80 | + Widget avatar = Container( |
| 74 | - ); | 81 | + height: 120.px + MediaQuery.of(context).padding.top, |
| 75 | - Widget avatar = Container( | 82 | + padding: EdgeInsets.only(left: 18.px), |
| 76 | - height: 120.px + MediaQuery.of(context).padding.top, | 83 | + alignment: Alignment.bottomLeft, |
| 77 | - padding: EdgeInsets.only(left: 18.px), | 84 | + child: OverflowBox( |
| 78 | - alignment: Alignment.bottomLeft, | 85 | + alignment: Alignment.bottomLeft, |
| 79 | - child: OverflowBox( | 86 | + minHeight: 20.px, |
| 80 | - alignment: Alignment.bottomLeft, | 87 | + maxHeight: 300.px, |
| 81 | - minHeight: 20.px, | 88 | + child: Container( |
| 82 | - maxHeight: 300.px, | 89 | + height: 74.px, |
| 83 | - child: Container( | 90 | + width: 74.px, |
| 84 | - height: 74.px, | 91 | + margin: EdgeInsets.only(bottom: 12.px), |
| 85 | - width: 74.px, | 92 | + decoration: BoxDecoration( |
| 86 | - margin: EdgeInsets.only(bottom: 12.px), | 93 | + borderRadius: BorderRadius.circular(44.px), |
| 87 | - decoration: BoxDecoration( | 94 | + color: Colors.orange, |
| 88 | - borderRadius: BorderRadius.circular(44.px), | 95 | + border: Border.all( |
| 89 | - color: Colors.orange, | 96 | + color: Colors.white, |
| 90 | - border: Border.all( | 97 | + width: 1.px, |
| 91 | - color: Colors.white, | 98 | + ), |
| 92 | - width: 1.px, | 99 | + ), |
| 100 | + child: ClipOval( | ||
| 101 | + child: Image.network( | ||
| 102 | + "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif", | ||
| 103 | + fit: BoxFit.cover, | ||
| 104 | + ), | ||
| 105 | + ), | ||
| 93 | ), | 106 | ), |
| 94 | ), | 107 | ), |
| 95 | - child: ClipOval( | 108 | + ); |
| 96 | - child: Image.network( | 109 | + Widget body = ListView( |
| 97 | - "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif", | 110 | + physics: const BouncingScrollPhysics( |
| 98 | - fit: BoxFit.cover, | 111 | + parent: AlwaysScrollableScrollPhysics(), |
| 99 | - ), | ||
| 100 | ), | 112 | ), |
| 101 | - ), | ||
| 102 | - ), | ||
| 103 | - ); | ||
| 104 | - Widget body = ListView( | ||
| 105 | - physics: const BouncingScrollPhysics( | ||
| 106 | - parent: AlwaysScrollableScrollPhysics(), | ||
| 107 | - ), | ||
| 108 | - children: <Widget>[ | ||
| 109 | - Stack( | ||
| 110 | - alignment: Alignment.bottomLeft, | ||
| 111 | children: <Widget>[ | 113 | children: <Widget>[ |
| 112 | - likeButton, | 114 | + Stack( |
| 113 | - avatar, | 115 | + alignment: Alignment.bottomLeft, |
| 114 | - Positioned( | 116 | + children: <Widget>[ |
| 115 | - child: GestureDetector( | 117 | + likeButton, |
| 116 | - child: CircleAvatar( | 118 | + avatar, |
| 117 | - backgroundColor: Colors.red.withOpacity(0.4), | 119 | + Positioned( |
| 118 | - radius: 14.px, | 120 | + child: GestureDetector( |
| 119 | - child: Icon( | 121 | + child: CircleAvatar( |
| 120 | - Icons.edit, | 122 | + backgroundColor: Colors.red.withOpacity(0.4), |
| 121 | - color: Colors.white, | 123 | + radius: 14.px, |
| 122 | - size: 16.px, | 124 | + child: Icon( |
| 125 | + Icons.edit, | ||
| 126 | + color: Colors.white, | ||
| 127 | + size: 16.px, | ||
| 128 | + ), | ||
| 129 | + ), | ||
| 130 | + onTap: () { | ||
| 131 | + NavigatorUtils.push( | ||
| 132 | + context, AccountRouter.accountEditPage); | ||
| 133 | + }, | ||
| 123 | ), | 134 | ), |
| 135 | + left: 64.px, | ||
| 136 | + bottom: 10.px, | ||
| 124 | ), | 137 | ), |
| 125 | - onTap: () { | 138 | + ], |
| 126 | - NavigatorUtils.push(context, AccountRouter.accountEditPage); | ||
| 127 | - }, | ||
| 128 | - ), | ||
| 129 | - left: 64.px, | ||
| 130 | - bottom: 10.px, | ||
| 131 | ), | 139 | ), |
| 132 | - ], | 140 | + Container( |
| 133 | - ), | 141 | + color: ColorPlate.white, |
| 134 | - Container( | 142 | + child: Column( |
| 135 | - color: ColorPlate.white, | 143 | + children: <Widget>[ |
| 136 | - child: Column( | 144 | + Container( |
| 137 | - children: <Widget>[ | 145 | + padding: EdgeInsets.only(left: 18.px), |
| 138 | - Container( | 146 | + color: ColorPlate.white, |
| 139 | - padding: EdgeInsets.only(left: 18.px), | 147 | + child: Column( |
| 140 | - color: ColorPlate.white, | 148 | + crossAxisAlignment: CrossAxisAlignment.start, |
| 141 | - child: Column( | 149 | + children: <Widget>[ |
| 142 | - crossAxisAlignment: CrossAxisAlignment.start, | 150 | + Text( |
| 143 | - children: <Widget>[ | 151 | + _user.email ?? '@唐宋八大家TOP8', |
| 144 | - const Text( | 152 | + style: StandardTextStyle.big, |
| 145 | - '@唐宋八大家TOP8', | 153 | + ), |
| 146 | - style: StandardTextStyle.big, | 154 | + Container(height: 8.px), |
| 155 | + Text( | ||
| 156 | + '朴实无华,且枯燥', | ||
| 157 | + style: StandardTextStyle.small.apply( | ||
| 158 | + color: Colors.black45, | ||
| 159 | + ), | ||
| 160 | + ), | ||
| 161 | + Container(height: 10.px), | ||
| 162 | + Row( | ||
| 163 | + children: const <Widget>[ | ||
| 164 | + _UserTag(tag: '幽默'), | ||
| 165 | + _UserTag(tag: '机智'), | ||
| 166 | + _UserTag(tag: '枯燥'), | ||
| 167 | + _UserTag(tag: '狮子座'), | ||
| 168 | + ], | ||
| 169 | + ), | ||
| 170 | + Container(height: 10.px), | ||
| 171 | + ], | ||
| 147 | ), | 172 | ), |
| 148 | - Container(height: 8.px), | 173 | + ), |
| 149 | - Text( | 174 | + Container( |
| 150 | - '朴实无华,且枯燥', | 175 | + color: ColorPlate.white, |
| 151 | - style: StandardTextStyle.small.apply( | 176 | + padding: EdgeInsets.symmetric( |
| 152 | - color: Colors.black45, | 177 | + horizontal: 8.px, |
| 153 | - ), | 178 | + vertical: 2.px, |
| 154 | ), | 179 | ), |
| 155 | - Container(height: 10.px), | 180 | + child: Row( |
| 156 | - Row( | 181 | + mainAxisAlignment: MainAxisAlignment.start, |
| 182 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 157 | children: const <Widget>[ | 183 | children: const <Widget>[ |
| 158 | - _UserTag(tag: '幽默'), | 184 | + TextGroup('356', '关注'), |
| 159 | - _UserTag(tag: '机智'), | 185 | + TextGroup('145万', '粉丝'), |
| 160 | - _UserTag(tag: '枯燥'), | 186 | + TextGroup('1423万', '获赞'), |
| 161 | - _UserTag(tag: '狮子座'), | ||
| 162 | ], | 187 | ], |
| 163 | ), | 188 | ), |
| 164 | - Container(height: 10.px), | ||
| 165 | - ], | ||
| 166 | - ), | ||
| 167 | - ), | ||
| 168 | - Container( | ||
| 169 | - color: ColorPlate.white, | ||
| 170 | - padding: EdgeInsets.symmetric( | ||
| 171 | - horizontal: 8.px, | ||
| 172 | - vertical: 2.px, | ||
| 173 | - ), | ||
| 174 | - child: Row( | ||
| 175 | - mainAxisAlignment: MainAxisAlignment.start, | ||
| 176 | - crossAxisAlignment: CrossAxisAlignment.center, | ||
| 177 | - children: const <Widget>[ | ||
| 178 | - TextGroup('356', '关注'), | ||
| 179 | - TextGroup('145万', '粉丝'), | ||
| 180 | - TextGroup('1423万', '获赞'), | ||
| 181 | - ], | ||
| 182 | - ), | ||
| 183 | - ), | ||
| 184 | - Container( | ||
| 185 | - height: 10.px, | ||
| 186 | - margin: const EdgeInsets.symmetric(horizontal: 12), | ||
| 187 | - decoration: BoxDecoration( | ||
| 188 | - border: Border( | ||
| 189 | - bottom: BorderSide( | ||
| 190 | - color: Colors.white.withOpacity(0.1), | ||
| 191 | - ), | ||
| 192 | ), | 189 | ), |
| 193 | - ), | 190 | + Container( |
| 194 | - ), | 191 | + height: 10.px, |
| 195 | - const _UserVideoTable(), | 192 | + margin: const EdgeInsets.symmetric(horizontal: 12), |
| 196 | - ], | 193 | + decoration: BoxDecoration( |
| 197 | - ), | 194 | + border: Border( |
| 198 | - ), | 195 | + bottom: BorderSide( |
| 199 | - ], | 196 | + color: Colors.white.withOpacity(0.1), |
| 200 | - ); | 197 | + ), |
| 201 | - return Scaffold( | 198 | + ), |
| 202 | - body: Container( | ||
| 203 | - decoration: const BoxDecoration( | ||
| 204 | - image: DecorationImage( | ||
| 205 | - image: AssetImage("assets/images/poem/poem_background.png"), | ||
| 206 | - fit: BoxFit.fill, | ||
| 207 | - ), | ||
| 208 | - ), | ||
| 209 | - child: Stack( | ||
| 210 | - alignment: Alignment.topCenter, | ||
| 211 | - children: <Widget>[ | ||
| 212 | - Container( | ||
| 213 | - margin: const EdgeInsets.only(top: 500), | ||
| 214 | - height: double.infinity, | ||
| 215 | - width: double.infinity, | ||
| 216 | - color: ColorPlate.white, | ||
| 217 | - ), | ||
| 218 | - body, | ||
| 219 | - Container( | ||
| 220 | - alignment: Alignment.centerRight, | ||
| 221 | - height: 64.px, | ||
| 222 | - width: double.infinity, | ||
| 223 | - child: Row( | ||
| 224 | - mainAxisAlignment: MainAxisAlignment.end, | ||
| 225 | - children: [ | ||
| 226 | - IconButton( | ||
| 227 | - icon: const Icon( | ||
| 228 | - Icons.settings_outlined, | ||
| 229 | - color: Colors.black54, | ||
| 230 | ), | 199 | ), |
| 231 | - onPressed: () { | ||
| 232 | - NavigatorUtils.push(context, SettingRouter.settingPage); | ||
| 233 | - }, | ||
| 234 | ), | 200 | ), |
| 201 | + const _UserVideoTable(), | ||
| 235 | ], | 202 | ], |
| 236 | ), | 203 | ), |
| 237 | ), | 204 | ), |
| 238 | ], | 205 | ], |
| 239 | - ), | 206 | + ); |
| 240 | - ), | 207 | + return Scaffold( |
| 241 | - ); | 208 | + body: Container( |
| 209 | + decoration: const BoxDecoration( | ||
| 210 | + image: DecorationImage( | ||
| 211 | + image: AssetImage("assets/images/poem/poem_background.png"), | ||
| 212 | + fit: BoxFit.fill, | ||
| 213 | + ), | ||
| 214 | + ), | ||
| 215 | + child: Stack( | ||
| 216 | + alignment: Alignment.topCenter, | ||
| 217 | + children: <Widget>[ | ||
| 218 | + Container( | ||
| 219 | + margin: const EdgeInsets.only(top: 500), | ||
| 220 | + height: double.infinity, | ||
| 221 | + width: double.infinity, | ||
| 222 | + color: ColorPlate.white, | ||
| 223 | + ), | ||
| 224 | + body, | ||
| 225 | + Container( | ||
| 226 | + alignment: Alignment.centerRight, | ||
| 227 | + height: 64.px, | ||
| 228 | + width: double.infinity, | ||
| 229 | + child: Row( | ||
| 230 | + mainAxisAlignment: MainAxisAlignment.end, | ||
| 231 | + children: [ | ||
| 232 | + IconButton( | ||
| 233 | + icon: const Icon( | ||
| 234 | + Icons.settings_outlined, | ||
| 235 | + color: Colors.black54, | ||
| 236 | + ), | ||
| 237 | + onPressed: () { | ||
| 238 | + NavigatorUtils.push( | ||
| 239 | + context, SettingRouter.settingPage); | ||
| 240 | + }, | ||
| 241 | + ), | ||
| 242 | + ], | ||
| 243 | + ), | ||
| 244 | + ), | ||
| 245 | + ], | ||
| 246 | + ), | ||
| 247 | + ), | ||
| 248 | + ); | ||
| 249 | + case Status.ERROR: | ||
| 250 | + return Center( | ||
| 251 | + child: Text('暂时无法获取数据,请稍候再试!' + apiResponse.message.toString()), | ||
| 252 | + ); | ||
| 253 | + case Status.INITIAL: | ||
| 254 | + default: | ||
| 255 | + return const Center( | ||
| 256 | + child: Text('正在获取数据....'), | ||
| 257 | + ); | ||
| 258 | + } | ||
| 242 | } | 259 | } |
| 243 | } | 260 | } |
| 244 | 261 | ||
| ... | @@ -399,11 +416,12 @@ class _PointSelectTextButton extends StatelessWidget { | ... | @@ -399,11 +416,12 @@ class _PointSelectTextButton extends StatelessWidget { |
| 399 | final String title; | 416 | final String title; |
| 400 | final Function? onTap; | 417 | final Function? onTap; |
| 401 | 418 | ||
| 402 | - const _PointSelectTextButton(this.isSelect, | 419 | + const _PointSelectTextButton( |
| 403 | - this.title, { | 420 | + this.isSelect, |
| 404 | - Key? key, | 421 | + this.title, { |
| 405 | - this.onTap, | 422 | + Key? key, |
| 406 | - }) : super(key: key); | 423 | + this.onTap, |
| 424 | + }) : super(key: key); | ||
| 407 | 425 | ||
| 408 | @override | 426 | @override |
| 409 | Widget build(BuildContext context) { | 427 | Widget build(BuildContext context) { |
| ... | @@ -413,13 +431,13 @@ class _PointSelectTextButton extends StatelessWidget { | ... | @@ -413,13 +431,13 @@ class _PointSelectTextButton extends StatelessWidget { |
| 413 | children: <Widget>[ | 431 | children: <Widget>[ |
| 414 | isSelect | 432 | isSelect |
| 415 | ? Container( | 433 | ? Container( |
| 416 | - width: 6.px, | 434 | + width: 6.px, |
| 417 | - height: 6.px, | 435 | + height: 6.px, |
| 418 | - decoration: BoxDecoration( | 436 | + decoration: BoxDecoration( |
| 419 | - color: ColorPlate.orange, | 437 | + color: ColorPlate.orange, |
| 420 | - borderRadius: BorderRadius.circular(3), | 438 | + borderRadius: BorderRadius.circular(3), |
| 421 | - ), | 439 | + ), |
| 422 | - ) | 440 | + ) |
| 423 | : Container(), | 441 | : Container(), |
| 424 | Container( | 442 | Container( |
| 425 | padding: const EdgeInsets.only(left: 2), | 443 | padding: const EdgeInsets.only(left: 2), |
| ... | @@ -438,11 +456,12 @@ class TextGroup extends StatelessWidget { | ... | @@ -438,11 +456,12 @@ class TextGroup extends StatelessWidget { |
| 438 | final String title, tag; | 456 | final String title, tag; |
| 439 | final Color? color; | 457 | final Color? color; |
| 440 | 458 | ||
| 441 | - const TextGroup(this.title, | 459 | + const TextGroup( |
| 442 | - this.tag, { | 460 | + this.title, |
| 443 | - Key? key, | 461 | + this.tag, { |
| 444 | - this.color, | 462 | + Key? key, |
| 445 | - }) : super(key: key); | 463 | + this.color, |
| 464 | + }) : super(key: key); | ||
| 446 | 465 | ||
| 447 | @override | 466 | @override |
| 448 | Widget build(BuildContext context) { | 467 | Widget build(BuildContext context) { | ... | ... |
| 1 | +import 'package:Parlando/account/models/user_entity.dart'; | ||
| 2 | +import 'package:Parlando/apis/api_response.dart'; | ||
| 3 | +import 'package:Parlando/net/dio_utils.dart'; | ||
| 4 | +import 'package:Parlando/net/http_api.dart'; | ||
| 5 | +import 'package:flutter/material.dart'; | ||
| 6 | + | ||
| 7 | +class AccountViewProvider with ChangeNotifier { | ||
| 8 | + ApiResponse _apiResponse = ApiResponse.initial('Empty data'); | ||
| 9 | + UserData? _user; | ||
| 10 | + | ||
| 11 | + ApiResponse get response { | ||
| 12 | + return _apiResponse; | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + UserData? get media { | ||
| 16 | + return _user; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + Future<void> fetchAccountData(String value) async { | ||
| 20 | + _apiResponse = ApiResponse.loading('Fetching artist data'); | ||
| 21 | + // TODO 不知道为啥会提前触发,先注释掉吧 | ||
| 22 | + | ||
| 23 | + DioUtils.instance.asyncRequestNetwork<UserEntity>( | ||
| 24 | + Method.get, | ||
| 25 | + HttpApi.user, | ||
| 26 | + onSuccess: (data) { | ||
| 27 | + _apiResponse = ApiResponse.completed(data!.data); | ||
| 28 | + notifyListeners(); | ||
| 29 | + }, | ||
| 30 | + onError: (code, msg) { | ||
| 31 | + _apiResponse = ApiResponse.error(msg); | ||
| 32 | + notifyListeners(); | ||
| 33 | + }, | ||
| 34 | + ); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + void setSelectedAccount(UserData? user) { | ||
| 38 | + _user = user; | ||
| 39 | + // notifyListeners(); | ||
| 40 | + } | ||
| 41 | +} |
lib/apis/api_response.dart
0 → 100644
| 1 | +class ApiResponse<T> { | ||
| 2 | + Status status; | ||
| 3 | + T? data; | ||
| 4 | + String? message; | ||
| 5 | + | ||
| 6 | + ApiResponse.initial(this.message) : status = Status.INITIAL; | ||
| 7 | + | ||
| 8 | + ApiResponse.loading(this.message) : status = Status.LOADING; | ||
| 9 | + | ||
| 10 | + ApiResponse.completed(this.data) : status = Status.COMPLETED; | ||
| 11 | + | ||
| 12 | + ApiResponse.error(this.message) : status = Status.ERROR; | ||
| 13 | + | ||
| 14 | + @override | ||
| 15 | + String toString() { | ||
| 16 | + return "Status : $status \n Message : $message \n Data : $data"; | ||
| 17 | + } | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +enum Status { INITIAL, LOADING, COMPLETED, ERROR } |
lib/apis/app_exception.dart
0 → 100644
| 1 | +class AppException implements Exception { | ||
| 2 | + late final String? _message; | ||
| 3 | + late final String? _prefix; | ||
| 4 | + | ||
| 5 | + AppException([this._message, this._prefix]); | ||
| 6 | + | ||
| 7 | + @override | ||
| 8 | + String toString() { | ||
| 9 | + return "$_prefix$_message"; | ||
| 10 | + } | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +class FetchDataException extends AppException { | ||
| 14 | + FetchDataException([String? message]) | ||
| 15 | + : super(message, "Error During Communication: "); | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +class BadRequestException extends AppException { | ||
| 19 | + BadRequestException([message]) : super(message, "Invalid Request: "); | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +class UnauthorisedException extends AppException { | ||
| 23 | + UnauthorisedException([message]) : super(message, "Unauthorised Request: "); | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +class InvalidInputException extends AppException { | ||
| 27 | + InvalidInputException([String? message]) : super(message, "Invalid Input: "); | ||
| 28 | +} |
| 1 | import 'package:Parlando/generated/json/base/json_convert_content.dart'; | 1 | import 'package:Parlando/generated/json/base/json_convert_content.dart'; |
| 2 | import 'package:Parlando/login/models/auth_entity.dart'; | 2 | import 'package:Parlando/login/models/auth_entity.dart'; |
| 3 | 3 | ||
| 4 | -AuthEntity $LoginEntityFromJson(Map<String, dynamic> json) { | 4 | +AuthEntity $AuthEntityFromJson(Map<String, dynamic> json) { |
| 5 | - final AuthEntity loginEntity = AuthEntity(); | 5 | + final AuthEntity authEntity = AuthEntity(); |
| 6 | final String? status = jsonConvert.convert<String>(json['status']); | 6 | final String? status = jsonConvert.convert<String>(json['status']); |
| 7 | if (status != null) { | 7 | if (status != null) { |
| 8 | - loginEntity.status = status; | 8 | + authEntity.status = status; |
| 9 | } | 9 | } |
| 10 | final int? code = jsonConvert.convert<int>(json['code']); | 10 | final int? code = jsonConvert.convert<int>(json['code']); |
| 11 | if (code != null) { | 11 | if (code != null) { |
| 12 | - loginEntity.code = code; | 12 | + authEntity.code = code; |
| 13 | } | 13 | } |
| 14 | final String? message = jsonConvert.convert<String>(json['message']); | 14 | final String? message = jsonConvert.convert<String>(json['message']); |
| 15 | if (message != null) { | 15 | if (message != null) { |
| 16 | - loginEntity.message = message; | 16 | + authEntity.message = message; |
| 17 | } | 17 | } |
| 18 | final AuthData? data = jsonConvert.convert<AuthData>(json['data']); | 18 | final AuthData? data = jsonConvert.convert<AuthData>(json['data']); |
| 19 | if (data != null) { | 19 | if (data != null) { |
| 20 | - loginEntity.data = data; | 20 | + authEntity.data = data; |
| 21 | } | 21 | } |
| 22 | final AuthError? error = jsonConvert.convert<AuthError>(json['error']); | 22 | final AuthError? error = jsonConvert.convert<AuthError>(json['error']); |
| 23 | if (error != null) { | 23 | if (error != null) { |
| 24 | - loginEntity.error = error; | 24 | + authEntity.error = error; |
| 25 | } | 25 | } |
| 26 | - return loginEntity; | 26 | + return authEntity; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | -Map<String, dynamic> $LoginEntityToJson(AuthEntity entity) { | 29 | +Map<String, dynamic> $AuthEntityToJson(AuthEntity entity) { |
| 30 | final Map<String, dynamic> data = <String, dynamic>{}; | 30 | final Map<String, dynamic> data = <String, dynamic>{}; |
| 31 | data['status'] = entity.status; | 31 | data['status'] = entity.status; |
| 32 | data['code'] = entity.code; | 32 | data['code'] = entity.code; |
| ... | @@ -36,27 +36,27 @@ Map<String, dynamic> $LoginEntityToJson(AuthEntity entity) { | ... | @@ -36,27 +36,27 @@ Map<String, dynamic> $LoginEntityToJson(AuthEntity entity) { |
| 36 | return data; | 36 | return data; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | -AuthData $LoginDataFromJson(Map<String, dynamic> json) { | 39 | +AuthData $AuthDataFromJson(Map<String, dynamic> json) { |
| 40 | - final AuthData loginData = AuthData(); | 40 | + final AuthData authData = AuthData(); |
| 41 | final String? token = jsonConvert.convert<String>(json['token']); | 41 | final String? token = jsonConvert.convert<String>(json['token']); |
| 42 | if (token != null) { | 42 | if (token != null) { |
| 43 | - loginData.token = token; | 43 | + authData.token = token; |
| 44 | } | 44 | } |
| 45 | - return loginData; | 45 | + return authData; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | -Map<String, dynamic> $LoginDataToJson(AuthData entity) { | 48 | +Map<String, dynamic> $AuthDataToJson(AuthData entity) { |
| 49 | final Map<String, dynamic> data = <String, dynamic>{}; | 49 | final Map<String, dynamic> data = <String, dynamic>{}; |
| 50 | data['token'] = entity.token; | 50 | data['token'] = entity.token; |
| 51 | return data; | 51 | return data; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | -AuthError $LoginErrorFromJson(Map<String, dynamic> json) { | 54 | +AuthError $AuthErrorFromJson(Map<String, dynamic> json) { |
| 55 | - final AuthError loginError = AuthError(); | 55 | + final AuthError authError = AuthError(); |
| 56 | - return loginError; | 56 | + return authError; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | -Map<String, dynamic> $LoginErrorToJson(AuthError entity) { | 59 | +Map<String, dynamic> $AuthErrorToJson(AuthError entity) { |
| 60 | final Map<String, dynamic> data = <String, dynamic>{}; | 60 | final Map<String, dynamic> data = <String, dynamic>{}; |
| 61 | return data; | 61 | return data; |
| 62 | } | 62 | } | ... | ... |
| ... | @@ -3,24 +3,41 @@ | ... | @@ -3,24 +3,41 @@ |
| 3 | // ignore_for_file: prefer_single_quotes | 3 | // ignore_for_file: prefer_single_quotes |
| 4 | 4 | ||
| 5 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost. | 5 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost. |
| 6 | +import 'package:flutter/material.dart'; | ||
| 6 | import 'package:Parlando/account/models/user_entity.dart'; | 7 | import 'package:Parlando/account/models/user_entity.dart'; |
| 7 | -import 'package:Parlando/generated/json/user_entity.g.dart'; | ||
| 8 | import 'package:Parlando/category/models/category_item_entity.dart'; | 8 | import 'package:Parlando/category/models/category_item_entity.dart'; |
| 9 | -import 'package:Parlando/generated/json/category_item_entity.g.dart'; | ||
| 10 | import 'package:Parlando/home/models/setting_entity.dart'; | 9 | import 'package:Parlando/home/models/setting_entity.dart'; |
| 11 | -import 'package:Parlando/generated/json/setting_entity.g.dart'; | ||
| 12 | import 'package:Parlando/login/models/auth_entity.dart'; | 10 | import 'package:Parlando/login/models/auth_entity.dart'; |
| 13 | -import 'package:Parlando/generated/json/login_entity.g.dart'; | ||
| 14 | import 'package:Parlando/poem/models/lang_sort_entity.dart'; | 11 | import 'package:Parlando/poem/models/lang_sort_entity.dart'; |
| 15 | -import 'package:Parlando/generated/json/lang_sort_entity.g.dart'; | ||
| 16 | import 'package:Parlando/poem/models/search_entity.dart'; | 12 | import 'package:Parlando/poem/models/search_entity.dart'; |
| 17 | -import 'package:Parlando/generated/json/search_entity.g.dart'; | ||
| 18 | import 'package:Parlando/timeline/models/friend_entity.dart'; | 13 | import 'package:Parlando/timeline/models/friend_entity.dart'; |
| 19 | -import 'package:Parlando/generated/json/friend_entity.g.dart'; | ||
| 20 | 14 | ||
| 21 | JsonConvert jsonConvert = JsonConvert(); | 15 | JsonConvert jsonConvert = JsonConvert(); |
| 22 | 16 | ||
| 17 | +typedef JsonConvertFunction<T> = T Function(Map<String, dynamic> json); | ||
| 18 | + | ||
| 23 | class JsonConvert { | 19 | class JsonConvert { |
| 20 | + static final Map<String, JsonConvertFunction> _convertFuncMap = { | ||
| 21 | + (UserEntity).toString(): UserEntity.fromJson, | ||
| 22 | + (UserData).toString(): UserData.fromJson, | ||
| 23 | + (UserError).toString(): UserError.fromJson, | ||
| 24 | + (CategoryItemEntity).toString(): CategoryItemEntity.fromJson, | ||
| 25 | + (SettingEntity).toString(): SettingEntity.fromJson, | ||
| 26 | + (SettingData).toString(): SettingData.fromJson, | ||
| 27 | + (SettingDataLoginSetting).toString(): SettingDataLoginSetting.fromJson, | ||
| 28 | + (SettingError).toString(): SettingError.fromJson, | ||
| 29 | + (AuthEntity).toString(): AuthEntity.fromJson, | ||
| 30 | + (AuthData).toString(): AuthData.fromJson, | ||
| 31 | + (AuthError).toString(): AuthError.fromJson, | ||
| 32 | + (LangSortEntity).toString(): LangSortEntity.fromJson, | ||
| 33 | + (SearchEntity).toString(): SearchEntity.fromJson, | ||
| 34 | + (SearchItems).toString(): SearchItems.fromJson, | ||
| 35 | + (SearchItemsOwner).toString(): SearchItemsOwner.fromJson, | ||
| 36 | + (SearchItemsLicense).toString(): SearchItemsLicense.fromJson, | ||
| 37 | + (FriendEntity).toString(): FriendEntity.fromJson, | ||
| 38 | + (FriendData).toString(): FriendData.fromJson, | ||
| 39 | + }; | ||
| 40 | + | ||
| 24 | T? convert<T>(dynamic value) { | 41 | T? convert<T>(dynamic value) { |
| 25 | if (value == null) { | 42 | if (value == null) { |
| 26 | return null; | 43 | return null; |
| ... | @@ -35,7 +52,7 @@ class JsonConvert { | ... | @@ -35,7 +52,7 @@ class JsonConvert { |
| 35 | try { | 52 | try { |
| 36 | return value.map((dynamic e) => asT<T>(e)).toList(); | 53 | return value.map((dynamic e) => asT<T>(e)).toList(); |
| 37 | } catch (e, stackTrace) { | 54 | } catch (e, stackTrace) { |
| 38 | - print('asT<$T> $e $stackTrace'); | 55 | + debugPrint('asT<$T> $e $stackTrace'); |
| 39 | return <T>[]; | 56 | return <T>[]; |
| 40 | } | 57 | } |
| 41 | } | 58 | } |
| ... | @@ -47,15 +64,16 @@ class JsonConvert { | ... | @@ -47,15 +64,16 @@ class JsonConvert { |
| 47 | try { | 64 | try { |
| 48 | return (value as List<dynamic>).map((dynamic e) => asT<T>(e)!).toList(); | 65 | return (value as List<dynamic>).map((dynamic e) => asT<T>(e)!).toList(); |
| 49 | } catch (e, stackTrace) { | 66 | } catch (e, stackTrace) { |
| 50 | - print('asT<$T> $e $stackTrace'); | 67 | + debugPrint('asT<$T> $e $stackTrace'); |
| 51 | return <T>[]; | 68 | return <T>[]; |
| 52 | } | 69 | } |
| 53 | } | 70 | } |
| 71 | + | ||
| 54 | T? asT<T extends Object?>(dynamic value) { | 72 | T? asT<T extends Object?>(dynamic value) { |
| 55 | if (value is T) { | 73 | if (value is T) { |
| 56 | return value; | 74 | return value; |
| 57 | } | 75 | } |
| 58 | - final String type = T.toString(); | 76 | + final String type = T.toString(); |
| 59 | try { | 77 | try { |
| 60 | final String valueS = value.toString(); | 78 | final String valueS = value.toString(); |
| 61 | if (type == "String") { | 79 | if (type == "String") { |
| ... | @@ -66,87 +84,48 @@ class JsonConvert { | ... | @@ -66,87 +84,48 @@ class JsonConvert { |
| 66 | return double.tryParse(valueS)?.toInt() as T?; | 84 | return double.tryParse(valueS)?.toInt() as T?; |
| 67 | } else { | 85 | } else { |
| 68 | return intValue as T; | 86 | return intValue as T; |
| 69 | - } } else if (type == "double") { | 87 | + } |
| 88 | + } else if (type == "double") { | ||
| 70 | return double.parse(valueS) as T; | 89 | return double.parse(valueS) as T; |
| 71 | - } else if (type == "DateTime") { | 90 | + } else if (type == "DateTime") { |
| 72 | return DateTime.parse(valueS) as T; | 91 | return DateTime.parse(valueS) as T; |
| 73 | - } else if (type == "bool") { | 92 | + } else if (type == "bool") { |
| 74 | if (valueS == '0' || valueS == '1') { | 93 | if (valueS == '0' || valueS == '1') { |
| 75 | return (valueS == '1') as T; | 94 | return (valueS == '1') as T; |
| 76 | } | 95 | } |
| 77 | return (valueS == 'true') as T; | 96 | return (valueS == 'true') as T; |
| 97 | + } else if (type == "Map" || type.startsWith("Map<")) { | ||
| 98 | + return value as T; | ||
| 78 | } else { | 99 | } else { |
| 79 | - return JsonConvert.fromJsonAsT<T>(value); | 100 | + if (_convertFuncMap.containsKey(type)) { |
| 101 | + return _convertFuncMap[type]!(value) as T; | ||
| 102 | + } else { | ||
| 103 | + throw UnimplementedError('$type unimplemented'); | ||
| 104 | + } | ||
| 80 | } | 105 | } |
| 81 | } catch (e, stackTrace) { | 106 | } catch (e, stackTrace) { |
| 82 | - print('asT<$T> $e $stackTrace'); | 107 | + debugPrint('asT<$T> $e $stackTrace'); |
| 83 | return null; | 108 | return null; |
| 84 | } | 109 | } |
| 85 | - } | 110 | + } |
| 86 | - //Go back to a single instance by type | ||
| 87 | - static M? _fromJsonSingle<M>(Map<String, dynamic> json) { | ||
| 88 | - final String type = M.toString(); | ||
| 89 | - if (type == (UserEntity).toString()) { | ||
| 90 | - return UserEntity.fromJson(json) as M; | ||
| 91 | - } | ||
| 92 | - if (type == (CategoryItemEntity).toString()) { | ||
| 93 | - return CategoryItemEntity.fromJson(json) as M; | ||
| 94 | - } | ||
| 95 | - if (type == (SettingEntity).toString()) { | ||
| 96 | - return SettingEntity.fromJson(json) as M; | ||
| 97 | - } | ||
| 98 | - if (type == (SettingData).toString()) { | ||
| 99 | - return SettingData.fromJson(json) as M; | ||
| 100 | - } | ||
| 101 | - if (type == (SettingDataLoginSetting).toString()) { | ||
| 102 | - return SettingDataLoginSetting.fromJson(json) as M; | ||
| 103 | - } | ||
| 104 | - if (type == (SettingError).toString()) { | ||
| 105 | - return SettingError.fromJson(json) as M; | ||
| 106 | - } | ||
| 107 | - if (type == (AuthEntity).toString()) { | ||
| 108 | - return AuthEntity.fromJson(json) as M; | ||
| 109 | - } | ||
| 110 | - if (type == (AuthData).toString()) { | ||
| 111 | - return AuthData.fromJson(json) as M; | ||
| 112 | - } | ||
| 113 | - if (type == (AuthError).toString()) { | ||
| 114 | - return AuthError.fromJson(json) as M; | ||
| 115 | - } | ||
| 116 | - if (type == (LangSortEntity).toString()) { | ||
| 117 | - return LangSortEntity.fromJson(json) as M; | ||
| 118 | - } | ||
| 119 | - if (type == (SearchEntity).toString()) { | ||
| 120 | - return SearchEntity.fromJson(json) as M; | ||
| 121 | - } | ||
| 122 | - if (type == (SearchItems).toString()) { | ||
| 123 | - return SearchItems.fromJson(json) as M; | ||
| 124 | - } | ||
| 125 | - if (type == (SearchItemsOwner).toString()) { | ||
| 126 | - return SearchItemsOwner.fromJson(json) as M; | ||
| 127 | - } | ||
| 128 | - if (type == (SearchItemsLicense).toString()) { | ||
| 129 | - return SearchItemsLicense.fromJson(json) as M; | ||
| 130 | - } | ||
| 131 | - if (type == (FriendEntity).toString()) { | ||
| 132 | - return FriendEntity.fromJson(json) as M; | ||
| 133 | - } | ||
| 134 | - if (type == (FriendData).toString()) { | ||
| 135 | - return FriendData.fromJson(json) as M; | ||
| 136 | - } | ||
| 137 | - | ||
| 138 | - print("$type not found"); | ||
| 139 | - | ||
| 140 | - return null; | ||
| 141 | -} | ||
| 142 | 111 | ||
| 143 | //list is returned by type | 112 | //list is returned by type |
| 144 | - static M? _getListChildType<M>(List<Map<String, dynamic>> data) { | 113 | + static M? _getListChildType<M>(List<Map<String, dynamic>> data) { |
| 145 | if (<UserEntity>[] is M) { | 114 | if (<UserEntity>[] is M) { |
| 146 | return data | 115 | return data |
| 147 | .map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e)) | 116 | .map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e)) |
| 148 | .toList() as M; | 117 | .toList() as M; |
| 149 | } | 118 | } |
| 119 | + if (<UserData>[] is M) { | ||
| 120 | + return data | ||
| 121 | + .map<UserData>((Map<String, dynamic> e) => UserData.fromJson(e)) | ||
| 122 | + .toList() as M; | ||
| 123 | + } | ||
| 124 | + if (<UserError>[] is M) { | ||
| 125 | + return data | ||
| 126 | + .map<UserError>((Map<String, dynamic> e) => UserError.fromJson(e)) | ||
| 127 | + .toList() as M; | ||
| 128 | + } | ||
| 150 | if (<CategoryItemEntity>[] is M) { | 129 | if (<CategoryItemEntity>[] is M) { |
| 151 | return data | 130 | return data |
| 152 | .map<CategoryItemEntity>( | 131 | .map<CategoryItemEntity>( |
| ... | @@ -232,18 +211,17 @@ class JsonConvert { | ... | @@ -232,18 +211,17 @@ class JsonConvert { |
| 232 | .toList() as M; | 211 | .toList() as M; |
| 233 | } | 212 | } |
| 234 | 213 | ||
| 235 | - print("${M.toString()} not found"); | 214 | + debugPrint("${M.toString()} not found"); |
| 236 | - | 215 | + |
| 237 | - return null; | 216 | + return null; |
| 238 | -} | 217 | + } |
| 239 | 218 | ||
| 240 | static M? fromJsonAsT<M>(dynamic json) { | 219 | static M? fromJsonAsT<M>(dynamic json) { |
| 241 | - if(json == null){ | 220 | + if (json is List) { |
| 242 | - return null; | 221 | + return _getListChildType<M>( |
| 243 | - } if (json is List) { | 222 | + json.map((e) => e as Map<String, dynamic>).toList()); |
| 244 | - return _getListChildType<M>(json.map((e) => e as Map<String, dynamic>).toList()); | 223 | + } else { |
| 245 | - } else { | 224 | + return jsonConvert.asT<M>(json); |
| 246 | - return _fromJsonSingle<M>(json as Map<String, dynamic>); | 225 | + } |
| 247 | - } | 226 | + } |
| 248 | - } | ||
| 249 | } | 227 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -3,25 +3,110 @@ import 'package:Parlando/account/models/user_entity.dart'; | ... | @@ -3,25 +3,110 @@ import 'package:Parlando/account/models/user_entity.dart'; |
| 3 | 3 | ||
| 4 | UserEntity $UserEntityFromJson(Map<String, dynamic> json) { | 4 | UserEntity $UserEntityFromJson(Map<String, dynamic> json) { |
| 5 | final UserEntity userEntity = UserEntity(); | 5 | final UserEntity userEntity = UserEntity(); |
| 6 | + final String? status = jsonConvert.convert<String>(json['status']); | ||
| 7 | + if (status != null) { | ||
| 8 | + userEntity.status = status; | ||
| 9 | + } | ||
| 10 | + final int? code = jsonConvert.convert<int>(json['code']); | ||
| 11 | + if (code != null) { | ||
| 12 | + userEntity.code = code; | ||
| 13 | + } | ||
| 14 | + final String? message = jsonConvert.convert<String>(json['message']); | ||
| 15 | + if (message != null) { | ||
| 16 | + userEntity.message = message; | ||
| 17 | + } | ||
| 18 | + final UserData? data = jsonConvert.convert<UserData>(json['data']); | ||
| 19 | + if (data != null) { | ||
| 20 | + userEntity.data = data; | ||
| 21 | + } | ||
| 22 | + final UserError? error = jsonConvert.convert<UserError>(json['error']); | ||
| 23 | + if (error != null) { | ||
| 24 | + userEntity.error = error; | ||
| 25 | + } | ||
| 26 | + return userEntity; | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +Map<String, dynamic> $UserEntityToJson(UserEntity entity) { | ||
| 30 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
| 31 | + data['status'] = entity.status; | ||
| 32 | + data['code'] = entity.code; | ||
| 33 | + data['message'] = entity.message; | ||
| 34 | + data['data'] = entity.data?.toJson(); | ||
| 35 | + data['error'] = entity.error?.toJson(); | ||
| 36 | + return data; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +UserData $UserDataFromJson(Map<String, dynamic> json) { | ||
| 40 | + final UserData userData = UserData(); | ||
| 6 | final int? id = jsonConvert.convert<int>(json['id']); | 41 | final int? id = jsonConvert.convert<int>(json['id']); |
| 7 | if (id != null) { | 42 | if (id != null) { |
| 8 | - userEntity.id = id; | 43 | + userData.id = id; |
| 44 | + } | ||
| 45 | + final dynamic? nickname = jsonConvert.convert<dynamic>(json['nickname']); | ||
| 46 | + if (nickname != null) { | ||
| 47 | + userData.nickname = nickname; | ||
| 48 | + } | ||
| 49 | + final dynamic? mobile = jsonConvert.convert<dynamic>(json['mobile']); | ||
| 50 | + if (mobile != null) { | ||
| 51 | + userData.mobile = mobile; | ||
| 9 | } | 52 | } |
| 10 | - final String? name = jsonConvert.convert<String>(json['name']); | 53 | + final String? email = jsonConvert.convert<String>(json['email']); |
| 11 | - if (name != null) { | 54 | + if (email != null) { |
| 12 | - userEntity.name = name; | 55 | + userData.email = email; |
| 13 | } | 56 | } |
| 14 | final String? avatar = jsonConvert.convert<String>(json['avatar']); | 57 | final String? avatar = jsonConvert.convert<String>(json['avatar']); |
| 15 | if (avatar != null) { | 58 | if (avatar != null) { |
| 16 | - userEntity.avatar = avatar; | 59 | + userData.avatar = avatar; |
| 17 | } | 60 | } |
| 18 | - return userEntity; | 61 | + final String? gender = jsonConvert.convert<String>(json['gender']); |
| 62 | + if (gender != null) { | ||
| 63 | + userData.gender = gender; | ||
| 64 | + } | ||
| 65 | + final dynamic? provider = jsonConvert.convert<dynamic>(json['provider']); | ||
| 66 | + if (provider != null) { | ||
| 67 | + userData.provider = provider; | ||
| 68 | + } | ||
| 69 | + final dynamic? providerId = jsonConvert.convert<dynamic>(json['provider_id']); | ||
| 70 | + if (providerId != null) { | ||
| 71 | + userData.providerId = providerId; | ||
| 72 | + } | ||
| 73 | + final String? state = jsonConvert.convert<String>(json['state']); | ||
| 74 | + if (state != null) { | ||
| 75 | + userData.state = state; | ||
| 76 | + } | ||
| 77 | + final String? createdAt = jsonConvert.convert<String>(json['created_at']); | ||
| 78 | + if (createdAt != null) { | ||
| 79 | + userData.createdAt = createdAt; | ||
| 80 | + } | ||
| 81 | + final String? updatedAt = jsonConvert.convert<String>(json['updated_at']); | ||
| 82 | + if (updatedAt != null) { | ||
| 83 | + userData.updatedAt = updatedAt; | ||
| 84 | + } | ||
| 85 | + return userData; | ||
| 19 | } | 86 | } |
| 20 | 87 | ||
| 21 | -Map<String, dynamic> $UserEntityToJson(UserEntity entity) { | ||
| 22 | - final Map<String, dynamic> data = <String, dynamic>{}; | ||
| 23 | - data['id'] = entity.id; | ||
| 24 | - data['name'] = entity.name; | ||
| 25 | - data['avatar'] = entity.avatar; | ||
| 26 | - return data; | ||
| 27 | -} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 88 | +Map<String, dynamic> $UserDataToJson(UserData entity) { | ||
| 89 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
| 90 | + data['id'] = entity.id; | ||
| 91 | + data['nickname'] = entity.nickname; | ||
| 92 | + data['mobile'] = entity.mobile; | ||
| 93 | + data['email'] = entity.email; | ||
| 94 | + data['avatar'] = entity.avatar; | ||
| 95 | + data['gender'] = entity.gender; | ||
| 96 | + data['provider'] = entity.provider; | ||
| 97 | + data['provider_id'] = entity.providerId; | ||
| 98 | + data['state'] = entity.state; | ||
| 99 | + data['created_at'] = entity.createdAt; | ||
| 100 | + data['updated_at'] = entity.updatedAt; | ||
| 101 | + return data; | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +UserError $UserErrorFromJson(Map<String, dynamic> json) { | ||
| 105 | + final UserError userError = UserError(); | ||
| 106 | + return userError; | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +Map<String, dynamic> $UserErrorToJson(UserError entity) { | ||
| 110 | + final Map<String, dynamic> data = <String, dynamic>{}; | ||
| 111 | + return data; | ||
| 112 | +} | ... | ... |
| 1 | import 'dart:convert'; | 1 | import 'dart:convert'; |
| 2 | import 'package:Parlando/generated/json/base/json_field.dart'; | 2 | import 'package:Parlando/generated/json/base/json_field.dart'; |
| 3 | -import 'package:Parlando/generated/json/login_entity.g.dart'; | 3 | +import 'package:Parlando/generated/json/auth_entity.g.dart'; |
| 4 | 4 | ||
| 5 | @JsonSerializable() | 5 | @JsonSerializable() |
| 6 | class AuthEntity { | 6 | class AuthEntity { |
| ... | @@ -13,9 +13,9 @@ class AuthEntity { | ... | @@ -13,9 +13,9 @@ class AuthEntity { |
| 13 | AuthEntity(); | 13 | AuthEntity(); |
| 14 | 14 | ||
| 15 | factory AuthEntity.fromJson(Map<String, dynamic> json) => | 15 | factory AuthEntity.fromJson(Map<String, dynamic> json) => |
| 16 | - $LoginEntityFromJson(json); | 16 | + $AuthEntityFromJson(json); |
| 17 | 17 | ||
| 18 | - Map<String, dynamic> toJson() => $LoginEntityToJson(this); | 18 | + Map<String, dynamic> toJson() => $AuthEntityToJson(this); |
| 19 | 19 | ||
| 20 | @override | 20 | @override |
| 21 | String toString() { | 21 | String toString() { |
| ... | @@ -30,9 +30,9 @@ class AuthData { | ... | @@ -30,9 +30,9 @@ class AuthData { |
| 30 | AuthData(); | 30 | AuthData(); |
| 31 | 31 | ||
| 32 | factory AuthData.fromJson(Map<String, dynamic> json) => | 32 | factory AuthData.fromJson(Map<String, dynamic> json) => |
| 33 | - $LoginDataFromJson(json); | 33 | + $AuthDataFromJson(json); |
| 34 | 34 | ||
| 35 | - Map<String, dynamic> toJson() => $LoginDataToJson(this); | 35 | + Map<String, dynamic> toJson() => $AuthDataToJson(this); |
| 36 | 36 | ||
| 37 | @override | 37 | @override |
| 38 | String toString() { | 38 | String toString() { |
| ... | @@ -45,12 +45,12 @@ class AuthError { | ... | @@ -45,12 +45,12 @@ class AuthError { |
| 45 | AuthError(); | 45 | AuthError(); |
| 46 | 46 | ||
| 47 | factory AuthError.fromJson(Map<String, dynamic> json) => | 47 | factory AuthError.fromJson(Map<String, dynamic> json) => |
| 48 | - $LoginErrorFromJson(json); | 48 | + $AuthErrorFromJson(json); |
| 49 | 49 | ||
| 50 | - Map<String, dynamic> toJson() => $LoginErrorToJson(this); | 50 | + Map<String, dynamic> toJson() => $AuthErrorToJson(this); |
| 51 | 51 | ||
| 52 | @override | 52 | @override |
| 53 | String toString() { | 53 | String toString() { |
| 54 | return jsonEncode(this); | 54 | return jsonEncode(this); |
| 55 | } | 55 | } |
| 56 | -} | 56 | +} |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | +import 'package:Parlando/account/view_models/account_view_model.dart'; | ||
| 1 | import 'package:dio/dio.dart'; | 2 | import 'package:dio/dio.dart'; |
| 2 | import 'package:flustars/flustars.dart'; | 3 | import 'package:flustars/flustars.dart'; |
| 3 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
| ... | @@ -88,15 +89,10 @@ class MyApp extends StatelessWidget { | ... | @@ -88,15 +89,10 @@ class MyApp extends StatelessWidget { |
| 88 | /// 统一添加身份验证请求头 | 89 | /// 统一添加身份验证请求头 |
| 89 | interceptors.add(AuthInterceptor()); | 90 | interceptors.add(AuthInterceptor()); |
| 90 | 91 | ||
| 91 | - /// 刷新Token | ||
| 92 | - interceptors.add(TokenInterceptor()); | ||
| 93 | - | ||
| 94 | /// 打印Log(生产模式去除) | 92 | /// 打印Log(生产模式去除) |
| 95 | if (!Constant.inProduction) { | 93 | if (!Constant.inProduction) { |
| 96 | interceptors.add(LoggingInterceptor()); | 94 | interceptors.add(LoggingInterceptor()); |
| 97 | } | 95 | } |
| 98 | - | ||
| 99 | - /// 适配数据(根据自己的数据结构,可自行选择添加) | ||
| 100 | interceptors.add(AdapterInterceptor()); | 96 | interceptors.add(AdapterInterceptor()); |
| 101 | configDio( | 97 | configDio( |
| 102 | baseUrl: 'http://www.yiyan.pub/api/v1/', | 98 | baseUrl: 'http://www.yiyan.pub/api/v1/', |
| ... | @@ -131,7 +127,8 @@ class MyApp extends StatelessWidget { | ... | @@ -131,7 +127,8 @@ class MyApp extends StatelessWidget { |
| 131 | final Widget app = MultiProvider( | 127 | final Widget app = MultiProvider( |
| 132 | providers: [ | 128 | providers: [ |
| 133 | ChangeNotifierProvider(create: (_) => ThemeProvider()), | 129 | ChangeNotifierProvider(create: (_) => ThemeProvider()), |
| 134 | - ChangeNotifierProvider(create: (_) => LocaleProvider()) | 130 | + ChangeNotifierProvider(create: (_) => LocaleProvider()), |
| 131 | + ChangeNotifierProvider(create: (_) => AccountViewProvider()) | ||
| 135 | ], | 132 | ], |
| 136 | child: Consumer2<ThemeProvider, LocaleProvider>( | 133 | child: Consumer2<ThemeProvider, LocaleProvider>( |
| 137 | builder: | 134 | builder: |
| ... | @@ -145,14 +142,13 @@ class MyApp extends StatelessWidget { | ... | @@ -145,14 +142,13 @@ class MyApp extends StatelessWidget { |
| 145 | return OKToast( | 142 | return OKToast( |
| 146 | backgroundColor: Colors.black54, | 143 | backgroundColor: Colors.black54, |
| 147 | textPadding: | 144 | textPadding: |
| 148 | - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), | 145 | + const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), |
| 149 | radius: 20.0, | 146 | radius: 20.0, |
| 150 | position: ToastPosition.bottom, | 147 | position: ToastPosition.bottom, |
| 151 | child: app); | 148 | child: app); |
| 152 | } | 149 | } |
| 153 | 150 | ||
| 154 | - Widget _buildMaterialApp( | 151 | + Widget _buildMaterialApp(ThemeProvider provider, LocaleProvider localeProvider) { |
| 155 | - ThemeProvider provider, LocaleProvider localeProvider) { | ||
| 156 | return MaterialApp( | 152 | return MaterialApp( |
| 157 | title: '一言', | 153 | title: '一言', |
| 158 | // showPerformanceOverlay: true, //显示性能标签 | 154 | // showPerformanceOverlay: true, //显示性能标签 | ... | ... |
| ... | @@ -120,6 +120,33 @@ class DioUtils { | ... | @@ -120,6 +120,33 @@ class DioUtils { |
| 120 | return options; | 120 | return options; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | + Future request<T>( | ||
| 124 | + String method, | ||
| 125 | + String url, { | ||
| 126 | + Object? data, | ||
| 127 | + Map<String, dynamic>? queryParameters, | ||
| 128 | + CancelToken? cancelToken, | ||
| 129 | + Options? options, | ||
| 130 | + }) async { | ||
| 131 | + final Response<String> response = await _dio.request<String>( | ||
| 132 | + url, | ||
| 133 | + data: data, | ||
| 134 | + queryParameters: queryParameters, | ||
| 135 | + options: _checkOptions(method, options), | ||
| 136 | + cancelToken: cancelToken, | ||
| 137 | + ); | ||
| 138 | + try { | ||
| 139 | + final String data = response.data.toString(); | ||
| 140 | + final bool isCompute = !Constant.isDriverTest && data.length > 10 * 1024; | ||
| 141 | + final Map<String, dynamic> _map = | ||
| 142 | + isCompute ? await compute(parseData, data) : parseData(data); | ||
| 143 | + return BaseEntity<T>.fromJson(_map); | ||
| 144 | + } catch (e) { | ||
| 145 | + debugPrint(e.toString()); | ||
| 146 | + return BaseEntity<T>(ExceptionHandle.parse_error, '数据解析错误!', null); | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + | ||
| 123 | Future requestNetwork<T>( | 150 | Future requestNetwork<T>( |
| 124 | Method method, | 151 | Method method, |
| 125 | String url, { | 152 | String url, { | ... | ... |
| ... | @@ -3,6 +3,7 @@ class HttpApi { | ... | @@ -3,6 +3,7 @@ class HttpApi { |
| 3 | static const String register = 'register'; | 3 | static const String register = 'register'; |
| 4 | static const String verify = 'verify'; | 4 | static const String verify = 'verify'; |
| 5 | static const String login = 'login'; | 5 | static const String login = 'login'; |
| 6 | + static const String user = 'user'; | ||
| 6 | static const String search = 'search/repositories'; | 7 | static const String search = 'search/repositories'; |
| 7 | static const String subscriptions = 'users/simplezhli/subscriptions'; | 8 | static const String subscriptions = 'users/simplezhli/subscriptions'; |
| 8 | static const String upload = 'uuc/upload-inco'; | 9 | static const String upload = 'uuc/upload-inco'; | ... | ... |
| ... | @@ -14,12 +14,11 @@ import 'error_handle.dart'; | ... | @@ -14,12 +14,11 @@ import 'error_handle.dart'; |
| 14 | class AuthInterceptor extends Interceptor { | 14 | class AuthInterceptor extends Interceptor { |
| 15 | @override | 15 | @override |
| 16 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) { | 16 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) { |
| 17 | - final String accessToken = SpUtil.getString(Constant.accessToken).nullSafe; | 17 | + final String accessToken = SpUtil.getString(Constant.userToken).nullSafe; |
| 18 | if (accessToken.isNotEmpty) { | 18 | if (accessToken.isNotEmpty) { |
| 19 | - options.headers['Authorization'] = 'token $accessToken'; | 19 | + options.headers['Authorization'] = 'Bearer $accessToken'; |
| 20 | } | 20 | } |
| 21 | if (!Device.isWeb) { | 21 | if (!Device.isWeb) { |
| 22 | - // https://developer.github.com/v3/#user-agent-required | ||
| 23 | options.headers['User-Agent'] = 'Mozilla/5.0'; | 22 | options.headers['User-Agent'] = 'Mozilla/5.0'; |
| 24 | } | 23 | } |
| 25 | super.onRequest(options, handler); | 24 | super.onRequest(options, handler); | ... | ... |
| ... | @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev | ... | @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev |
| 18 | version: 1.0.0+1 | 18 | version: 1.0.0+1 |
| 19 | 19 | ||
| 20 | environment: | 20 | environment: |
| 21 | - sdk: ">=2.14.0 <3.0.0" | 21 | + sdk: ">=2.16.2 <3.0.0" |
| 22 | flutter: ">=2.5.0" | 22 | flutter: ">=2.5.0" |
| 23 | 23 | ||
| 24 | # Dependencies specify other packages that your package needs in poem to work. | 24 | # Dependencies specify other packages that your package needs in poem to work. | ... | ... |
-
Please register or login to post a comment