-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
お気に入りユーザー一覧画面実装 #49
base: develop
Are you sure you want to change the base?
お気に入りユーザー一覧画面実装 #49
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:pg_mobile/constants/app_colors.dart'; | ||
import 'package:pg_mobile/providers/favorite_user_list_notifier.dart'; | ||
import 'package:pg_mobile/widgets/favorite_user_item.dart'; | ||
|
||
class DebugFavoriteUserListPage extends ConsumerStatefulWidget { | ||
const DebugFavoriteUserListPage({required this.statusId, super.key}); | ||
final String statusId; | ||
|
||
@override | ||
ConsumerState<DebugFavoriteUserListPage> createState() => | ||
_DebugFavoriteUserListPageState(); | ||
} | ||
|
||
class _DebugFavoriteUserListPageState | ||
extends ConsumerState<DebugFavoriteUserListPage> { | ||
@override | ||
void initState() { | ||
super.initState(); | ||
// ボタンを押したら、すぐに画面遷移できるようにinitStateでAPIからデータを取得 | ||
Future(() async { | ||
await ref | ||
.read(favoriteUserListProvider.notifier) | ||
.fetchFavoriteUserList(widget.statusId); | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final favoriteUserAccountList = ref.watch( | ||
favoriteUserListProvider.select((value) => value.favoriteUserAccountList), | ||
); | ||
final isLoading = | ||
ref.watch(favoriteUserListProvider.select((value) => value.isLoading)); | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: const Text('Favorite'), | ||
), | ||
body: isLoading && favoriteUserAccountList.isEmpty | ||
? const Center( | ||
child: CupertinoActivityIndicator(), | ||
) | ||
: ListView.builder( | ||
itemCount: favoriteUserAccountList.length, | ||
itemBuilder: (BuildContext context, int index) { | ||
return Column( | ||
children: [ | ||
FavoriteUserItem( | ||
account: favoriteUserAccountList[index], | ||
), | ||
const Divider( | ||
thickness: 1, | ||
height: 0, | ||
color: AppColors.gray2, | ||
), | ||
], | ||
); | ||
}, | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import 'package:freezed_annotation/freezed_annotation.dart'; | ||
import 'package:pg_mobile/models/mastodon/account.dart'; | ||
|
||
part 'favorite_user_list.freezed.dart'; | ||
|
||
@freezed | ||
class FavoriteUserList with _$FavoriteUserList { | ||
const factory FavoriteUserList({ | ||
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このクラス名だと、Listだけ持ってるクラスを連想しちゃう人も少なからずいると思うので、 |
||
@Default([]) List<Account> favoriteUserAccountList, | ||
@Default(false) bool isLoading, | ||
}) = _FavoriteUserList; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:pg_mobile/models/mastodon/favorite_user_list.dart'; | ||
import 'package:pg_mobile/repository/mastodon_repository.dart'; | ||
|
||
final favoriteUserListProvider = | ||
StateNotifierProvider<FavoriteUserListNotifier, FavoriteUserList>((ref) { | ||
return FavoriteUserListNotifier(); | ||
}); | ||
|
||
class FavoriteUserListNotifier extends StateNotifier<FavoriteUserList> { | ||
FavoriteUserListNotifier() : super(const FavoriteUserList()); | ||
|
||
Future<void> fetchFavoriteUserList(String statusId) async { | ||
state = state.copyWith(isLoading: true); | ||
final favoriteUserAccountList = | ||
await MastodonRepository.instance.fetchFavoriteUserList(statusId); | ||
state = state.copyWith(favoriteUserAccountList: favoriteUserAccountList); | ||
state = state.copyWith(isLoading: false); | ||
} | ||
|
||
void resetData() { | ||
state = state.copyWith( | ||
favoriteUserAccountList: [], | ||
isLoading: false, | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class PgMobileDefaultButton extends StatelessWidget { | ||
const PgMobileDefaultButton({ | ||
required this.backgroundColor, | ||
required this.onPressed, | ||
required this.buttonText, | ||
required this.buttonTextStyle, | ||
required this.buttonHeight, | ||
required this.buttonWidth, | ||
super.key, | ||
}); | ||
final Color backgroundColor; | ||
final void Function() onPressed; | ||
final String buttonText; | ||
final TextStyle buttonTextStyle; | ||
final double buttonHeight; | ||
final double buttonWidth; | ||
Comment on lines
+3
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. クラスの命名について
クラス引数についてアプリ内で頻繁に使うWidgetにしてはrequiredの引数が少し多い気がします。引数でWidgetを自由にカスタマイズできる点はとても良いと思うのですが、クラスのインスタンスを生成するたびに6種類の引数を必ず入れないといけないのは、ちょっと使いづらい気がします。こういうクラスを設計する場合は、requiredだけでなく、デフォルト値とかも使ってみるとrequiredが減っていいんじゃないかなと思います。 UIコンポーネントの必要性についてそもそもUIコンポーネントのクラスを作る必要があるか考えてみてほしいです。同じ部分を共通化しようという考えはめちゃくちゃ大事ですし、これからも大事にしてほしいです。 |
||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return SizedBox( | ||
height: buttonHeight, | ||
width: buttonWidth, | ||
child: ElevatedButton( | ||
style: ElevatedButton.styleFrom( | ||
elevation: 0, | ||
backgroundColor: backgroundColor, | ||
), | ||
onPressed: onPressed, | ||
child: Text( | ||
buttonText, | ||
style: buttonTextStyle, | ||
), | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
import 'package:pg_mobile/constants/app_colors.dart'; | ||
import 'package:pg_mobile/models/mastodon/account.dart'; | ||
import 'package:pg_mobile/widgets/buttons/pg_mobile_default_button.dart'; | ||
import 'package:pg_mobile/widgets/network_image_container.dart'; | ||
|
||
class FavoriteUserItem extends StatelessWidget { | ||
const FavoriteUserItem({required this.account, super.key}); | ||
final Account account; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Padding( | ||
padding: const EdgeInsets.symmetric( | ||
horizontal: 16, | ||
vertical: 8, | ||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 余白もレイアウトの一種なので、他の箇所と同じように |
||
), | ||
child: Row( | ||
children: [ | ||
NetworkImageContainer( | ||
imageUrl: account.avatar, | ||
height: 64.h, | ||
width: 64.w, | ||
boxShape: BoxShape.circle, | ||
), | ||
SizedBox(width: 16.w), | ||
Expanded( | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
Text( | ||
account.displayName, | ||
style: Theme.of(context).textTheme.bodyMedium, | ||
), | ||
SizedBox(height: 5.h), | ||
Text( | ||
'@${account.username}', | ||
style: Theme.of(context) | ||
.textTheme | ||
.bodyMedium! | ||
.copyWith(color: AppColors.gray3), | ||
), | ||
], | ||
), | ||
), | ||
PgMobileDefaultButton( | ||
backgroundColor: AppColors.accent, | ||
onPressed: () {}, | ||
buttonText: 'フォロー', | ||
buttonTextStyle: Theme.of(context) | ||
.textTheme | ||
.bodySmall! | ||
.copyWith(fontWeight: FontWeight.w700), | ||
buttonHeight: 32.h, | ||
buttonWidth: 104.w, | ||
), | ||
], | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,12 @@ import 'package:flutter/material.dart'; | |
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
import 'package:pg_mobile/constants/app_colors.dart'; | ||
import 'package:pg_mobile/debug/debug_favorite_user_list_page.dart'; | ||
import 'package:pg_mobile/debug/debug_thread_page.dart'; | ||
import 'package:pg_mobile/models/mastodon/account.dart'; | ||
import 'package:pg_mobile/models/mastodon/status.dart'; | ||
import 'package:pg_mobile/models/mastodon/status_menu_action.dart'; | ||
import 'package:pg_mobile/providers/favorite_user_list_notifier.dart'; | ||
import 'package:pg_mobile/providers/signed_in_user_notifier.dart'; | ||
import 'package:pg_mobile/providers/timeline_notifier.dart'; | ||
import 'package:pg_mobile/util/navigator_util.dart'; | ||
|
@@ -88,8 +90,13 @@ class _StatusItemState extends ConsumerState<StatusItem> { | |
// TODO: ブーストを押したユーザー一覧を表示する画面へ遷移 | ||
} | ||
|
||
void _onTapEngagementFavorite() { | ||
// TODO: お気に入りを押したユーザー一覧を表示する画面へ遷移 | ||
void _onTapEngagementFavorite(String statusId) { | ||
// 画面のチラつきを防ぐために今までのデータをリセットする | ||
ref.read(favoriteUserListProvider.notifier).resetData(); | ||
Comment on lines
+94
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 勉強になります✨ |
||
NavigatorUtil.pushScreen( | ||
context, | ||
DebugFavoriteUserListPage(statusId: statusId), | ||
); | ||
} | ||
|
||
void _onTapMenu(List<StatusMenuAction> actions) { | ||
|
@@ -277,7 +284,8 @@ class _StatusItemState extends ConsumerState<StatusItem> { | |
StatusDetailsEngagementView( | ||
status: widget.status, | ||
onTapReblog: _onTapEngagementReblog, | ||
onTapFavorite: _onTapEngagementFavorite, | ||
onTapFavorite: () => | ||
_onTapEngagementFavorite(widget.status.id), | ||
), | ||
SizedBox(height: 8.h), | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍