You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
6.7 KiB
208 lines
6.7 KiB
import 'package:flutter/material.dart';
|
|
|
|
import 'device_category.dart';
|
|
|
|
/// 功能模块(agent)定义。
|
|
///
|
|
/// AI 页与广场页共用同一份注册表:广场展示全部,AI 页只展示用户启用的那些,
|
|
/// 顺序由 [AgentModuleService] 持久化。新增 agent 只需往 [AgentModules.all]
|
|
/// 里加一条,两个页面自动生效。
|
|
class AgentModule {
|
|
const AgentModule({
|
|
required this.id,
|
|
required this.title,
|
|
required this.icon,
|
|
required this.gradient,
|
|
this.subtitle,
|
|
this.requiresDevice = false,
|
|
this.comingSoon = false,
|
|
});
|
|
|
|
/// 唯一标识,持久化时存的就是它,改名会导致用户已有配置失效
|
|
final String id;
|
|
|
|
/// i18n key,展示时 `.tr`(不是中文文案本身)
|
|
final String title;
|
|
|
|
/// i18n key,展示时 `.tr`
|
|
final String? subtitle;
|
|
final IconData icon;
|
|
|
|
/// 卡片图标底色渐变(两个色值)
|
|
final List<Color> gradient;
|
|
|
|
/// 是否依赖设备连接:未连接时卡片置灰,点击提示连接设备
|
|
final bool requiresDevice;
|
|
|
|
/// 尚未实现的占位模块:可以加到 AI 页排版,但点击只提示"敬请期待"
|
|
final bool comingSoon;
|
|
}
|
|
|
|
/// 全部可用模块的注册表
|
|
class AgentModules {
|
|
AgentModules._();
|
|
|
|
// ---------- 已实现(对应现有路由) ----------
|
|
static const String meeting = 'meeting';
|
|
static const String simultaneous = 'simultaneous';
|
|
static const String faceToFace = 'faceToFace';
|
|
static const String call = 'call';
|
|
static const String audioVideo = 'audioVideo';
|
|
static const String callRecording = 'callRecording';
|
|
static const String fieldRecording = 'fieldRecording';
|
|
|
|
/// EMAI 助手:原来 AI 页底部那颗悬浮球,改成广场里的一个正式 agent
|
|
static const String emaiAssistant = 'emaiAssistant';
|
|
static const String textTranslation = 'textTranslation';
|
|
static const String pictureTranslation = 'pictureTranslation';
|
|
|
|
// ---------- 规划中(占位,方便测试增删) ----------
|
|
static const String englishChat = 'englishChat';
|
|
static const String englishStudy = 'englishStudy';
|
|
static const String kidsStory = 'kidsStory';
|
|
|
|
static const List<AgentModule> all = [
|
|
AgentModule(
|
|
id: meeting,
|
|
title: 'agentMeeting',
|
|
subtitle: 'agentMeetingDesc',
|
|
icon: Icons.groups_2,
|
|
gradient: [Color(0xFFAB47BC), Color(0xFFEC407A)],
|
|
),
|
|
AgentModule(
|
|
id: emaiAssistant,
|
|
title: 'agentEmai',
|
|
subtitle: 'agentEmaiDesc',
|
|
icon: Icons.auto_awesome,
|
|
gradient: [Color(0xFF5B8DEF), Color(0xFF7E57C2)],
|
|
),
|
|
AgentModule(
|
|
id: simultaneous,
|
|
title: 'agentSimultaneous',
|
|
subtitle: 'agentSimultaneousDesc',
|
|
icon: Icons.record_voice_over,
|
|
gradient: [Color(0xFF4CAF50), Color(0xFF009688)],
|
|
),
|
|
AgentModule(
|
|
id: faceToFace,
|
|
title: 'agentFaceToFace',
|
|
subtitle: 'agentFaceToFaceDesc',
|
|
icon: Icons.forum,
|
|
gradient: [Color(0xFF42A5F5), Color(0xFF1E88E5)],
|
|
),
|
|
AgentModule(
|
|
id: callRecording,
|
|
title: 'agentCallRecording',
|
|
subtitle: 'agentCallRecordingDesc',
|
|
icon: Icons.fiber_manual_record,
|
|
gradient: [Color(0xFFEF5350), Color(0xFFE53935)],
|
|
requiresDevice: true,
|
|
),
|
|
AgentModule(
|
|
id: fieldRecording,
|
|
title: 'agentFieldRecording',
|
|
// 有设备走设备录音通路,没设备退回手机麦克风,两种情况都能用
|
|
subtitle: 'agentFieldRecordingDesc',
|
|
icon: Icons.mic,
|
|
gradient: [Color(0xFF26C6DA), Color(0xFF00838F)],
|
|
),
|
|
AgentModule(
|
|
id: call,
|
|
title: 'agentCall',
|
|
subtitle: 'agentCallDesc',
|
|
icon: Icons.phone_in_talk,
|
|
gradient: [Color(0xFFFFA726), Color(0xFFFB8C00)],
|
|
requiresDevice: true,
|
|
),
|
|
AgentModule(
|
|
id: audioVideo,
|
|
title: 'agentAudioVideo',
|
|
subtitle: 'agentAudioVideoDesc',
|
|
// 放映机图标:这个功能是音视频内容翻译,用投影/放映的意象更贴切
|
|
icon: Icons.slideshow,
|
|
gradient: [Color(0xFF5C6BC0), Color(0xFF3949AB)],
|
|
),
|
|
AgentModule(
|
|
id: textTranslation,
|
|
title: 'agentTextTranslation',
|
|
subtitle: 'agentTextTranslationDesc',
|
|
icon: Icons.translate,
|
|
gradient: [Color(0xFF26A69A), Color(0xFF00796B)],
|
|
),
|
|
AgentModule(
|
|
id: pictureTranslation,
|
|
title: 'agentPictureTranslation',
|
|
subtitle: 'agentPictureTranslationDesc',
|
|
icon: Icons.image_search,
|
|
gradient: [Color(0xFFEC407A), Color(0xFFAD1457)],
|
|
),
|
|
AgentModule(
|
|
id: englishChat,
|
|
title: 'agentEnglishChat',
|
|
subtitle: 'agentEnglishChatDesc',
|
|
icon: Icons.chat_bubble_outline,
|
|
gradient: [Color(0xFF7E57C2), Color(0xFF5E35B1)],
|
|
comingSoon: true,
|
|
),
|
|
AgentModule(
|
|
id: englishStudy,
|
|
title: 'agentEnglishStudy',
|
|
subtitle: 'agentEnglishStudyDesc',
|
|
icon: Icons.menu_book,
|
|
gradient: [Color(0xFF29B6F6), Color(0xFF0288D1)],
|
|
comingSoon: true,
|
|
),
|
|
AgentModule(
|
|
id: kidsStory,
|
|
title: 'agentKidsStory',
|
|
subtitle: 'agentKidsStoryDesc',
|
|
icon: Icons.auto_stories,
|
|
gradient: [Color(0xFFFF7043), Color(0xFFF4511E)],
|
|
comingSoon: true,
|
|
),
|
|
];
|
|
|
|
/// AI 页首次进入时的默认模块。
|
|
///
|
|
/// 没连过设备也能用的三个(都只依赖手机本身):语音记录助手、EMAI助手、现场录音。
|
|
/// 依赖设备的功能等连上对应设备后由 [defaultsForCategory] 自动补进来。
|
|
static const List<String> defaultEnabled = [
|
|
// 网格区(左大 + 右上下两小)
|
|
call,
|
|
simultaneous,
|
|
faceToFace,
|
|
// 并排方块
|
|
meeting,
|
|
audioVideo,
|
|
// 往下是整行横条,现场录音是第一行
|
|
fieldRecording,
|
|
callRecording,
|
|
textTranslation,
|
|
pictureTranslation,
|
|
emaiAssistant,
|
|
];
|
|
|
|
/// 各设备品类**第一次连接成功**时要铺到 AI 页的默认功能与顺序。
|
|
///
|
|
/// key 用的是 [DeviceCategories] 的品类 id。只在该品类首次连接时生效一次
|
|
/// (由 AgentModuleService 记录已应用过的品类),之后用户怎么增删排序都不再覆盖。
|
|
static const Map<String, List<String>> defaultsByCategory = {
|
|
// AI手机支架 / AI录音卡片:只有录音相关能力,AI 页就只留这三个
|
|
DeviceCategories.phoneHolder: [meeting, fieldRecording, callRecording],
|
|
DeviceCategories.noteCard: [meeting, fieldRecording, callRecording],
|
|
// AI耳机(恒玄):通话 + 翻译整套都能跑,铺开全量默认编排
|
|
DeviceCategories.earphone: defaultEnabled,
|
|
};
|
|
|
|
static List<String> defaultsForCategory(String? categoryId) {
|
|
if (categoryId == null) return const [];
|
|
return defaultsByCategory[categoryId] ?? const [];
|
|
}
|
|
|
|
static AgentModule? byId(String id) {
|
|
for (final m in all) {
|
|
if (m.id == id) return m;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|