diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 0c460f9..b822609 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -710,5 +710,16 @@ "fileIdHint": "The file ID is the ID you get after upload the file via the Solar Network Drive.", "translate": "Translate", "translating": "Translating", - "translated": "Translated" -} \ No newline at end of file + "translated": "Translated", + "reactionThumbUp": "Thumbs Up", + "reactionThumbDown": "Thumbs Down", + "reactionJustOkay": "Just Okay", + "reactionCry": "Cry", + "reactionConfuse": "Confused", + "reactionClap": "Clap", + "reactionLaugh": "Laugh", + "reactionAngry": "Angry", + "reactionParty": "Party", + "reactionPray": "Pray", + "reactionHeart": "Heart" +} diff --git a/lib/models/post.dart b/lib/models/post.dart index c3ce273..edb1aec 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -78,6 +78,13 @@ sealed class SnSubscriptionStatus with _$SnSubscriptionStatus { sealed class ReactInfo with _$ReactInfo { const factory ReactInfo({required String icon, required int attitude}) = _ReactInfo; + + static String getTranslationKey(String templateKey) { + final parts = templateKey.split('_'); + final camelCase = + parts.map((p) => p[0].toUpperCase() + p.substring(1)).join(); + return 'reaction$camelCase'; + } } const Map kReactionTemplates = { diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index 4d59fef..06ee9f1 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -383,6 +383,7 @@ class PostItem extends HookConsumerWidget { builder: (BuildContext context) { return _PostReactionSheet( reactionsCount: item.reactionsCount, + reactionsMade: item.reactionsMade, onReact: (symbol, attitude) { reactPost(symbol, attitude); }, @@ -701,12 +702,14 @@ Widget _buildReferencePost( class PostReactionList extends HookConsumerWidget { final String parentId; final Map reactions; + final Map reactionsMade; final Function(String symbol, int attitude, int delta)? onReact; final EdgeInsets? padding; const PostReactionList({ super.key, required this.parentId, required this.reactions, + required this.reactionsMade, this.padding, this.onReact, }); @@ -760,6 +763,7 @@ class PostReactionList extends HookConsumerWidget { builder: (BuildContext context) { return _PostReactionSheet( reactionsCount: reactions, + reactionsMade: reactionsMade, onReact: (symbol, attitude) { reactPost(symbol, attitude); }, @@ -804,9 +808,11 @@ class PostReactionList extends HookConsumerWidget { class _PostReactionSheet extends StatelessWidget { final Map reactionsCount; + final Map reactionsMade; final Function(String symbol, int attitude) onReact; const _PostReactionSheet({ required this.reactionsCount, + required this.reactionsMade, required this.onReact, }); @@ -843,9 +849,24 @@ class _PostReactionSheet extends StatelessWidget { Expanded( child: ListView( children: [ - _buildReactionSection(context, 'Positive Reactions', 0), - _buildReactionSection(context, 'Neutral Reactions', 1), - _buildReactionSection(context, 'Negative Reactions', 2), + _buildReactionSection( + context, + Symbols.mood, + 'reactionPositive'.tr(), + 0, + ), + _buildReactionSection( + context, + Symbols.sentiment_neutral, + 'reactionNeutral'.tr(), + 1, + ), + _buildReactionSection( + context, + Symbols.mood_bad, + 'reactionNegative'.tr(), + 2, + ), ], ), ), @@ -855,6 +876,7 @@ class _PostReactionSheet extends StatelessWidget { Widget _buildReactionSection( BuildContext context, + IconData icon, String title, int attitude, ) { @@ -867,38 +889,58 @@ class _PostReactionSheet extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title).fontSize(20).bold().padding(horizontal: 20, vertical: 12), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + spacing: 8, + children: [Icon(icon), Text(title).fontSize(17).bold()], + ).padding(horizontal: 24, top: 16, bottom: 6), SizedBox( - height: 84, + height: 120, child: GridView.builder( scrollDirection: Axis.horizontal, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 1, - mainAxisExtent: 100, + mainAxisExtent: 120, mainAxisSpacing: 8.0, crossAxisSpacing: 8.0, - childAspectRatio: 2.0, + childAspectRatio: 1.0, ), + padding: EdgeInsets.symmetric(horizontal: 16), itemCount: allReactions.length, itemBuilder: (context, index) { final symbol = allReactions[index]; final count = reactionsCount[symbol] ?? 0; - return InkWell( - onTap: () { - onReact(symbol, attitude); - Navigator.pop(context); - }, - child: GridTile( - header: Text( - kReactionTemplates[symbol]?.icon ?? '', - textAlign: TextAlign.center, - ).fontSize(24), - footer: Text( - count > 0 ? 'x$count' : '', - textAlign: TextAlign.center, - ).bold().padding(bottom: 12), - child: Center( - child: Text(symbol, textAlign: TextAlign.center), + return Card( + margin: EdgeInsets.symmetric(vertical: 4), + color: + (reactionsMade[symbol] ?? false) + ? Theme.of(context).colorScheme.primaryContainer + : Theme.of(context).colorScheme.surfaceContainerLowest, + child: InkWell( + borderRadius: BorderRadius.all(Radius.circular(8)), + onTap: () { + onReact(symbol, attitude); + Navigator.pop(context); + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + kReactionTemplates[symbol]?.icon ?? '', + textAlign: TextAlign.center, + ).fontSize(24), + Text( + ReactInfo.getTranslationKey(symbol), + textAlign: TextAlign.center, + ).tr(), + if (count > 0) + Text( + 'x$count', + textAlign: TextAlign.center, + ).bold().padding(bottom: 4) + else + const Gap(20), + ], ), ), ); diff --git a/lib/widgets/post/post_item_creator.dart b/lib/widgets/post/post_item_creator.dart index 198c4f0..e949946 100644 --- a/lib/widgets/post/post_item_creator.dart +++ b/lib/widgets/post/post_item_creator.dart @@ -370,6 +370,7 @@ class PostItemCreator extends HookConsumerWidget { PostReactionList( parentId: item.id, reactions: item.reactionsCount, + reactionsMade: item.reactionsMade, padding: EdgeInsets.zero, ), const Gap(16),