Skip to content

MarketConfig

MarketConfig 持有市场仓库的 GitHub 坐标(owner / repo / branch / token),并提供所有 URL 构建方法。数据层通过它知道往哪发请求,不硬编码任何端点。

文件:lib/core/market/market_config.dart

enum MarketDir {
friend('friend', '.moodfriend'),
application('application', '.moodapp'),
packs('packs', '.moodpack');
final String path; // 仓库内目录名
final String suffix; // 插件包文件后缀
}

三个值对应三种插件类型,每个携带目录名和包文件后缀。用 MarketDir.friend.path 拿目录名,MarketDir.friend.suffix 拿 .moodfriend。

class MarketConfig {
final String owner;
final String repo;
final String branch;
final String? token;
const MarketConfig({
required this.owner,
required this.repo,
required this.branch,
this.token,
});
static const MarketConfig defaultConfig = MarketConfig(
owner: 'Tangmjiu',
repo: 'moodpet-plugin-market',
branch: 'main',
);
}
字段 类型 说明
owner String GitHub 用户/组织名
repo String 仓库名
branch String 分支/ref
token String? 可选 GitHub PAT,提高 API 限速到 5000 次/小时

预配置的官方市场常量。客户端默认用它。要指向自己的 fork,构造一个新实例即可:

final config = MarketConfig(
owner: 'my-org',
repo: 'my-plugin-market',
branch: 'main',
token: 'ghp_xxx', // 可选
);

Contents API URL,返回目录文件列表:

final url = config.contentsApiUrl(MarketDir.friend);
// https://api.github.com/repos/Tangmjiu/moodpet-plugin-market/contents/friend?ref=main

GitHub 返回 JSON 数组,每个元素是 {name, path, download_url, type, ...}。

Raw 文件 URL,CDN 加速,无限速:

final url = config.rawUrl('friend/moodpet.friend.default_smiley.meta.json');
// https://raw.githubusercontent.com/Tangmjiu/moodpet-plugin-market/main/friend/moodpet.friend.default_smiley.meta.json

metaPath(MarketDir dir, String id) → String

Section titled “metaPath(MarketDir dir, String id) → String”

插件 .meta.json 的仓库相对路径:

friend/moodpet.friend.default_smiley.meta.json
final p = config.metaPath(MarketDir.friend, 'moodpet.friend.default_smiley');

packagePath(MarketDir dir, String id) → String

Section titled “packagePath(MarketDir dir, String id) → String”

插件包的仓库相对路径:

friend/moodpet.friend.default_smiley.moodfriend
final p = config.packagePath(MarketDir.friend, 'moodpet.friend.default_smiley');

previewPath(MarketDir dir, String id) → String

Section titled “previewPath(MarketDir dir, String id) → String”

预览图的仓库相对路径:

friend/moodpet.friend.default_smiley.png
final p = config.previewPath(MarketDir.friend, 'moodpet.friend.default_smiley');

GitHub API 调用的请求头:

final headers = config.apiHeaders;
// {
// 'Accept': 'application/vnd.github+json',
// 'User-Agent': 'MoodPet-PluginMarket',
// 'Authorization': 'Bearer ghp_xxx' // 仅当 token 非 null
// }

Raw 下载的请求头(无 Authorization):

final headers = config.rawHeaders;
// {'User-Agent': 'MoodPet-PluginMarket'}
class MarketException implements Exception {
final String message;
final int? statusCode;
const MarketException(this.message, [this.statusCode]);
}

市场层失败时抛出。statusCode 是 HTTP 状态码(网络错误时为 null)。UI 的 .when(error:) 直接显示 e.message。

final config = MarketConfig.defaultConfig;
// 列出 friend 目录
final apiUrl = config.contentsApiUrl(MarketDir.friend);
final response = await http.get(
Uri.parse(apiUrl),
headers: config.apiHeaders,
);
// 下载某个插件的 meta.json
final metaUrl = config.rawUrl(
config.metaPath(MarketDir.friend, 'moodpet.friend.default_smiley'),
);
final metaResp = await http.get(
Uri.parse(metaUrl),
headers: config.rawHeaders,
);

在 Riverpod 里覆盖 marketConfigProvider:

ProviderScope(
overrides: [
marketConfigProvider.overrideWithValue(
const MarketConfig(
owner: 'my-org',
repo: 'my-plugin-market',
branch: 'main',
),
),
],
child: const MoodPetApp(),
)

这样客户端所有市场请求都指向你的仓库。