diff --git a/l10n_arb/intl_zh_CN.arb b/l10n_arb/intl_zh_CN.arb index c303575..3fdcfcb 100644 --- a/l10n_arb/intl_zh_CN.arb +++ b/l10n_arb/intl_zh_CN.arb @@ -39,5 +39,9 @@ "NOTIFY_TARGET_STATUS_SUSPEND": "停止", "NOTIFY_TARGET_TYPE": "类型", "NOTIFY_TARGET_TYPE_UNSPECIFIED": "未知", - "NOTIFY_TARGET_TYPE_TELEGRAM": "Telegram" + "NOTIFY_TARGET_TYPE_TELEGRAM": "Telegram", + "NOTIFY_FLOW_STATUS": "状态", + "NOTIFY_FLOW_STATUS_UNSPECIFIED": "未知", + "NOTIFY_FLOW_STATUS_ACTIVE": "启用", + "NOTIFY_FLOW_STATUS_SUSPEND": "停止" } \ No newline at end of file diff --git a/lib/l10n/intl/messages_zh_CN.dart b/lib/l10n/intl/messages_zh_CN.dart index f476315..11a7c04 100644 --- a/lib/l10n/intl/messages_zh_CN.dart +++ b/lib/l10n/intl/messages_zh_CN.dart @@ -45,6 +45,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("停止"), "FEED_CONFIG_STATUS_UNSPECIFIED": MessageLookupByLibrary.simpleMessage("未知"), + "NOTIFY_FLOW_STATUS": MessageLookupByLibrary.simpleMessage("状态"), + "NOTIFY_FLOW_STATUS_ACTIVE": MessageLookupByLibrary.simpleMessage("启用"), + "NOTIFY_FLOW_STATUS_SUSPEND": + MessageLookupByLibrary.simpleMessage("停止"), + "NOTIFY_FLOW_STATUS_UNSPECIFIED": + MessageLookupByLibrary.simpleMessage("未知"), "NOTIFY_TARGET_STATUS": MessageLookupByLibrary.simpleMessage("状态"), "NOTIFY_TARGET_STATUS_ACTIVE": MessageLookupByLibrary.simpleMessage("启用"), diff --git a/lib/l10n/l10n.dart b/lib/l10n/l10n.dart index ef24236..241207f 100644 --- a/lib/l10n/l10n.dart +++ b/lib/l10n/l10n.dart @@ -399,6 +399,46 @@ class S { args: [], ); } + + /// `状态` + String get NOTIFY_FLOW_STATUS { + return Intl.message( + '状态', + name: 'NOTIFY_FLOW_STATUS', + desc: '', + args: [], + ); + } + + /// `未知` + String get NOTIFY_FLOW_STATUS_UNSPECIFIED { + return Intl.message( + '未知', + name: 'NOTIFY_FLOW_STATUS_UNSPECIFIED', + desc: '', + args: [], + ); + } + + /// `启用` + String get NOTIFY_FLOW_STATUS_ACTIVE { + return Intl.message( + '启用', + name: 'NOTIFY_FLOW_STATUS_ACTIVE', + desc: '', + args: [], + ); + } + + /// `停止` + String get NOTIFY_FLOW_STATUS_SUSPEND { + return Intl.message( + '停止', + name: 'NOTIFY_FLOW_STATUS_SUSPEND', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/repo/grpc/l10n.dart b/lib/repo/grpc/l10n.dart index 59ce993..f9a557e 100644 --- a/lib/repo/grpc/l10n.dart +++ b/lib/repo/grpc/l10n.dart @@ -108,3 +108,15 @@ String notifyTargetStatusString(NotifyTargetStatus status) { } return ''; } + +String notifyFlowStatusString(NotifyFlowStatus status) { + switch (status) { + case NotifyFlowStatus.NOTIFY_FLOW_STATUS_UNSPECIFIED: + return S.current.NOTIFY_FLOW_STATUS_UNSPECIFIED; + case NotifyFlowStatus.NOTIFY_FLOW_STATUS_ACTIVE: + return S.current.NOTIFY_FLOW_STATUS_ACTIVE; + case NotifyFlowStatus.NOTIFY_FLOW_STATUS_SUSPEND: + return S.current.NOTIFY_FLOW_STATUS_SUSPEND; + } + return ''; +} diff --git a/lib/view/pages/settings/notify/notify_flow_add_page.dart b/lib/view/pages/settings/notify/notify_flow_add_page.dart index 43bc352..25e6394 100644 --- a/lib/view/pages/settings/notify/notify_flow_add_page.dart +++ b/lib/view/pages/settings/notify/notify_flow_add_page.dart @@ -7,7 +7,9 @@ import 'package:tuihub_protos/librarian/sephirah/v1/yesod.pb.dart'; import '../../../../bloc/netzach/netzach_bloc.dart'; import '../../../../bloc/yesod/yesod_bloc.dart'; +import '../../../../repo/grpc/l10n.dart'; import '../../../../route.dart'; +import '../../../components/expand_rail_tile.dart'; import '../../../components/toast.dart'; import '../../../form/form_field.dart'; import '../../../helper/spacing.dart'; @@ -42,6 +44,8 @@ class _NotifyFlowAddPageState extends State { } }, builder: (context, state) { + final notifySources = context.read().state.feedConfigs ?? []; + final notifyTargets = state.notifyTargets ?? []; return Scaffold( appBar: AppBar( shape: const RoundedRectangleBorder( @@ -125,40 +129,97 @@ class _NotifyFlowAddPageState extends State { ), Step( title: const Text('通知源'), - content: MultiSelectDialogField( - title: const Text('订阅源'), - buttonText: const Text('订阅'), - buttonIcon: const Icon(Icons.filter_alt_outlined), - items: [ - for (final ListFeedConfigsResponse_FeedWithConfig config - in context - .read() - .state - .feedConfigs ?? - []) - MultiSelectItem( - config.config.id, - config.feed.title.isNotEmpty - ? config.feed.title - : config.config.feedUrl), - ], - initialValue: - sources.map((e) => e.sourceId).toList(), - onConfirm: (values) { - sources = values - .map((e) => NotifyFlowSource(sourceId: e)) - .toList(); - }, - decoration: BoxDecoration( - borderRadius: SpacingHelper.defaultBorderRadius, + content: Column(children: [ + MultiSelectDialogField( + title: const Text('订阅源'), + buttonText: const Text('订阅'), + buttonIcon: const Icon(Icons.filter_alt_outlined), + items: [ + for (final ListFeedConfigsResponse_FeedWithConfig config + in notifySources) + MultiSelectItem( + config.config.id, + config.feed.title.isNotEmpty + ? config.feed.title + : config.config.feedUrl), + ], + initialValue: + sources.map((e) => e.sourceId).toList(), + onConfirm: (values) { + setState(() { + sources = values + .map((e) => NotifyFlowSource(sourceId: e)) + .toList(); + }); + }, + decoration: BoxDecoration( + borderRadius: SpacingHelper.defaultBorderRadius, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return '请选择至少一个订阅'; + } + return null; + }, ), - validator: (value) { - if (value == null || value.isEmpty) { - return '请选择至少一个订阅'; - } - return null; - }, - ), + for (var i = 0; i < sources.length; i++) + Column(children: [ + SpacingHelper.defaultDivider, + Align( + alignment: Alignment.centerLeft, + child: Text(notifySources + .firstWhere((e) => + e.config.id == sources[i].sourceId) + .feed + .title), + ), + const SizedBox( + height: 8, + ), + ExpandRailTile( + title: const Text('过滤器'), + children: [ + const SizedBox( + height: 8, + ), + TextFormField( + onChanged: (newValue) { + setState(() { + sources[i].filter = NotifyFilter( + includeKeywords: [newValue], + excludeKeywords: sources[i] + .filter + .excludeKeywords, + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '排除关键字', + ), + ), + const SizedBox( + height: 8, + ), + TextFormField( + onChanged: (newValue) { + setState(() { + sources[i].filter = NotifyFilter( + includeKeywords: sources[i] + .filter + .includeKeywords, + excludeKeywords: [newValue], + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '包含关键字', + ), + ), + ]), + ]), + ]), ), Step( title: const Text('通知目标'), @@ -168,9 +229,9 @@ class _NotifyFlowAddPageState extends State { buttonText: const Text('第三方平台'), buttonIcon: const Icon(Icons.filter_alt_outlined), items: [ - for (final NotifyTarget config - in state.notifyTargets ?? []) - MultiSelectItem(config.id, config.name), + for (final NotifyTarget config in notifyTargets) + MultiSelectItem(config.id, + '${config.name} (${notifyTargetTypeString(config.type)})'), ], initialValue: targets.map((e) => e.targetId).toList(), @@ -191,25 +252,73 @@ class _NotifyFlowAddPageState extends State { return null; }, ), - for (final NotifyFlowTarget target in targets) + for (var i = 0; i < targets.length; i++) Column(children: [ + SpacingHelper.defaultDivider, + Align( + alignment: Alignment.centerLeft, + child: Text( + '${notifyTargets.firstWhere((e) => e.id == targets[i].targetId).name} (${notifyTargetTypeString(notifyTargets.firstWhere((e) => e.id == targets[i].targetId).type)})'), + ), const SizedBox( - height: 16, + height: 8, ), TextFormField( onChanged: (newValue) { setState(() { - targets[targets.indexWhere((e) => - e.targetId == target.targetId)] - .channelId = newValue; + targets[i].channelId = newValue; }); }, - decoration: InputDecoration( - border: const OutlineInputBorder(), - labelText: - '频道: ${state.notifyTargets?.firstWhere((e) => e.id == target.targetId).name ?? ''}', + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '频道', ), ), + const SizedBox( + height: 8, + ), + ExpandRailTile( + title: const Text('过滤器'), + children: [ + const SizedBox( + height: 8, + ), + TextFormField( + onChanged: (newValue) { + setState(() { + targets[i].filter = NotifyFilter( + includeKeywords: [newValue], + excludeKeywords: targets[i] + .filter + .excludeKeywords, + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '排除关键字', + ), + ), + const SizedBox( + height: 8, + ), + TextFormField( + onChanged: (newValue) { + setState(() { + targets[i].filter = NotifyFilter( + includeKeywords: targets[i] + .filter + .includeKeywords, + excludeKeywords: [newValue], + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '包含关键字', + ), + ), + ]), ]), ]), ), diff --git a/lib/view/pages/settings/notify/notify_flow_edit_page.dart b/lib/view/pages/settings/notify/notify_flow_edit_page.dart index 8cc8251..c99420b 100644 --- a/lib/view/pages/settings/notify/notify_flow_edit_page.dart +++ b/lib/view/pages/settings/notify/notify_flow_edit_page.dart @@ -7,7 +7,9 @@ import 'package:tuihub_protos/librarian/sephirah/v1/yesod.pb.dart'; import '../../../../bloc/netzach/netzach_bloc.dart'; import '../../../../bloc/yesod/yesod_bloc.dart'; +import '../../../../repo/grpc/l10n.dart'; import '../../../../route.dart'; +import '../../../components/expand_rail_tile.dart'; import '../../../components/toast.dart'; import '../../../form/form_field.dart'; import '../../../helper/spacing.dart'; @@ -42,6 +44,8 @@ class _NotifyFlowAddPageState extends State { } }, builder: (context, state) { + final notifySources = context.read().state.feedConfigs ?? []; + final notifyTargets = state.notifyTargets ?? []; if (state.notifyFlowEditIndex != null && state.notifyFlows != null) { final NotifyFlow flow = state.notifyFlows![state.notifyFlowEditIndex!]; @@ -136,40 +140,105 @@ class _NotifyFlowAddPageState extends State { ), Step( title: const Text('通知源'), - content: MultiSelectDialogField( - title: const Text('订阅源'), - buttonText: const Text('订阅'), - buttonIcon: const Icon(Icons.filter_alt_outlined), - items: [ - for (final ListFeedConfigsResponse_FeedWithConfig config - in context - .read() - .state - .feedConfigs ?? - []) - MultiSelectItem( - config.config.id, - config.feed.title.isNotEmpty - ? config.feed.title - : config.config.feedUrl), - ], - initialValue: - sources.map((e) => e.sourceId).toList(), - onConfirm: (values) { - sources = values - .map((e) => NotifyFlowSource(sourceId: e)) - .toList(); - }, - decoration: BoxDecoration( - borderRadius: SpacingHelper.defaultBorderRadius, + content: Column(children: [ + MultiSelectDialogField( + title: const Text('订阅源'), + buttonText: const Text('订阅'), + buttonIcon: const Icon(Icons.filter_alt_outlined), + items: [ + for (final ListFeedConfigsResponse_FeedWithConfig config + in notifySources) + MultiSelectItem( + config.config.id, + config.feed.title.isNotEmpty + ? config.feed.title + : config.config.feedUrl), + ], + initialValue: + sources.map((e) => e.sourceId).toList(), + onConfirm: (values) { + setState(() { + sources = values + .map((e) => NotifyFlowSource(sourceId: e)) + .toList(); + }); + }, + decoration: BoxDecoration( + borderRadius: SpacingHelper.defaultBorderRadius, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return '请选择至少一个订阅'; + } + return null; + }, ), - validator: (value) { - if (value == null || value.isEmpty) { - return '请选择至少一个订阅'; - } - return null; - }, - ), + for (var i = 0; i < sources.length; i++) + Column(children: [ + SpacingHelper.defaultDivider, + Align( + alignment: Alignment.centerLeft, + child: Text(notifySources + .firstWhere((e) => + e.config.id == sources[i].sourceId) + .feed + .title), + ), + const SizedBox( + height: 8, + ), + ExpandRailTile( + title: const Text('过滤器'), + children: [ + const SizedBox( + height: 8, + ), + TextFormField( + initialValue: sources[i] + .filter + .includeKeywords + .join(','), + onChanged: (newValue) { + setState(() { + sources[i].filter = NotifyFilter( + includeKeywords: [newValue], + excludeKeywords: sources[i] + .filter + .excludeKeywords, + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '排除关键字', + ), + ), + const SizedBox( + height: 8, + ), + TextFormField( + initialValue: sources[i] + .filter + .excludeKeywords + .join(','), + onChanged: (newValue) { + setState(() { + sources[i].filter = NotifyFilter( + includeKeywords: sources[i] + .filter + .includeKeywords, + excludeKeywords: [newValue], + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '包含关键字', + ), + ), + ]), + ]), + ]), ), Step( title: const Text('通知目标'), @@ -202,26 +271,82 @@ class _NotifyFlowAddPageState extends State { return null; }, ), - for (final NotifyFlowTarget target in targets) + for (var i = 0; i < targets.length; i++) Column(children: [ + SpacingHelper.defaultDivider, + Align( + alignment: Alignment.centerLeft, + child: Text( + '${notifyTargets.firstWhere((e) => e.id == targets[i].targetId).name} (${notifyTargetTypeString(notifyTargets.firstWhere((e) => e.id == targets[i].targetId).type)})'), + ), const SizedBox( - height: 16, + height: 8, ), TextFormField( - initialValue: target.channelId, + initialValue: targets[i].channelId, onChanged: (newValue) { setState(() { - targets[targets.indexWhere((e) => - e.targetId == target.targetId)] - .channelId = newValue; + targets[i].channelId = newValue; }); }, - decoration: InputDecoration( - border: const OutlineInputBorder(), - labelText: - '频道: ${state.notifyTargets?.firstWhere((e) => e.id == target.targetId).name ?? ''}', + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '频道', ), ), + const SizedBox( + height: 8, + ), + ExpandRailTile( + title: const Text('过滤器'), + children: [ + const SizedBox( + height: 8, + ), + TextFormField( + initialValue: targets[i] + .filter + .includeKeywords + .join(','), + onChanged: (newValue) { + setState(() { + targets[i].filter = NotifyFilter( + includeKeywords: [newValue], + excludeKeywords: targets[i] + .filter + .excludeKeywords, + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '排除关键字', + ), + ), + const SizedBox( + height: 8, + ), + TextFormField( + initialValue: targets[i] + .filter + .excludeKeywords + .join(','), + onChanged: (newValue) { + setState(() { + targets[i].filter = NotifyFilter( + includeKeywords: targets[i] + .filter + .includeKeywords, + excludeKeywords: [newValue], + ); + }); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: '包含关键字', + ), + ), + ]), ]), ]), ), diff --git a/lib/view/pages/settings/notify/notify_flow_page.dart b/lib/view/pages/settings/notify/notify_flow_page.dart index 9e09b68..f873f3d 100644 --- a/lib/view/pages/settings/notify/notify_flow_page.dart +++ b/lib/view/pages/settings/notify/notify_flow_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../bloc/netzach/netzach_bloc.dart'; import '../../../../bloc/yesod/yesod_bloc.dart'; +import '../../../../repo/grpc/l10n.dart'; import '../../../../route.dart'; class NotifyFlowPage extends StatelessWidget { @@ -94,6 +95,10 @@ class NotifyFlowPage extends StatelessWidget { maxLines: 2, ), Text(item.name), + Text( + '${item.sources.length}个源 | ${item.targets.length}个目标'), + Text( + '状态: ${notifyFlowStatusString(item.status)}'), Text(item.description), ], ), diff --git a/lib/view/pages/settings/notify/notify_target_page.dart b/lib/view/pages/settings/notify/notify_target_page.dart index f4e0de0..70a0be7 100644 --- a/lib/view/pages/settings/notify/notify_target_page.dart +++ b/lib/view/pages/settings/notify/notify_target_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../bloc/netzach/netzach_bloc.dart'; import '../../../../bloc/yesod/yesod_bloc.dart'; +import '../../../../repo/grpc/l10n.dart'; import '../../../../route.dart'; class NotifyTargetPage extends StatelessWidget { @@ -94,6 +95,10 @@ class NotifyTargetPage extends StatelessWidget { maxLines: 2, ), Text(item.name), + Text( + '类型: ${notifyTargetTypeString(item.type)}'), + Text( + '状态: ${notifyTargetStatusString(item.status)}'), Text(item.description), ], ),