diff --git a/lib/analytics.dart b/lib/analytics.dart index 9bbef76..41fcf06 100644 --- a/lib/analytics.dart +++ b/lib/analytics.dart @@ -5,7 +5,7 @@ import 'package:nererun/entity/off_timer_type.dart'; import 'package:nererun/entity/product.dart'; import 'package:nererun/entity/top_banner_setting.dart'; -final firebaseAnalytics = FirebaseAnalytics(); +final firebaseAnalytics = FirebaseAnalytics.instance; class Analytics { String screenName = ''; diff --git a/lib/feature/home/home.dart b/lib/feature/home/home.dart index 13ef8fe..53d6ac0 100644 --- a/lib/feature/home/home.dart +++ b/lib/feature/home/home.dart @@ -76,7 +76,6 @@ class HomeScreen extends HookConsumerWidget { ); }, error: (error, stackTrace) { - ref.refresh(homeAsyncStateProvider); return Container(); }, loading: () => const ScaffoldIndicator(), diff --git a/lib/feature/off_timer/off_timer_page.dart b/lib/feature/off_timer/off_timer_page.dart index cccc92a..b5e635f 100644 --- a/lib/feature/off_timer/off_timer_page.dart +++ b/lib/feature/off_timer/off_timer_page.dart @@ -7,7 +7,6 @@ import 'package:nererun/components/scaffold_indicator.dart'; import 'package:nererun/entity/off_timer_type.dart'; import 'package:nererun/feature/off_timer/components/off_timer_button.dart'; import 'package:nererun/feature/off_timer/off_timer_page_current_type_state.dart'; -import 'package:nererun/feature/off_timer/off_timer_page_state.codegen.dart'; import 'package:nererun/feature/off_timer/off_timer_page_state_notifier.dart'; import 'package:nererun/resource/color.dart'; import 'package:nererun/resource/text_style.dart'; @@ -76,7 +75,6 @@ class OffTimerScreen extends HookConsumerWidget { ); }, error: (error, stackTrace) { - ref.refresh(offTimerStateProvider); return Container(); }, loading: () => const ScaffoldIndicator(), diff --git a/lib/feature/premium/components/premium_purchase.dart b/lib/feature/premium/components/premium_purchase.dart deleted file mode 100644 index da2765e..0000000 --- a/lib/feature/premium/components/premium_purchase.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:nererun/feature/premium/components/premium_purchase_mini_button.dart'; -import 'package:nererun/feature/premium/components/premium_restore_mini_button.dart'; -import 'package:nererun/resource/color.dart'; -import 'package:nererun/resource/text_style.dart'; -import 'package:nererun/util/assets.dart'; - -class PremiumPurchase extends StatelessWidget { - final Function(BuildContext context) purchase; - final Function(BuildContext context) restore; - - const PremiumPurchase({ - Key? key, - required this.purchase, - required this.restore, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Stack( - children: [ - Image.asset( - Assets.png('premium_background'), - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.width, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 32), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 56), - Image.asset( - Assets.png('premium_header'), - width: 238, - height: 43, - ), - const SizedBox(height: 8), - Text( - '¥960/ 月を\n2週間無料でお試し', - style: AppTextStyle.header2(AppColor.white), - ), - const SizedBox(height: 16), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(left: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '登録から13日後の解約期限までに\n解約した場合、料金は一切かかりません', - style: AppTextStyle.body1(AppColor.white), - ), - const SizedBox(height: 16), - Row( - children: [ - PremiumPurchaseMiniButton(onTap: purchase), - const SizedBox(width: 12), - PremiumRestoreMiniButton(onTap: restore), - ], - ), - const SizedBox(height: 16), - Text( - '※無料トライアルは初めて登録する方が対象です', - style: AppTextStyle.body4(AppColor.gray3), - ), - ], - ), - ), - ], - ), - ], - ); - } -} diff --git a/lib/feature/premium/components/premium_purchase_button.dart b/lib/feature/premium/components/premium_purchase_button.dart deleted file mode 100644 index b9ad759..0000000 --- a/lib/feature/premium/components/premium_purchase_button.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:nererun/components/rounded.dart'; -import 'package:nererun/resource/color.dart'; -import 'package:nererun/resource/text_style.dart'; - -class PremiumPurchaseButton extends StatelessWidget { - final Function(BuildContext context) onTap; - - const PremiumPurchaseButton({ - Key? key, - required this.onTap, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return RoundedInk( - key, - radius: 8, - color: AppColor.blue, - onTap: onTap, - child: SizedBox( - height: 58, - width: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'ネレルン プレミアムに登録', - style: AppTextStyle.body1(AppColor.white), - ), - Text( - '¥960/月', - style: AppTextStyle.body2(AppColor.white), - ), - ], - ), - ), - ); - } -} diff --git a/lib/feature/premium/components/premium_purchase_mini_button.dart b/lib/feature/premium/components/premium_purchase_mini_button.dart deleted file mode 100644 index 7f373be..0000000 --- a/lib/feature/premium/components/premium_purchase_mini_button.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:nererun/components/rounded.dart'; -import 'package:nererun/resource/color.dart'; -import 'package:nererun/resource/text_style.dart'; - -class PremiumPurchaseMiniButton extends StatelessWidget { - final Function(BuildContext context) onTap; - - const PremiumPurchaseMiniButton({ - Key? key, - required this.onTap, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return RoundedInk( - key, - radius: 20, - color: AppColor.blue, - onTap: onTap, - child: SizedBox( - height: 40, - width: 188, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Spacer(), - Text( - 'ネレルン プレミアムに登録', - style: AppTextStyle.body2(AppColor.white), - ), - const Spacer(), - ], - ), - ), - ); - } -} diff --git a/lib/feature/premium/components/premium_restore_mini_button.dart b/lib/feature/premium/components/premium_restore_mini_button.dart deleted file mode 100644 index 2a38999..0000000 --- a/lib/feature/premium/components/premium_restore_mini_button.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:nererun/components/rounded.dart'; -import 'package:nererun/resource/color.dart'; -import 'package:nererun/resource/text_style.dart'; - -class PremiumRestoreMiniButton extends StatelessWidget { - final Function(BuildContext context) onTap; - - const PremiumRestoreMiniButton({ - Key? key, - required this.onTap, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return RoundedInk( - key, - radius: 20, - onTap: onTap, - child: SizedBox( - height: 40, - width: 115, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Spacer(), - Text( - '登録済みの方', - style: AppTextStyle.body2(AppColor.black), - ), - const Spacer(), - ], - ), - ), - ); - } -} diff --git a/lib/feature/premium/premium_sheet.dart b/lib/feature/premium/premium_sheet.dart deleted file mode 100644 index 860f21d..0000000 --- a/lib/feature/premium/premium_sheet.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:nererun/components/gradient_scaffold.dart'; -import 'package:nererun/components/nererun_app_bar.dart'; -import 'package:nererun/components/scaffold_indicator.dart'; -import 'package:nererun/feature/premium/components/premium_purchase.dart'; -import 'package:nererun/feature/premium/components/premium_purchase_button.dart'; -import 'package:nererun/feature/premium/premium_sheet_state_notifier.dart'; -import 'package:nererun/feature/premium/premium_state.codegen.dart'; -import 'package:nererun/resource/color.dart'; -import 'package:nererun/resource/text_style.dart'; -import 'package:nererun/util/assets.dart'; - -class PremiumSheet extends HookConsumerWidget { - const PremiumSheet({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final store = ref.watch(premiumSheetStateNotifierProvider.notifier); - final state = ref.watch(premiumSheetStateNotifierProvider); - - return state.when( - data: (state) => _PremiumSheet(state: state, store: store), - error: (error, _) => Container(), - loading: () => const ScaffoldIndicator(), - ); - } -} - -class _PremiumSheet extends StatelessWidget { - final PremiumState state; - final PremiumSheetStateNotifier store; - - const _PremiumSheet({ - Key? key, - required this.state, - required this.store, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return GradientScaffold( - appBar: NererunAppBar(), - body: SingleChildScrollView( - child: Column( - children: [ - PremiumPurchase( - purchase: (_) => store.asyncAction.purchase(), - restore: (_) async { - final snackbar = await store.asyncAction.restore(); - if (snackbar) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - duration: Duration(seconds: 2), - content: Text("購入情報を復元しました"), - ), - ); - } - }, - ), - Image.asset(Assets.png('premium_nererun_function')), - const SizedBox(height: 40), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: PremiumPurchaseButton( - onTap: (_) => store.asyncAction.purchase(), - ), - ), - const SizedBox(height: 40), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Image.asset(Assets.png('premium_short_blurb')), - ), - const SizedBox(height: 40), - Image.asset(Assets.png('premium_picture_book_diff')), - const SizedBox(height: 40), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: PremiumPurchaseButton( - onTap: (_) => store.asyncAction.purchase(), - ), - ), - const SizedBox(height: 40), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( - '無料トライアルは初めて登録される方が対象です。無料トライアル終了後は、通常価格の960円/月に自動で更新されます。購入後のお支払いはApple IDアカウントに請求されます。更新日時の24時間前までに解約しない限り、登録が自動更新されます。AppStoreの設定から解約することができます。自動更新後の料金(960円)は、更新日時前の24時間以内に請求されます。', - style: AppTextStyle.body4(AppColor.gray2), - ), - ), - const SizedBox(height: 80), - ], - ), - ), - ); - } -} diff --git a/lib/feature/premium/premium_sheet_async_action.dart b/lib/feature/premium/premium_sheet_async_action.dart deleted file mode 100644 index 1428c8a..0000000 --- a/lib/feature/premium/premium_sheet_async_action.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:nererun/service/purchase.dart'; -import 'package:riverpod/riverpod.dart'; - -final premiumSheetAsyncActionProvider = Provider( - (ref) => PremiumSheetAsyncAction(), -); - -class PremiumSheetAsyncAction { - Future purchase() async {} - - Future restore() async => callRestorePurchaseInfo(); -} diff --git a/lib/feature/premium/premium_sheet_state_notifier.dart b/lib/feature/premium/premium_sheet_state_notifier.dart deleted file mode 100644 index 4d91080..0000000 --- a/lib/feature/premium/premium_sheet_state_notifier.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:nererun/feature/premium/premium_sheet_async_action.dart'; -import 'package:nererun/feature/premium/premium_state.codegen.dart'; -import 'package:riverpod/riverpod.dart'; - -final premiumSheetStateNotifierProvider = - StateNotifierProvider>( - (ref) => PremiumSheetStateNotifier( - asyncAction: ref.watch(premiumSheetAsyncActionProvider), - initialState: ref.watch(premiumSheetStateProvider), - ), -); - -class PremiumSheetStateNotifier - extends StateNotifier> { - final PremiumSheetAsyncAction asyncAction; - - PremiumSheetStateNotifier({ - required this.asyncAction, - required AsyncValue initialState, - }) : super(initialState); -} diff --git a/lib/feature/premium/premium_state.codegen.dart b/lib/feature/premium/premium_state.codegen.dart deleted file mode 100644 index 893fc17..0000000 --- a/lib/feature/premium/premium_state.codegen.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:nererun/entity/user.dart'; -import 'package:nererun/provider/user.dart'; -import 'package:riverpod/riverpod.dart'; - -part 'premium_state.codegen.freezed.dart'; - -@freezed -class PremiumState with _$PremiumState { - factory PremiumState({ - required User user, - }) = _PremiumState; - PremiumState._(); -} - -final premiumSheetStateProvider = Provider>((ref) { - final user = ref.watch(userStreamProvider).value; - - if (user == null) { - return const AsyncLoading(); - } - - try { - return AsyncValue.data(PremiumState( - user: user, - )); - } catch (error, stackTrace) { - return AsyncValue.error(error, stackTrace); - } -}); diff --git a/lib/feature/premium/premium_state.codegen.freezed.dart b/lib/feature/premium/premium_state.codegen.freezed.dart deleted file mode 100644 index 9caae56..0000000 --- a/lib/feature/premium/premium_state.codegen.freezed.dart +++ /dev/null @@ -1,142 +0,0 @@ -// 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 - -part of 'premium_state.codegen.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#custom-getters-and-methods'); - -/// @nodoc -mixin _$PremiumState { - User get user => throw _privateConstructorUsedError; - - @JsonKey(ignore: true) - $PremiumStateCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $PremiumStateCopyWith<$Res> { - factory $PremiumStateCopyWith( - PremiumState value, $Res Function(PremiumState) then) = - _$PremiumStateCopyWithImpl<$Res>; - $Res call({User user}); - - $UserCopyWith<$Res> get user; -} - -/// @nodoc -class _$PremiumStateCopyWithImpl<$Res> implements $PremiumStateCopyWith<$Res> { - _$PremiumStateCopyWithImpl(this._value, this._then); - - final PremiumState _value; - // ignore: unused_field - final $Res Function(PremiumState) _then; - - @override - $Res call({ - Object? user = freezed, - }) { - return _then(_value.copyWith( - user: user == freezed - ? _value.user - : user // ignore: cast_nullable_to_non_nullable - as User, - )); - } - - @override - $UserCopyWith<$Res> get user { - return $UserCopyWith<$Res>(_value.user, (value) { - return _then(_value.copyWith(user: value)); - }); - } -} - -/// @nodoc -abstract class _$$_PremiumStateCopyWith<$Res> - implements $PremiumStateCopyWith<$Res> { - factory _$$_PremiumStateCopyWith( - _$_PremiumState value, $Res Function(_$_PremiumState) then) = - __$$_PremiumStateCopyWithImpl<$Res>; - @override - $Res call({User user}); - - @override - $UserCopyWith<$Res> get user; -} - -/// @nodoc -class __$$_PremiumStateCopyWithImpl<$Res> - extends _$PremiumStateCopyWithImpl<$Res> - implements _$$_PremiumStateCopyWith<$Res> { - __$$_PremiumStateCopyWithImpl( - _$_PremiumState _value, $Res Function(_$_PremiumState) _then) - : super(_value, (v) => _then(v as _$_PremiumState)); - - @override - _$_PremiumState get _value => super._value as _$_PremiumState; - - @override - $Res call({ - Object? user = freezed, - }) { - return _then(_$_PremiumState( - user: user == freezed - ? _value.user - : user // ignore: cast_nullable_to_non_nullable - as User, - )); - } -} - -/// @nodoc - -class _$_PremiumState extends _PremiumState { - _$_PremiumState({required this.user}) : super._(); - - @override - final User user; - - @override - String toString() { - return 'PremiumState(user: $user)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_PremiumState && - const DeepCollectionEquality().equals(other.user, user)); - } - - @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(user)); - - @JsonKey(ignore: true) - @override - _$$_PremiumStateCopyWith<_$_PremiumState> get copyWith => - __$$_PremiumStateCopyWithImpl<_$_PremiumState>(this, _$identity); -} - -abstract class _PremiumState extends PremiumState { - factory _PremiumState({required final User user}) = _$_PremiumState; - _PremiumState._() : super._(); - - @override - User get user; - @override - @JsonKey(ignore: true) - _$$_PremiumStateCopyWith<_$_PremiumState> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/lib/feature/routes.dart b/lib/feature/routes.dart index 02bf6a5..43ceb15 100644 --- a/lib/feature/routes.dart +++ b/lib/feature/routes.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:nererun/entity/product.dart'; import 'package:nererun/feature/off_timer/off_timer_page.dart'; -import 'package:nererun/feature/premium/premium_sheet.dart'; import 'package:nererun/feature/product/product_page.dart'; import 'package:nererun/feature/about/about.dart'; @@ -13,14 +12,6 @@ class Routes { ); } - static premiumRoute() { - return MaterialPageRoute( - fullscreenDialog: true, - settings: const RouteSettings(name: 'PremiumSheet'), - builder: (_) => const PremiumSheet(), - ); - } - static productRoute(Product product) { return MaterialPageRoute( settings: const RouteSettings(name: 'ProductPage'), diff --git a/lib/service/purchase.dart b/lib/service/purchase.dart deleted file mode 100644 index bd2bcaa..0000000 --- a/lib/service/purchase.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:flutter/services.dart'; -import 'package:nererun/database/database.dart'; -import 'package:nererun/datastore/user.dart'; -import 'package:purchases_flutter/purchases_flutter.dart'; - -const premiumEntitlements = "Premium"; - -Future initialzePurchase(String uid) async { - await Purchases.setDebugLogsEnabled(true); - await Purchases.setup('apiKey', appUserId: uid); - Purchases.addPurchaserInfoUpdateListener(_callUpdatePurchaseInfo); - - await _syncPurchaseInfo(); -} - -Future callRestorePurchaseInfo() async { - try { - final info = await Purchases.restoreTransactions(); - final entitlements = info.entitlements.all[premiumEntitlements]; - - if (entitlements != null && entitlements.isActive) { - await _callUpdatePurchaseInfo(info); - return Future.value(true); - } - throw Exception('以前の購入情報が見つかりません。アカウントをお確かめの上再度お試しください'); - } on PlatformException catch (exception, stack) { - print(exception); - print(stack); - rethrow; - } catch (exception, stack) { - print(exception); - print(stack); - rethrow; - } -} - -Future _callUpdatePurchaseInfo(PurchaserInfo info) async { - final uid = FirebaseAuth.instance.currentUser?.uid; - if (uid == null) return; - - final userDatastore = UserDatastore(DatabaseConnection(uid)); - final premiumEntitlement = info.entitlements.all[premiumEntitlements]; - try { - await userDatastore.updatePurchaseInfo( - isActivated: premiumEntitlement?.isActive, - entitlementIdentifier: premiumEntitlement?.identifier, - premiumPlanIdentifier: premiumEntitlement?.productIdentifier, - purchaseAppID: info.originalAppUserId, - activeSubscriptions: info.activeSubscriptions, - originalPurchaseDate: info.originalPurchaseDate, - ); - } catch (exception, stack) { - print(exception); - print(stack); - } -} - -Future _syncPurchaseInfo() async { - final uid = FirebaseAuth.instance.currentUser?.uid; - if (uid == null) return; - - final purchaseInfo = await Purchases.getPurchaserInfo(); - final premiumEntitlement = purchaseInfo.entitlements.all[premiumEntitlements]; - final isActivated = - premiumEntitlement == null ? false : premiumEntitlement.isActive; - - try { - final userDatastore = UserDatastore(DatabaseConnection(uid)); - await userDatastore.syncPurchaseInfo(isActivated: isActivated); - } catch (exception, stack) { - print(exception); - print(stack); - return; - } -} diff --git a/pubspec.yaml b/pubspec.yaml index 4c31962..2e428ee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: 'none' version: 2022.12.2+24 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.15.0 <3.0.0" dependencies: flutter: