diff --git a/api/Passport/Developer Notify All Users.bru b/api/Passport/Developer Notify All Users.bru index 52c4455..05bdfe9 100644 --- a/api/Passport/Developer Notify All Users.bru +++ b/api/Passport/Developer Notify All Users.bru @@ -15,11 +15,11 @@ body:json { "client_id": "{{third_client_id}}", "client_secret":"{{third_client_tk}}", "type": "general", - "subject": "Merry Christmas!", + "subject": "新年快乐!", "subtitle": "一条来自 Solar Network 团队的信息", - "content": "今天是 12 月 25 日 (UTC+8),小羊祝您圣诞快乐 🎄", + "content": "今天是农历正月初一,小羊祝您新年快乐 🎉", "metadata": { - "image": "6EqsYQwmFRCkbmhR" + "image": "D2EDbcrsTugs3xk5" }, "priority": 10 } diff --git a/api/environments/Prod.bru b/api/environments/Prod.bru index 7f767e1..7d585a2 100644 --- a/api/environments/Prod.bru +++ b/api/environments/Prod.bru @@ -1,8 +1,8 @@ vars { endpoint: https://api.sn.solsynth.dev third_client_id: alphabot + atk: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3NvbHN5bnRoLmRldiIsInN1YiI6IjEiLCJhdWQiOlsic29sYXItbmV0d29yayJdLCJleHAiOjE3MzgwODE2OTYsIm5iZiI6MTczODA3ODY5NiwiaWF0IjoxNzM4MDc4Njk2LCJqdGkiOiI1Yzg2MTYxZC00MTZjLTQwNDYtOWFlNS04YWZhNGIyZjdlMTkiLCJzZWQiOiIyMTciLCJ0eXAiOiJhY2Nlc3MifQ.LdLZ6FLb8IqPI__U8sT6VyxK5S_ZgwVGGL-tk01tK9C19wnbFFThPDgga1pJu_VVVpGVxzvMyd-3tBotzLMB5LjhYbtPOJakN2oug1HAgJ8zfc1clORlpHlUVisaiQtl3ZkWtzxni8etZDhJpqHU65IGQG01TO6PZGLgxKkMel4gGeeKhHpg9Q4Eewr3Pbl_wJkHVChJ9IJPmgioc_CACE10nEHZgwptCbndUz3AbIDOG9qW-7ZoprtKoRwAcuUXANK277VvdBRhwQjqKBREqVeMXP_Rv37jDPYhWpfS6HtKoHElZOTJG-69S2Zc3HyHlPJAPlzLAjGPoxScky79Gg } vars:secret [ - atk, third_client_tk ] diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index 27b3e2d..8632dc9 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -18,6 +18,7 @@ "screenAbuseReport": "Abuse Reports", "screenSettings": "Settings", "screenAccountSettings": "Account Settings", + "screenFactorSettings": "Auth Factors", "screenAccountWallet": "Wallet", "screenNews": "News", "screenAlbum": "Album", @@ -30,7 +31,6 @@ "screenNotification": "Notification", "screenPostSearch": "Search Posts", "screenFriend": "Friends", - "screenFactorSettings": "Auth Factors", "dialogOkay": "Okay", "dialogCancel": "Cancel", "dialogConfirm": "Confirm", @@ -592,5 +592,14 @@ "totpPostSetupDescription": "Scan the QR Code below with Google Authenticator, Microsoft Authenticator, 1Password, Authy, Bitwarden or any of kind of authenticator app which supports TOTP.", "totpNeverShare": "Never share this QR Code", "needHelp": "Need Help?", - "needHelpLaunch": "Check out our Goatpedia!" + "needHelpLaunch": "Check out our Goatpedia!", + "walletCreate": "Create a Wallet", + "walletCreateSubtitle": "Create a wallet to start using Solar Coins", + "walletCreateTerms": "By creating a wallet, you agree to Solar Wallet's Extra Terms of Service.", + "walletCreatePassword": "Set a payment password for your new wallet below", + "walletCurrencyShort": "Credit", + "walletCurrency": { + "one": "{} Social Credit Point", + "other": "{} Social Credit Points" + } } diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 14ba966..c01cc86 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -16,6 +16,7 @@ "screenAbuseReport": "滥用检举", "screenSettings": "设置", "screenAccountSettings": "账号设置", + "screenFactorSettings": "验证因子", "screenAccountWallet": "钱包", "screenNews": "新闻", "screenAlbum": "相册", @@ -589,5 +590,10 @@ "totpPostSetupDescription": "使用 Google Authenticator, Microsoft Authenticator, 1Password, Authy, Bitwarden 或其他支持 TOTP 的验证器扫描本 QR Code 来添加。", "totpNeverShare": "永远不要分享这个 QR Code", "needHelp": "需要帮助?", - "needHelpLaunch": "查看我们的山羊维基!" + "needHelpLaunch": "查看我们的山羊维基!", + "walletCurrencyShort": "信用点", + "walletCurrency": { + "one": "{} 社会信用点", + "other": "{} 社会信用点" + } } diff --git a/lib/router.dart b/lib/router.dart index f837da4..b6f6a75 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -33,6 +33,7 @@ import 'package:surface/screens/realm/manage.dart'; import 'package:surface/screens/realm/realm_detail.dart'; import 'package:surface/screens/settings.dart'; import 'package:surface/screens/sharing.dart'; +import 'package:surface/screens/wallet.dart'; import 'package:surface/types/post.dart'; import 'package:surface/widgets/about.dart'; import 'package:surface/widgets/navigation/app_scaffold.dart'; @@ -99,6 +100,11 @@ final _appRoutes = [ ], ), GoRoute(path: '/account', name: 'account', builder: (context, state) => const AccountScreen(), routes: [ + GoRoute( + path: '/wallet', + name: 'accountWallet', + builder: (context, state) => const WalletScreen(), + ), GoRoute( path: '/settings', name: 'accountSettings', diff --git a/lib/screens/account.dart b/lib/screens/account.dart index 69c0442..fce2792 100644 --- a/lib/screens/account.dart +++ b/lib/screens/account.dart @@ -144,6 +144,16 @@ class _AuthorizedAccountScreen extends StatelessWidget { GoRouter.of(context).pushNamed('factorSettings'); }, ), + ListTile( + title: Text('accountWallet').tr(), + subtitle: Text('accountWalletSubtitle').tr(), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + leading: const Icon(Symbols.wallet), + trailing: const Icon(Symbols.chevron_right), + onTap: () { + GoRouter.of(context).pushNamed('accountWallet'); + }, + ), ListTile( title: Text('accountSettings').tr(), subtitle: Text('accountSettingsSubtitle').tr(), diff --git a/lib/screens/account/factor_settings.dart b/lib/screens/account/factor_settings.dart index d89e31f..56e63a7 100644 --- a/lib/screens/account/factor_settings.dart +++ b/lib/screens/account/factor_settings.dart @@ -238,7 +238,7 @@ class _FactorNewDialogState extends State<_FactorNewDialog> { class _FactorTotpFactorDialog extends StatelessWidget { final SnAuthFactor factor; - const _FactorTotpFactorDialog({super.key, required this.factor}); + const _FactorTotpFactorDialog({required this.factor}); @override Widget build(BuildContext context) { diff --git a/lib/screens/auth/login.dart b/lib/screens/auth/login.dart index c20e3c0..7f1d1b4 100644 --- a/lib/screens/auth/login.dart +++ b/lib/screens/auth/login.dart @@ -412,8 +412,9 @@ class _LoginLookupScreenState extends State<_LoginLookupScreen> { await sn.client.post('/cgi/id/users/me/password-reset', data: { 'user_id': lookupResp.data['id'], }); - if (mounted) + if (mounted) { context.showModalDialog('done'.tr(), 'signinResetPasswordSent'.tr()); + } } catch (err) { if (mounted) context.showErrorDialog(err); } finally { diff --git a/lib/screens/wallet.dart b/lib/screens/wallet.dart new file mode 100644 index 0000000..9ff84cb --- /dev/null +++ b/lib/screens/wallet.dart @@ -0,0 +1,284 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; +import 'package:styled_widget/styled_widget.dart'; +import 'package:surface/providers/sn_network.dart'; +import 'package:surface/types/wallet.dart'; +import 'package:surface/widgets/dialog.dart'; +import 'package:surface/widgets/loading_indicator.dart'; +import 'package:surface/widgets/navigation/app_scaffold.dart'; +import 'package:very_good_infinite_list/very_good_infinite_list.dart'; + +class WalletScreen extends StatefulWidget { + const WalletScreen({super.key}); + + @override + State createState() => _WalletScreenState(); +} + +class _WalletScreenState extends State { + bool _isBusy = false; + SnWallet? _wallet; + + Future _fetchWallet() async { + try { + setState(() => _isBusy = true); + final sn = context.read(); + final resp = await sn.client.get('/cgi/wa/wallets/me'); + _wallet = SnWallet.fromJson(resp.data); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + + @override + void initState() { + super.initState(); + _fetchWallet(); + } + + @override + Widget build(BuildContext context) { + return AppScaffold( + appBar: AppBar( + leading: PageBackButton(), + title: Text('screenAccountWallet').tr(), + ), + body: Column( + children: [ + LoadingIndicator(isActive: _isBusy), + if (_wallet == null) + Expanded( + child: _CreateWalletWidget( + onCreate: () { + _fetchWallet(); + }, + ), + ) + else + Card( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CircleAvatar( + radius: 28, + child: Icon(Symbols.wallet, size: 28), + ), + const Gap(12), + SizedBox(width: double.infinity), + Text( + NumberFormat.compactCurrency( + locale: EasyLocalization.of(context)!.currentLocale.toString(), + symbol: '${'walletCurrencyShort'.tr()} ', + decimalDigits: 2, + ).format(double.parse(_wallet!.balance)), + style: Theme.of(context).textTheme.titleLarge, + ), + Text('walletCurrency'.plural(double.parse(_wallet!.balance))), + ], + ).padding(horizontal: 20, vertical: 24), + ), + if (_wallet != null) Expanded(child: _WalletTransactionList(myself: _wallet!)), + ], + ), + ); + } +} + +class _WalletTransactionList extends StatefulWidget { + final SnWallet myself; + + const _WalletTransactionList({required this.myself}); + + @override + State<_WalletTransactionList> createState() => _WalletTransactionListState(); +} + +class _WalletTransactionListState extends State<_WalletTransactionList> { + bool _isBusy = false; + int? _totalCount; + final List _transactions = List.empty(growable: true); + + Future _fetchTransactions() async { + try { + setState(() => _isBusy = true); + final sn = context.read(); + final resp = await sn.client.get('/cgi/wa/transactions/me', queryParameters: { + 'take': 10, + 'offset': _transactions.length, + }); + _totalCount = resp.data['count']; + _transactions.addAll( + resp.data['data']?.map((e) => SnTransaction.fromJson(e)).cast() ?? [], + ); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + + @override + void initState() { + super.initState(); + _fetchTransactions(); + } + + @override + Widget build(BuildContext context) { + return MediaQuery.removePadding( + context: context, + removeTop: true, + child: RefreshIndicator( + onRefresh: _fetchTransactions, + child: InfiniteList( + itemCount: _transactions.length, + isLoading: _isBusy, + hasReachedMax: _totalCount != null && _transactions.length >= _totalCount!, + onFetchData: () { + _fetchTransactions(); + }, + itemBuilder: (context, idx) { + final ele = _transactions[idx]; + final isIncoming = ele.payeeId == widget.myself.id; + return ListTile( + leading: isIncoming ? const Icon(Symbols.call_received) : const Icon(Symbols.call_made), + title: Text( + '${isIncoming ? '+' : '-'}${ele.amount} ${'walletCurrencyShort'.tr()}', + style: TextStyle(color: isIncoming ? Colors.green : Colors.red), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(ele.remark), + const Gap(2), + Text( + DateFormat( + null, + EasyLocalization.of(context)!.currentLocale.toString(), + ).format(ele.createdAt), + style: Theme.of(context).textTheme.labelSmall, + ), + ], + ), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + ); + }, + ), + ), + ); + } +} + +class _CreateWalletWidget extends StatefulWidget { + final Function()? onCreate; + + const _CreateWalletWidget({required this.onCreate}); + + @override + State<_CreateWalletWidget> createState() => _CreateWalletWidgetState(); +} + +class _CreateWalletWidgetState extends State<_CreateWalletWidget> { + bool _isBusy = false; + + Future _createWallet() async { + final TextEditingController passwordController = TextEditingController(); + final password = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text('walletCreate').tr(), + content: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text('walletCreatePassword').tr(), + const Gap(8), + TextField( + autofocus: true, + obscureText: true, + controller: passwordController, + decoration: InputDecoration( + labelText: 'fieldPassword'.tr(), + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(ctx).pop(), + child: Text('cancel').tr(), + ), + TextButton( + onPressed: () { + Navigator.of(ctx).pop(passwordController.text); + }, + child: Text('next').tr(), + ), + ], + ), + ); + WidgetsBinding.instance.addPostFrameCallback((_) { + passwordController.dispose(); + }); + if (password == null || password.isEmpty) return; + if (!mounted) return; + + try { + setState(() => _isBusy = true); + final sn = context.read(); + await sn.client.post('/cgi/wa/wallets/me', data: { + 'password': password, + }); + } catch (err) { + if (!mounted) return; + context.showErrorDialog(err); + } finally { + setState(() => _isBusy = false); + } + } + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + constraints: const BoxConstraints(maxWidth: 380), + child: Card( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CircleAvatar( + radius: 28, + child: Icon(Symbols.add, size: 28), + ), + const Gap(12), + Text('walletCreate', style: Theme.of(context).textTheme.titleLarge).tr(), + Text('walletCreateSubtitle', style: Theme.of(context).textTheme.bodyMedium).tr(), + const Gap(4), + Text('walletCreateTerms', style: Theme.of(context).textTheme.bodySmall).tr(), + const Gap(8), + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: _isBusy ? null : () => _createWallet(), + child: Text('next').tr(), + ), + ), + ], + ).padding(horizontal: 20, vertical: 24), + ), + ), + ); + } +} diff --git a/lib/types/wallet.dart b/lib/types/wallet.dart new file mode 100644 index 0000000..7f199c0 --- /dev/null +++ b/lib/types/wallet.dart @@ -0,0 +1,37 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'wallet.freezed.dart'; +part 'wallet.g.dart'; + +@freezed +class SnWallet with _$SnWallet { + const factory SnWallet({ + required int id, + required DateTime createdAt, + required DateTime updatedAt, + required DateTime? deletedAt, + required String balance, + required String password, + required int accountId, + }) = _SnWallet; + + factory SnWallet.fromJson(Map json) => _$SnWalletFromJson(json); +} + +@freezed +class SnTransaction with _$SnTransaction { + const factory SnTransaction({ + required int id, + required DateTime createdAt, + required DateTime updatedAt, + required DateTime? deletedAt, + required String remark, + required String amount, + required SnWallet? payer, + required SnWallet? payee, + required int? payerId, + required int? payeeId, + }) = _SnTransaction; + + factory SnTransaction.fromJson(Map json) => _$SnTransactionFromJson(json); +} diff --git a/lib/types/wallet.freezed.dart b/lib/types/wallet.freezed.dart new file mode 100644 index 0000000..35413aa --- /dev/null +++ b/lib/types/wallet.freezed.dart @@ -0,0 +1,666 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'wallet.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +SnWallet _$SnWalletFromJson(Map json) { + return _SnWallet.fromJson(json); +} + +/// @nodoc +mixin _$SnWallet { + int get id => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + DateTime? get deletedAt => throw _privateConstructorUsedError; + String get balance => throw _privateConstructorUsedError; + String get password => throw _privateConstructorUsedError; + int get accountId => throw _privateConstructorUsedError; + + /// Serializes this SnWallet to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SnWallet + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SnWalletCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SnWalletCopyWith<$Res> { + factory $SnWalletCopyWith(SnWallet value, $Res Function(SnWallet) then) = + _$SnWalletCopyWithImpl<$Res, SnWallet>; + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + DateTime? deletedAt, + String balance, + String password, + int accountId}); +} + +/// @nodoc +class _$SnWalletCopyWithImpl<$Res, $Val extends SnWallet> + implements $SnWalletCopyWith<$Res> { + _$SnWalletCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SnWallet + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? balance = null, + Object? password = null, + Object? accountId = null, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + balance: null == balance + ? _value.balance + : balance // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + accountId: null == accountId + ? _value.accountId + : accountId // ignore: cast_nullable_to_non_nullable + as int, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$SnWalletImplCopyWith<$Res> + implements $SnWalletCopyWith<$Res> { + factory _$$SnWalletImplCopyWith( + _$SnWalletImpl value, $Res Function(_$SnWalletImpl) then) = + __$$SnWalletImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + DateTime? deletedAt, + String balance, + String password, + int accountId}); +} + +/// @nodoc +class __$$SnWalletImplCopyWithImpl<$Res> + extends _$SnWalletCopyWithImpl<$Res, _$SnWalletImpl> + implements _$$SnWalletImplCopyWith<$Res> { + __$$SnWalletImplCopyWithImpl( + _$SnWalletImpl _value, $Res Function(_$SnWalletImpl) _then) + : super(_value, _then); + + /// Create a copy of SnWallet + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? balance = null, + Object? password = null, + Object? accountId = null, + }) { + return _then(_$SnWalletImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + balance: null == balance + ? _value.balance + : balance // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + accountId: null == accountId + ? _value.accountId + : accountId // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SnWalletImpl implements _SnWallet { + const _$SnWalletImpl( + {required this.id, + required this.createdAt, + required this.updatedAt, + required this.deletedAt, + required this.balance, + required this.password, + required this.accountId}); + + factory _$SnWalletImpl.fromJson(Map json) => + _$$SnWalletImplFromJson(json); + + @override + final int id; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + @override + final DateTime? deletedAt; + @override + final String balance; + @override + final String password; + @override + final int accountId; + + @override + String toString() { + return 'SnWallet(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, balance: $balance, password: $password, accountId: $accountId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SnWalletImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + (identical(other.deletedAt, deletedAt) || + other.deletedAt == deletedAt) && + (identical(other.balance, balance) || other.balance == balance) && + (identical(other.password, password) || + other.password == password) && + (identical(other.accountId, accountId) || + other.accountId == accountId)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, id, createdAt, updatedAt, + deletedAt, balance, password, accountId); + + /// Create a copy of SnWallet + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SnWalletImplCopyWith<_$SnWalletImpl> get copyWith => + __$$SnWalletImplCopyWithImpl<_$SnWalletImpl>(this, _$identity); + + @override + Map toJson() { + return _$$SnWalletImplToJson( + this, + ); + } +} + +abstract class _SnWallet implements SnWallet { + const factory _SnWallet( + {required final int id, + required final DateTime createdAt, + required final DateTime updatedAt, + required final DateTime? deletedAt, + required final String balance, + required final String password, + required final int accountId}) = _$SnWalletImpl; + + factory _SnWallet.fromJson(Map json) = + _$SnWalletImpl.fromJson; + + @override + int get id; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + @override + DateTime? get deletedAt; + @override + String get balance; + @override + String get password; + @override + int get accountId; + + /// Create a copy of SnWallet + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SnWalletImplCopyWith<_$SnWalletImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SnTransaction _$SnTransactionFromJson(Map json) { + return _SnTransaction.fromJson(json); +} + +/// @nodoc +mixin _$SnTransaction { + int get id => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + DateTime? get deletedAt => throw _privateConstructorUsedError; + String get remark => throw _privateConstructorUsedError; + String get amount => throw _privateConstructorUsedError; + SnWallet? get payer => throw _privateConstructorUsedError; + SnWallet? get payee => throw _privateConstructorUsedError; + int? get payerId => throw _privateConstructorUsedError; + int? get payeeId => throw _privateConstructorUsedError; + + /// Serializes this SnTransaction to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SnTransactionCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SnTransactionCopyWith<$Res> { + factory $SnTransactionCopyWith( + SnTransaction value, $Res Function(SnTransaction) then) = + _$SnTransactionCopyWithImpl<$Res, SnTransaction>; + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + DateTime? deletedAt, + String remark, + String amount, + SnWallet? payer, + SnWallet? payee, + int? payerId, + int? payeeId}); + + $SnWalletCopyWith<$Res>? get payer; + $SnWalletCopyWith<$Res>? get payee; +} + +/// @nodoc +class _$SnTransactionCopyWithImpl<$Res, $Val extends SnTransaction> + implements $SnTransactionCopyWith<$Res> { + _$SnTransactionCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? remark = null, + Object? amount = null, + Object? payer = freezed, + Object? payee = freezed, + Object? payerId = freezed, + Object? payeeId = freezed, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + remark: null == remark + ? _value.remark + : remark // ignore: cast_nullable_to_non_nullable + as String, + amount: null == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as String, + payer: freezed == payer + ? _value.payer + : payer // ignore: cast_nullable_to_non_nullable + as SnWallet?, + payee: freezed == payee + ? _value.payee + : payee // ignore: cast_nullable_to_non_nullable + as SnWallet?, + payerId: freezed == payerId + ? _value.payerId + : payerId // ignore: cast_nullable_to_non_nullable + as int?, + payeeId: freezed == payeeId + ? _value.payeeId + : payeeId // ignore: cast_nullable_to_non_nullable + as int?, + ) as $Val); + } + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SnWalletCopyWith<$Res>? get payer { + if (_value.payer == null) { + return null; + } + + return $SnWalletCopyWith<$Res>(_value.payer!, (value) { + return _then(_value.copyWith(payer: value) as $Val); + }); + } + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SnWalletCopyWith<$Res>? get payee { + if (_value.payee == null) { + return null; + } + + return $SnWalletCopyWith<$Res>(_value.payee!, (value) { + return _then(_value.copyWith(payee: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SnTransactionImplCopyWith<$Res> + implements $SnTransactionCopyWith<$Res> { + factory _$$SnTransactionImplCopyWith( + _$SnTransactionImpl value, $Res Function(_$SnTransactionImpl) then) = + __$$SnTransactionImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {int id, + DateTime createdAt, + DateTime updatedAt, + DateTime? deletedAt, + String remark, + String amount, + SnWallet? payer, + SnWallet? payee, + int? payerId, + int? payeeId}); + + @override + $SnWalletCopyWith<$Res>? get payer; + @override + $SnWalletCopyWith<$Res>? get payee; +} + +/// @nodoc +class __$$SnTransactionImplCopyWithImpl<$Res> + extends _$SnTransactionCopyWithImpl<$Res, _$SnTransactionImpl> + implements _$$SnTransactionImplCopyWith<$Res> { + __$$SnTransactionImplCopyWithImpl( + _$SnTransactionImpl _value, $Res Function(_$SnTransactionImpl) _then) + : super(_value, _then); + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? deletedAt = freezed, + Object? remark = null, + Object? amount = null, + Object? payer = freezed, + Object? payee = freezed, + Object? payerId = freezed, + Object? payeeId = freezed, + }) { + return _then(_$SnTransactionImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + deletedAt: freezed == deletedAt + ? _value.deletedAt + : deletedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + remark: null == remark + ? _value.remark + : remark // ignore: cast_nullable_to_non_nullable + as String, + amount: null == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as String, + payer: freezed == payer + ? _value.payer + : payer // ignore: cast_nullable_to_non_nullable + as SnWallet?, + payee: freezed == payee + ? _value.payee + : payee // ignore: cast_nullable_to_non_nullable + as SnWallet?, + payerId: freezed == payerId + ? _value.payerId + : payerId // ignore: cast_nullable_to_non_nullable + as int?, + payeeId: freezed == payeeId + ? _value.payeeId + : payeeId // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$SnTransactionImpl implements _SnTransaction { + const _$SnTransactionImpl( + {required this.id, + required this.createdAt, + required this.updatedAt, + required this.deletedAt, + required this.remark, + required this.amount, + required this.payer, + required this.payee, + required this.payerId, + required this.payeeId}); + + factory _$SnTransactionImpl.fromJson(Map json) => + _$$SnTransactionImplFromJson(json); + + @override + final int id; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + @override + final DateTime? deletedAt; + @override + final String remark; + @override + final String amount; + @override + final SnWallet? payer; + @override + final SnWallet? payee; + @override + final int? payerId; + @override + final int? payeeId; + + @override + String toString() { + return 'SnTransaction(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, remark: $remark, amount: $amount, payer: $payer, payee: $payee, payerId: $payerId, payeeId: $payeeId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SnTransactionImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + (identical(other.deletedAt, deletedAt) || + other.deletedAt == deletedAt) && + (identical(other.remark, remark) || other.remark == remark) && + (identical(other.amount, amount) || other.amount == amount) && + (identical(other.payer, payer) || other.payer == payer) && + (identical(other.payee, payee) || other.payee == payee) && + (identical(other.payerId, payerId) || other.payerId == payerId) && + (identical(other.payeeId, payeeId) || other.payeeId == payeeId)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, id, createdAt, updatedAt, + deletedAt, remark, amount, payer, payee, payerId, payeeId); + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SnTransactionImplCopyWith<_$SnTransactionImpl> get copyWith => + __$$SnTransactionImplCopyWithImpl<_$SnTransactionImpl>(this, _$identity); + + @override + Map toJson() { + return _$$SnTransactionImplToJson( + this, + ); + } +} + +abstract class _SnTransaction implements SnTransaction { + const factory _SnTransaction( + {required final int id, + required final DateTime createdAt, + required final DateTime updatedAt, + required final DateTime? deletedAt, + required final String remark, + required final String amount, + required final SnWallet? payer, + required final SnWallet? payee, + required final int? payerId, + required final int? payeeId}) = _$SnTransactionImpl; + + factory _SnTransaction.fromJson(Map json) = + _$SnTransactionImpl.fromJson; + + @override + int get id; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + @override + DateTime? get deletedAt; + @override + String get remark; + @override + String get amount; + @override + SnWallet? get payer; + @override + SnWallet? get payee; + @override + int? get payerId; + @override + int? get payeeId; + + /// Create a copy of SnTransaction + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SnTransactionImplCopyWith<_$SnTransactionImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/types/wallet.g.dart b/lib/types/wallet.g.dart new file mode 100644 index 0000000..e4fa420 --- /dev/null +++ b/lib/types/wallet.g.dart @@ -0,0 +1,65 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'wallet.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$SnWalletImpl _$$SnWalletImplFromJson(Map json) => + _$SnWalletImpl( + id: (json['id'] as num).toInt(), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), + balance: json['balance'] as String, + password: json['password'] as String, + accountId: (json['account_id'] as num).toInt(), + ); + +Map _$$SnWalletImplToJson(_$SnWalletImpl instance) => + { + 'id': instance.id, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), + 'balance': instance.balance, + 'password': instance.password, + 'account_id': instance.accountId, + }; + +_$SnTransactionImpl _$$SnTransactionImplFromJson(Map json) => + _$SnTransactionImpl( + id: (json['id'] as num).toInt(), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), + remark: json['remark'] as String, + amount: json['amount'] as String, + payer: json['payer'] == null + ? null + : SnWallet.fromJson(json['payer'] as Map), + payee: json['payee'] == null + ? null + : SnWallet.fromJson(json['payee'] as Map), + payerId: (json['payer_id'] as num?)?.toInt(), + payeeId: (json['payee_id'] as num?)?.toInt(), + ); + +Map _$$SnTransactionImplToJson(_$SnTransactionImpl instance) => + { + 'id': instance.id, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), + 'remark': instance.remark, + 'amount': instance.amount, + 'payer': instance.payer?.toJson(), + 'payee': instance.payee?.toJson(), + 'payer_id': instance.payerId, + 'payee_id': instance.payeeId, + };