Skip to content

Commit

Permalink
Merge pull request #71 from shinonome-inc/feature/status-item-actions
Browse files Browse the repository at this point in the history
StatusItemクラスの引数関連のリファクタ
  • Loading branch information
KobayashiYoh authored Dec 22, 2024
2 parents 3df91ae + 153c2c5 commit 544bc58
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 186 deletions.
6 changes: 6 additions & 0 deletions lib/extensions/account_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'package:pg_mobile/models/mastodon/account.dart';
import 'package:pg_mobile/util/mastodon_content_parser.dart';

extension AccountExtension on Account {
String get noteText => MastodonContentParser.convertHtmlToPlainText(note);
}
18 changes: 14 additions & 4 deletions lib/extensions/status_extension.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import 'package:pg_mobile/models/mastodon/status.dart';
import 'package:pg_mobile/util/date_formatter.dart';
import 'package:pg_mobile/util/status_util.dart';
import 'package:pg_mobile/util/mastodon_content_parser.dart';

extension StatusExtension on Status {
DateTime get _createdAt => DateTime.parse(createdAt).toLocal();
String get createdAtText => DateFormatter.formatStatusDetail(_createdAt);
String get createdAtTimeAgoText =>
DateFormatter.formatTimeAgoDate(_createdAt);

String get contentText => StatusUtil.convertHtmlToPlainText(content);
List<String> get urls => StatusUtil.extractUrls(contentText);
String get mentionsText => StatusUtil.extractMentionsText(mentions);
String get contentText =>
MastodonContentParser.convertHtmlToPlainText(content);
List<String> get urls => MastodonContentParser.extractUrls(contentText);
String get mentionsText =>
MastodonContentParser.extractMentionsText(mentions);

bool get containsUrl => urls.isNotEmpty;
bool get showLinkPreview => containsUrl && mediaAttachments.isEmpty;

bool get isPinnedToProfile => pinned ?? false;

Uri get _uri => Uri.parse(url ?? '');
String get uriText => _uri.toString();
}

extension StatusListExtension on List<Status> {
Status findStatusFromId(String id) =>
firstWhere((element) => element.id == id);
}
33 changes: 11 additions & 22 deletions lib/pages/my_page/my_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ class _MyPageState extends ConsumerState<MyPage> {

@override
Widget build(BuildContext context) {
final user = ref.watch(signedInUserNotifierProvider);
final signedInUser = ref.watch(signedInUserNotifierProvider);
final state = ref.watch(myPageNotifierProvider);
if (user == null) {
if (signedInUser == null) {
return const Center(
child: CircularProgressIndicator(),
);
Expand All @@ -80,7 +80,7 @@ class _MyPageState extends ConsumerState<MyPage> {
child: Column(
children: [
UserProfileView(
user: user,
user: signedInUser,
onTapStatusCount: _onTapStatusCount,
onTapFollowingCount: _onTapFollowingCount,
onTapFollowerCount: _onTapFollowerCount,
Expand All @@ -106,24 +106,18 @@ class _MyPageState extends ConsumerState<MyPage> {
itemCount: state.statusesWithoutReply.length,
shrinkWrap: true,
itemBuilder: (context, index) {
final status = state.statusesWithoutReply.elementAt(index);
return StatusItem(
status: state.statusesWithoutReply.elementAt(index),
onTapItem: () {},
onTapAccount: () {},
onTapHashtag: () {},
onTapMention: () {},
onTapReply: () {},
status: status,
signedInUser: signedInUser,
onTapBoost: () {},
onTapFavorite: () {},
onTapMenu: () {},
onCopyLink: () {},
onPinToProfile: () {},
onUnpinToProfile: () {},
onDeleteAndReturnToDraft: () {},
onDelete: () {},
onMute: () {},
onBlock: () {},
onCancel: () {},
);
},
),
Expand All @@ -135,24 +129,18 @@ class _MyPageState extends ConsumerState<MyPage> {
itemCount: state.statusesWithReply.length,
shrinkWrap: true,
itemBuilder: (context, index) {
final status = state.statusesWithReply.elementAt(index);
return StatusItem(
status: state.statusesWithReply.elementAt(index),
onTapItem: () {},
onTapAccount: () {},
onTapHashtag: () {},
onTapMention: () {},
onTapReply: () {},
status: status,
signedInUser: signedInUser,
onTapBoost: () {},
onTapFavorite: () {},
onTapMenu: () {},
onCopyLink: () {},
onPinToProfile: () {},
onUnpinToProfile: () {},
onDeleteAndReturnToDraft: () {},
onDelete: () {},
onMute: () {},
onBlock: () {},
onCancel: () {},
);
},
),
Expand All @@ -170,8 +158,9 @@ class _MyPageState extends ConsumerState<MyPage> {
crossAxisSpacing: 4.h,
),
itemBuilder: (context, index) {
final status = state.mediaStatuses.elementAt(index);
return MediaGridViewItem(
status: state.mediaStatuses.elementAt(index),
status: status,
);
},
),
Expand Down
6 changes: 1 addition & 5 deletions lib/pages/timeline/timeline_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'package:pg_mobile/models/mastodon/account.dart';
import 'package:pg_mobile/models/mastodon/status.dart';
import 'package:pg_mobile/pages/timeline/timeline_state.dart';
import 'package:pg_mobile/repository/mastodon_repository.dart';
import 'package:pg_mobile/util/status_util.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'timeline_notifier.g.dart';
Expand Down Expand Up @@ -76,10 +75,7 @@ class TimelineNotifier extends _$TimelineNotifier {
setLoading(false);
}
if (inReplyToId != null) {
final repliedStatus = StatusUtil.findStatusFromId(
state.statuses,
inReplyToId,
);
final repliedStatus = state.statuses.findStatusFromId(inReplyToId);
_setStatus(
repliedStatus.copyWith(repliesCount: repliedStatus.favouritesCount + 1),
);
Expand Down
84 changes: 5 additions & 79 deletions lib/pages/timeline/timeline_page.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:go_router/go_router.dart';
import 'package:pg_mobile/constants/app_colors.dart';
import 'package:pg_mobile/extensions/status_extension.dart';
import 'package:pg_mobile/models/enums/app_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/pages/timeline/timeline_notifier.dart';
import 'package:pg_mobile/providers/signed_in_user_notifier.dart';
import 'package:pg_mobile/util/navigator_util.dart';
import 'package:pg_mobile/util/status_menu_action_util.dart';
import 'package:pg_mobile/widgets/status/status_item.dart';

class TimelinePage extends ConsumerStatefulWidget {
Expand All @@ -24,33 +18,6 @@ class TimelinePage extends ConsumerStatefulWidget {
class _StatusListPageState extends ConsumerState<TimelinePage> {
final ScrollController _controller = ScrollController();

void _onTapItem(Status status) {
context.push(AppPage.statusDetail.path);
}

void _onTapAccount(Account account) {
final signedInUser = ref.read(signedInUserNotifierProvider);
// FIXME: 現状だと認証中のユーザーアカウント情報が正しく保持されていないため、サインインの処理を修正する必要がある。
final isSignedInUser =
signedInUser != null && account.id == signedInUser.id;
context.push(isSignedInUser ? AppPage.myPage.path : AppPage.user.path);
}

void _onTapHashtag(String hashtag) {
context.push(AppPage.hashTag.path);
}

void _onTapMention(String hashtag) {
context.push(AppPage.user.path);
}

void _onTapReply(Status tappedStatus) {
NavigatorUtil.showNewPostCreateView(
context,
replyToStatus: tappedStatus,
);
}

Future<void> _onTapBoost(Status status) async {
final notifier = ref.read(timelineNotifierProvider.notifier);
await notifier.onTapBoost(status);
Expand All @@ -61,11 +28,6 @@ class _StatusListPageState extends ConsumerState<TimelinePage> {
await notifier.onTapFavorite(status);
}

void _copyLink() {
// TODO: リンクをコピー
NavigatorUtil.popScreen(context);
}

Future<void> _pinToProfile(Status status) async {
final notifier = ref.read(timelineNotifierProvider.notifier);
await notifier.pinStatusToProfile(status);
Expand Down Expand Up @@ -104,14 +66,6 @@ class _StatusListPageState extends ConsumerState<TimelinePage> {
NavigatorUtil.popScreen(context);
}

void _cancel() {
NavigatorUtil.popScreen(context);
}

void _onTapMenu(List<StatusMenuAction> actions) {
NavigatorUtil.showStatusMenuActionSheet(context, actions: actions);
}

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -157,45 +111,17 @@ class _StatusListPageState extends ConsumerState<TimelinePage> {
itemCount: state.statuses.length,
itemBuilder: (BuildContext context, int index) {
final status = state.statuses[index];
final isSignedInUser = signedInUser != null &&
status.account.id == signedInUser.id;
final statusMenuActions =
StatusMenuActionUtil.getStatusMenuActions(
status: status,
isSignedInUser: isSignedInUser,
onCopyLink: _copyLink,
onPinToProfile: () => status.isPinnedToProfile
? _unpinToProfile(status)
: _pinToProfile(status),
onDeleteAndReturnToDraft: _deleteAndReturnToDraft,
onDelete: () => _delete(status),
onMute: () => _mute(status),
onBlock: () => _block(),
onCancel: _cancel,
);
return StatusItem(
status: status,
reblogAccount:
status.reblog == null ? null : status.account,
onTapItem: () => _onTapItem(status),
onTapAccount: () => _onTapAccount(status.account),
onTapHashtag: () => _onTapHashtag,
onTapMention: () => _onTapMention,
onTapReply: () => _onTapReply(status),
signedInUser: signedInUser,
onTapBoost: () => _onTapBoost(status),
onTapFavorite: () => _onTapFavorite(status),
onTapMenu: () => _onTapMenu(statusMenuActions),
onCopyLink: _copyLink,
onPinToProfile: () =>
isSignedInUser ? _pinToProfile : null,
onUnpinToProfile: () =>
isSignedInUser ? _unpinToProfile : null,
onDeleteAndReturnToDraft: () =>
isSignedInUser ? _deleteAndReturnToDraft : null,
onDelete: () => isSignedInUser ? _delete : null,
onPinToProfile: () => _pinToProfile,
onUnpinToProfile: () => _unpinToProfile,
onDeleteAndReturnToDraft: () => _deleteAndReturnToDraft,
onDelete: () => _delete,
onMute: () => _mute,
onBlock: _block,
onCancel: _cancel,
);
},
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import 'package:html/parser.dart';
import 'package:pg_mobile/constants/patterns.dart';
import 'package:pg_mobile/models/mastodon/status.dart';
import 'package:pg_mobile/models/mastodon/status_mention.dart';

/// ステータスに関するユーティリティクラスです
class StatusUtil {
StatusUtil._();
/// MastodonのContentに関するユーティリティクラス
class MastodonContentParser {
MastodonContentParser._();

/// HTMLテキストを解析してテキストに変換する。
static String convertHtmlToPlainText(String htmlText) {
Expand Down Expand Up @@ -34,8 +33,4 @@ class StatusUtil {
}
return mentionsText;
}

/// 指定されたIDを持つ投稿を取得する。
static Status findStatusFromId(List<Status> statuses, String id) =>
statuses.firstWhere((element) => element.id == id);
}
19 changes: 12 additions & 7 deletions lib/util/status_menu_action_util.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:pg_mobile/extensions/status_extension.dart';
import 'package:pg_mobile/extensions/status_menu_action_extension.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';

Expand Down Expand Up @@ -79,7 +80,7 @@ class StatusMenuActionUtil {
/// ユーザーに応じてフィルタリングされたStatusMenuActionsのリストを取得する
static List<StatusMenuAction> getStatusMenuActions({
required Status status,
required bool isSignedInUser,
required Account? signedInUser,
required void Function() onCopyLink,
required void Function() onPinToProfile,
required void Function() onDeleteAndReturnToDraft,
Expand All @@ -88,22 +89,26 @@ class StatusMenuActionUtil {
required void Function() onBlock,
required void Function() onCancel,
}) {
final isSignedInUser =
signedInUser != null && status.account.id == signedInUser.id;
// アクションリスト生成
final actions = _createStatusMenuActions(
status: status,
onCopyLink: onCopyLink,
onPinToProfile: onPinToProfile,
onDeleteAndReturnToDraft: onDeleteAndReturnToDraft,
onDelete: onDelete,
onMute: onMute,
onBlock: onBlock,
onPinToProfile: () => isSignedInUser ? onPinToProfile : null,
onDeleteAndReturnToDraft: () =>
isSignedInUser ? onDeleteAndReturnToDraft : null,
onDelete: () => isSignedInUser ? onDelete : null,
onMute: () => isSignedInUser ? null : onMute,
onBlock: () => isSignedInUser ? null : onBlock,
onCancel: onCancel,
);

// ユーザーに基づいてフィルタリング
return _filterActionsByUser(
final filledActions = _filterActionsByUser(
actions: actions,
isSignedInUser: isSignedInUser,
);
return filledActions;
}
}
Loading

0 comments on commit 544bc58

Please sign in to comment.