Merge branch 'main' into feat-rating-action
commit
2753e17d7c
|
|
@ -47,7 +47,7 @@ class LikeActivityActionButton extends ConsumerWidget {
|
||||||
|
|
||||||
return BaseActionButton(
|
return BaseActionButton(
|
||||||
maxWidth: 60,
|
maxWidth: 60,
|
||||||
iconData: liked != null ? Icons.favorite : Icons.favorite_border,
|
iconData: liked != null ? Icons.thumb_up : Icons.thumb_up_off_alt,
|
||||||
label: "like".t(context: context),
|
label: "like".t(context: context),
|
||||||
onPressed: () => onTap(liked),
|
onPressed: () => onTap(liked),
|
||||||
iconOnly: iconOnly,
|
iconOnly: iconOnly,
|
||||||
|
|
@ -57,7 +57,7 @@ class LikeActivityActionButton extends ConsumerWidget {
|
||||||
|
|
||||||
// default to empty heart during loading
|
// default to empty heart during loading
|
||||||
loading: () => BaseActionButton(
|
loading: () => BaseActionButton(
|
||||||
iconData: Icons.favorite_border,
|
iconData: Icons.thumb_up_off_alt,
|
||||||
label: "like".t(context: context),
|
label: "like".t(context: context),
|
||||||
iconOnly: iconOnly,
|
iconOnly: iconOnly,
|
||||||
menuItem: menuItem,
|
menuItem: menuItem,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/providers/activity.provider.dart';
|
import 'package:immich_mobile/providers/activity.provider.dart';
|
||||||
import 'package:immich_mobile/providers/album/current_album.provider.dart';
|
import 'package:immich_mobile/providers/album/current_album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
|
||||||
|
|
@ -68,11 +69,11 @@ class ActivityTextField extends HookConsumerWidget {
|
||||||
suffixIcon: Padding(
|
suffixIcon: Padding(
|
||||||
padding: const EdgeInsets.only(right: 10),
|
padding: const EdgeInsets.only(right: 10),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(liked ? Icons.favorite_rounded : Icons.favorite_border_rounded),
|
icon: Icon(liked ? Icons.thumb_up : Icons.thumb_up_off_alt),
|
||||||
onPressed: liked ? removeLike : addLike,
|
onPressed: liked ? removeLike : addLike,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
suffixIconColor: liked ? Colors.red[700] : null,
|
suffixIconColor: liked ? context.primaryColor : null,
|
||||||
hintText: !isEnabled ? 'shared_album_activities_input_disable'.tr() : 'say_something'.tr(),
|
hintText: !isEnabled ? 'shared_album_activities_input_disable'.tr() : 'say_something'.tr(),
|
||||||
hintStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.grey[600]),
|
hintStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.grey[600]),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class ActivityTile extends HookConsumerWidget {
|
||||||
? Container(
|
? Container(
|
||||||
width: isBottomSheet ? 30 : 44,
|
width: isBottomSheet ? 30 : 44,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Icon(Icons.favorite_rounded, color: Colors.red[700]),
|
child: Icon(Icons.thumb_up, color: context.primaryColor),
|
||||||
)
|
)
|
||||||
: isBottomSheet
|
: isBottomSheet
|
||||||
? UserCircleAvatar(user: activity.user, size: 30, radius: 15)
|
? UserCircleAvatar(user: activity.user, size: 30, radius: 15)
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,8 @@ class CommentBubble extends ConsumerWidget {
|
||||||
bottom: 6,
|
bottom: 6,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle),
|
decoration: BoxDecoration(color: context.colorScheme.surfaceContainer, shape: BoxShape.circle),
|
||||||
child: Icon(Icons.favorite, color: Colors.red[600], size: 18),
|
child: Icon(Icons.thumb_up, color: context.primaryColor, size: 18),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -81,8 +81,8 @@ class CommentBubble extends ConsumerWidget {
|
||||||
if (isLike && !showThumbnail) {
|
if (isLike && !showThumbnail) {
|
||||||
likes = Container(
|
likes = Container(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle),
|
decoration: BoxDecoration(color: context.colorScheme.surfaceContainer, shape: BoxShape.circle),
|
||||||
child: Icon(Icons.favorite, color: Colors.red[600], size: 18),
|
child: Icon(Icons.thumb_up, color: context.primaryColor, size: 18),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,15 +77,15 @@ void main() {
|
||||||
overrides: overrides,
|
overrides: overrides,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(find.widgetWithIcon(IconButton, Icons.favorite_rounded), findsOneWidget);
|
expect(find.widgetWithIcon(IconButton, Icons.thumb_up), findsOneWidget);
|
||||||
expect(find.widgetWithIcon(IconButton, Icons.favorite_border_rounded), findsNothing);
|
expect(find.widgetWithIcon(IconButton, Icons.thumb_up_off_alt), findsNothing);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Bordered icon if likedId == null', (tester) async {
|
testWidgets('Bordered icon if likedId == null', (tester) async {
|
||||||
await tester.pumpConsumerWidget(ActivityTextField(onSubmit: (_) {}), overrides: overrides);
|
await tester.pumpConsumerWidget(ActivityTextField(onSubmit: (_) {}), overrides: overrides);
|
||||||
|
|
||||||
expect(find.widgetWithIcon(IconButton, Icons.favorite_border_rounded), findsOneWidget);
|
expect(find.widgetWithIcon(IconButton, Icons.thumb_up_off_alt), findsOneWidget);
|
||||||
expect(find.widgetWithIcon(IconButton, Icons.favorite_rounded), findsNothing);
|
expect(find.widgetWithIcon(IconButton, Icons.thumb_up), findsNothing);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Adds new like', (tester) async {
|
testWidgets('Adds new like', (tester) async {
|
||||||
|
|
|
||||||
|
|
@ -91,17 +91,17 @@ void main() {
|
||||||
group('Like Activity', () {
|
group('Like Activity', () {
|
||||||
final activity = Activity(id: '1', createdAt: DateTime(100), type: ActivityType.like, user: UserStub.admin);
|
final activity = Activity(id: '1', createdAt: DateTime(100), type: ActivityType.like, user: UserStub.admin);
|
||||||
|
|
||||||
testWidgets('Like contains filled heart as leading', (tester) async {
|
testWidgets('Like contains filled thumbs-up as leading', (tester) async {
|
||||||
await tester.pumpConsumerWidget(ActivityTile(activity), overrides: overrides);
|
await tester.pumpConsumerWidget(ActivityTile(activity), overrides: overrides);
|
||||||
|
|
||||||
// Leading widget should not be null
|
// Leading widget should not be null
|
||||||
final listTile = tester.widget<ListTile>(find.byType(ListTile));
|
final listTile = tester.widget<ListTile>(find.byType(ListTile));
|
||||||
expect(listTile.leading, isNotNull);
|
expect(listTile.leading, isNotNull);
|
||||||
|
|
||||||
// And should have a favorite icon
|
// And should have a thumb_up icon
|
||||||
final favoIconFinder = find.widgetWithIcon(listTile.leading!.runtimeType, Icons.favorite_rounded);
|
final thumbUpIconFinder = find.widgetWithIcon(listTile.leading!.runtimeType, Icons.thumb_up);
|
||||||
|
|
||||||
expect(favoIconFinder, findsOneWidget);
|
expect(thumbUpIconFinder, findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Like title is center aligned', (tester) async {
|
testWidgets('Like title is center aligned', (tester) async {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { locale } from '$lib/stores/preferences.store';
|
import { locale } from '$lib/stores/preferences.store';
|
||||||
import type { ActivityResponseDto } from '@immich/sdk';
|
import type { ActivityResponseDto } from '@immich/sdk';
|
||||||
import { Icon } from '@immich/ui';
|
import { Icon } from '@immich/ui';
|
||||||
import { mdiCommentOutline, mdiHeart, mdiHeartOutline } from '@mdi/js';
|
import { mdiCommentOutline, mdiThumbUp, mdiThumbUpOutline } from '@mdi/js';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isLiked: ActivityResponseDto | null;
|
isLiked: ActivityResponseDto | null;
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<div class="w-full flex p-4 items-center justify-center rounded-full gap-5 bg-subtle border bg-opacity-60">
|
<div class="w-full flex p-4 items-center justify-center rounded-full gap-5 bg-subtle border bg-opacity-60">
|
||||||
<button type="button" class={disabled ? 'cursor-not-allowed' : ''} onclick={onFavorite} {disabled}>
|
<button type="button" class={disabled ? 'cursor-not-allowed' : ''} onclick={onFavorite} {disabled}>
|
||||||
<div class="flex gap-2 items-center justify-center">
|
<div class="flex gap-2 items-center justify-center">
|
||||||
<Icon icon={isLiked ? mdiHeart : mdiHeartOutline} size="24" class={isLiked ? 'text-red-400' : 'text-fg'} />
|
<Icon icon={isLiked ? mdiThumbUp : mdiThumbUpOutline} size="24" class={isLiked ? 'text-primary' : 'text-fg'} />
|
||||||
{#if numberOfLikes}
|
{#if numberOfLikes}
|
||||||
<div class="text-l">{numberOfLikes.toLocaleString($locale)}</div>
|
<div class="text-l">{numberOfLikes.toLocaleString($locale)}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
import { isTenMinutesApart } from '$lib/utils/timesince';
|
import { isTenMinutesApart } from '$lib/utils/timesince';
|
||||||
import { ReactionType, type ActivityResponseDto, type AssetTypeEnum, type UserResponseDto } from '@immich/sdk';
|
import { ReactionType, type ActivityResponseDto, type AssetTypeEnum, type UserResponseDto } from '@immich/sdk';
|
||||||
import { Icon, IconButton, LoadingSpinner, toastManager } from '@immich/ui';
|
import { Icon, IconButton, LoadingSpinner, toastManager } from '@immich/ui';
|
||||||
import { mdiClose, mdiDeleteOutline, mdiDotsVertical, mdiHeart, mdiSend } from '@mdi/js';
|
import { mdiClose, mdiDeleteOutline, mdiDotsVertical, mdiSend, mdiThumbUp } from '@mdi/js';
|
||||||
import * as luxon from 'luxon';
|
import * as luxon from 'luxon';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import UserAvatar from '../shared-components/user-avatar.svelte';
|
import UserAvatar from '../shared-components/user-avatar.svelte';
|
||||||
|
|
@ -181,7 +181,7 @@
|
||||||
{:else if reaction.type === ReactionType.Like}
|
{:else if reaction.type === ReactionType.Like}
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div class="flex py-3 ps-3 mt-3 gap-4 items-center text-sm">
|
<div class="flex py-3 ps-3 mt-3 gap-4 items-center text-sm">
|
||||||
<div class="text-red-600"><Icon icon={mdiHeart} size="20" /></div>
|
<div class="text-primary"><Icon icon={mdiThumbUp} size="20" /></div>
|
||||||
|
|
||||||
<div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}>
|
<div class="w-full" title={`${reaction.user.name} (${reaction.user.email})`}>
|
||||||
{$t('user_liked', {
|
{$t('user_liked', {
|
||||||
|
|
@ -254,7 +254,7 @@
|
||||||
shortcut: { key: 'Enter' },
|
shortcut: { key: 'Enter' },
|
||||||
onShortcut: () => handleSendComment(),
|
onShortcut: () => handleSendComment(),
|
||||||
}}
|
}}
|
||||||
class="h-[18px] {disabled
|
class="h-4.5 {disabled
|
||||||
? 'cursor-not-allowed'
|
? 'cursor-not-allowed'
|
||||||
: ''} w-full max-h-56 pe-2 items-center overflow-y-auto leading-4 outline-none resize-none bg-gray-200"
|
: ''} w-full max-h-56 pe-2 items-center overflow-y-auto leading-4 outline-none resize-none bg-gray-200"
|
||||||
></textarea>
|
></textarea>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue