Skip to content

Commit

Permalink
Support scam warning (MixinNetwork#364)
Browse files Browse the repository at this point in the history
* Support scam warning.

* format

* improve scam warning
  • Loading branch information
YeungKC authored Nov 1, 2021
1 parent acc2ecd commit 02d0851
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 11 deletions.
6 changes: 6 additions & 0 deletions assets/images/triangle_warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions lib/account/scam_warning.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:rxdart/rxdart.dart';

import '../utils/hive_key_values.dart';

class ScamWarningKeyValue extends HiveKeyValue<DateTime?> {
ScamWarningKeyValue._() : super(_hiveName);
static const _hiveName = 'scam_warning_key_value';

static ScamWarningKeyValue? _instance;

static ScamWarningKeyValue get instance =>
_instance ??= ScamWarningKeyValue._();

bool _isShow(String userId) => box.get(userId, defaultValue: null).isShow;

Future<void> dismiss(String userId) =>
box.put(userId, DateTime.now().add(const Duration(days: 1)));

Stream<bool> watch(String userId) => box
.watch(key: userId)
.map((event) => event.value)
.where((event) => event is DateTime?)
.cast<DateTime?>()
.map((dateTime) => dateTime.isShow)
.startWith(_isShow(userId));
}

extension _IsShowScamWarningExtension on DateTime? {
bool get isShow {
if (this == null) return true;
return DateTime.now().isAfter(this!);
}
}
3 changes: 3 additions & 0 deletions lib/constants/resources.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ class MessageLookup extends MessageLookupByLibrary {
"reportWarning": MessageLookupByLibrary.simpleMessage(
"Do you want to report and block this contact?"),
"save": MessageLookupByLibrary.simpleMessage("Save"),
"scamWarning": MessageLookupByLibrary.simpleMessage(
"Warning: Many users reported this account as a scam. Please be careful, especially if it asks you for money"),
"search": MessageLookupByLibrary.simpleMessage("Search"),
"searchEmpty": MessageLookupByLibrary.simpleMessage(
"No chats, \ncontacts or messages found."),
Expand Down
2 changes: 2 additions & 0 deletions lib/generated/intl/messages_zh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ class MessageLookup extends MessageLookupByLibrary {
"report": MessageLookupByLibrary.simpleMessage("举报"),
"reportWarning": MessageLookupByLibrary.simpleMessage("确定要举报这个联系人?"),
"save": MessageLookupByLibrary.simpleMessage("保存"),
"scamWarning": MessageLookupByLibrary.simpleMessage(
"警告:此账号被大量用户举报,请谨防网络诈骗,注意个人财产安全"),
"search": MessageLookupByLibrary.simpleMessage("搜索"),
"searchEmpty": MessageLookupByLibrary.simpleMessage("找不到联系人或消息。"),
"searchMessageHistory": MessageLookupByLibrary.simpleMessage("搜索聊天记录"),
Expand Down
10 changes: 10 additions & 0 deletions lib/generated/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -222,5 +222,6 @@
"walletTransactionThatTimeNoValue": "value then N/A",
"text": "Text",
"developer": "Developer",
"goToChat": "Go to chat"
"goToChat": "Go to chat",
"scamWarning": "Warning: Many users reported this account as a scam. Please be careful, especially if it asks you for money"
}
3 changes: 2 additions & 1 deletion lib/l10n/intl_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -217,5 +217,6 @@
"walletTransactionThatTimeNoValue": "当时价值 暂无",
"text": "文字",
"developer": "开发者",
"goToChat": "定位到聊天"
"goToChat": "定位到聊天",
"scamWarning": "警告:此账号被大量用户举报,请谨防网络诈骗,注意个人财产安全"
}
86 changes: 86 additions & 0 deletions lib/ui/home/chat/chat_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart';

import '../../../account/scam_warning.dart';
import '../../../account/show_pin_message_key_value.dart';
import '../../../bloc/simple_cubit.dart';
import '../../../bloc/subscribe_mixin.dart';
Expand Down Expand Up @@ -414,6 +415,12 @@ class ChatContainer extends HookWidget {
const _NotificationListener(
child: _List(),
),
const Positioned(
left: 6,
right: 6,
bottom: 6,
child: _BottomBanner(),
),
Positioned(
bottom: 16,
right: 16,
Expand Down Expand Up @@ -662,6 +669,85 @@ class _JumpCurrentButton extends HookWidget {
}
}

class _BottomBanner extends HookWidget {
const _BottomBanner({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
final userId =
useBlocStateConverter<ConversationCubit, ConversationState?, String?>(
converter: (state) => state?.userId);
final isScam =
useBlocStateConverter<ConversationCubit, ConversationState?, bool>(
converter: (state) => (state?.user?.isScam ?? 0) > 0);

final showScamWarning = useMemoizedStream(
() {
if (userId == null || !isScam) return Stream.value(false);
return ScamWarningKeyValue.instance.watch(userId);
},
initialData: false,
keys: [userId],
).data ??
false;

return AnimatedVisibility(
visible: showScamWarning,
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: context.messageBubbleColor(false),
boxShadow: const [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.15),
offset: Offset(0, 2),
blurRadius: 10,
),
],
),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(
left: 8,
right: 16,
top: 8,
bottom: 8,
),
child: SvgPicture.asset(
Resources.assetsImagesTriangleWarningSvg,
color: context.theme.red,
width: 26,
height: 26,
),
),
Expanded(
child: Text(
context.l10n.scamWarning,
style: TextStyle(
color: context.theme.text,
fontSize: 14,
),
),
),
ActionButton(
name: Resources.assetsImagesIcCloseSvg,
color: context.theme.icon,
size: 20,
onTap: () {
final userId = context.read<ConversationCubit>().state?.userId;
if (userId == null) return;
ScamWarningKeyValue.instance.dismiss(userId);
},
),
],
),
),
);
}
}

class _PinMessagesBanner extends HookWidget {
const _PinMessagesBanner({Key? key}) : super(key: key);

Expand Down
1 change: 0 additions & 1 deletion lib/ui/home/slide_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class SlidePage extends StatelessWidget {
const Expanded(child: _CircleList()),
AnimatedVisibility(
alignment: Alignment.bottomCenter,
duration: const Duration(milliseconds: 200),
visible: showCollapse,
child: HookBuilder(builder: (context) {
final collapse = useBlocStateConverter<MultiAuthCubit,
Expand Down
3 changes: 3 additions & 0 deletions lib/utils/hive_key_values.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:hive/hive.dart';
import 'package:path/path.dart' as p;

import '../account/account_key_value.dart';
import '../account/scam_warning.dart';
import '../account/show_pin_message_key_value.dart';
import '../crypto/crypto_key_value.dart';
import '../crypto/privacy_key_value.dart';
Expand All @@ -16,13 +17,15 @@ Future<void> initKeyValues() => Future.wait([
CryptoKeyValue.instance.init(),
AccountKeyValue.instance.init(),
ShowPinMessageKeyValue.instance.init(),
ScamWarningKeyValue.instance.init(),
]);

Future<void> clearKeyValues() => Future.wait([
PrivacyKeyValue.instance.delete(),
CryptoKeyValue.instance.delete(),
AccountKeyValue.instance.delete(),
ShowPinMessageKeyValue.instance.delete(),
ScamWarningKeyValue.instance.delete(),
]);

abstract class HiveKeyValue<E> {
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/animated_visibility.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class AnimatedVisibility extends StatelessWidget {
required this.visible,
this.maintainSize = true,
this.alignment = Alignment.center,
this.duration = const Duration(milliseconds: 100),
this.duration = const Duration(milliseconds: 200),
}) : super(key: key);

final Widget child;
Expand Down
1 change: 0 additions & 1 deletion lib/widgets/search_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ class SearchTextField extends HookWidget {
).requireData;

return AnimatedVisibility(
duration: const Duration(milliseconds: 200),
visible: showClear || isNotEmpty,
child: _SearchClearIcon(onTap: () {
controller.text = '';
Expand Down
12 changes: 6 additions & 6 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ flutter:
# the material Icons class.
uses-material-design: true
assets:
# assets start
# assets start

# GENERATED CODE - DO NOT MODIFY MANUALLY
# **************************************************************************
# Auto generated by https://github.com/fluttercandies/assets_generator
# **************************************************************************
# GENERATED CODE - DO NOT MODIFY MANUALLY
# **************************************************************************
# Auto generated by https://github.com/fluttercandies/assets_generator
# **************************************************************************

- assets/icons/
- assets/images/
Expand Down Expand Up @@ -190,4 +190,4 @@ msix_config:
icons_background_color: transparent
architecture: x64
capabilities: 'internetClient,microphone'
store: true
store: true

0 comments on commit 02d0851

Please sign in to comment.