Compare commits

..

325 Commits

Author SHA1 Message Date
shenmo7192 e16acbd0a5 refactor(installer): 调整下载重试超时配置和次数
更新了下载重试的超时时间列表和总重试次数,从原3次调整为10次,优化下载成功率
2026-05-13 21:13:25 +08:00
shenmo7192 8a5f8d154f feat: 添加APM安装确认弹窗并重构APM检查流程
1. 新增全局状态控制APM安装弹窗显示
2. 新建ApmInstallConfirmModal弹窗组件
3. 将主进程的APM安装弹窗逻辑迁移到前端Vue组件
4. 更新package.json版本到5.1.0
5. 简化安装和升级流程中的APM检查逻辑
2026-05-12 21:54:47 +08:00
shenmo7192 8c8b53fc29 update tool/apt-fast/ss-apt-fast.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2026-05-09 15:04:46 +00:00
shenmo7192 c50655c106 !389 dark下的效果还是怪怪的重新改一下,还有统一应用管理和软件更新的按钮样式
Merge pull request !389 from zeqi/Erotica
2026-05-03 04:02:34 +00:00
zeqi 4b37aa4da4 dark下的效果还是怪怪的重新改一下,还有统一应用管理和软件更新的按钮样式
Signed-off-by: zeqi <a202128502@163.com>
2026-05-03 02:35:28 +00:00
shenmo7192 ce5de692f7 修复 Ubuntu 26.04 上无法正常安装的问题
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2026-04-30 15:29:13 +00:00
shenmo7192 3d4af0c492 改为5.0.1 2026-04-25 14:40:37 +08:00
shenmo7192 c39b25e393 5.1 2026-04-25 14:33:21 +08:00
shenmo7192 2086152aa5 refactor: 移除缓存清除函数并直接使用原始URL
移除cacheBuster函数及其所有调用,改为直接使用原始URL进行请求
2026-04-25 14:25:52 +08:00
shenmo7192 f8f112a782 !388 feat(build): add loong64 to build
Merge pull request !388 from AAA Elysia 猫猫侠 ⁧~喵/elysia/add-loong64
2026-04-21 14:04:55 +00:00
Elysia 6a9091b2ec feat(build): add loong64
- Downgrad electron for the sake of loong64
- Add my project to CREDIT.md

Signed-off-by: Elysia <a.elysia@proton.me>
2026-04-19 09:37:21 +08:00
shenmo7192 994dbaf9b9 !387 优化dark模式下应用管理的关闭按钮和刷新按钮、软件更新的关闭按钮的hover效果
Merge pull request !387 from zeqi/Erotica
2026-04-16 22:59:56 +00:00
zeqi 9c9f0b6076 优化dark模式下应用管理的关闭按钮和刷新按钮、软件更新的关闭按钮的hover效果
Signed-off-by: zeqi <a202128502@163.com>
2026-04-16 15:27:55 +00:00
shenmo7192 42046caf2c feat(update-center): 添加加载状态处理及UI优化
为更新中心添加加载状态管理,包括:
- 在打开和刷新操作时显示加载状态
- 禁用刷新按钮防止重复操作
- 添加加载中的动画效果和提示文本
- 优化加载时的UI显示
2026-04-16 14:00:33 +08:00
shenmo7192 e72553d570 feat(update-center): 添加详细日志记录以帮助调试更新中心服务
在更新中心服务的关键路径添加console.log和console.error输出
包括服务刷新、包解析、命令执行等环节的输入输出和中间状态
便于排查更新中心相关的问题
2026-04-16 13:48:08 +08:00
momen 309b9bc003 fix(update-center): load aptss updates reliably 2026-04-16 13:32:23 +08:00
momen 0b784af3d7 fix(sources): hide unavailable update and management entries 2026-04-16 13:04:54 +08:00
momen e1ec526cb9 fix(update-center): handle missing apm and restore scrolling 2026-04-16 11:11:06 +08:00
shenmo7192 120233cf56 feat(settings): 添加安装设置模态框及配置管理功能
实现安装设置功能,包括更新检测通知和自动创建桌面启动器的开关配置
重构原有的安装设置逻辑,使用模态框替代直接调用脚本
新增 IPC 接口用于获取和保存设置配置
2026-04-16 00:35:37 +08:00
shenmo7192 a2d4192592 chore: 更新版本号至5.0.0 2026-04-16 00:22:06 +08:00
shenmo7192 c907fbb5d4 refactor(AppDetailModal): 优化应用详情弹窗的布局和样式
将版本号和下载量合并显示,并调整应用来源切换的布局结构
2026-04-16 00:21:38 +08:00
shenmo7192 68dd6a0a26 perf(spark): 优化已安装应用检查逻辑
- 对于 Spark 应用,使用 dpkg-query 替代自定义脚本检查安装状态
- 在 list-installed 接口中支持传入包名列表进行批量检查,避免全量扫描
- 添加 aptss 可用性检查,避免在不可用时执行相关命令
- 移除冗余的 check-installed 二次验证步骤
2026-04-16 00:10:14 +08:00
shenmo7192 9eb141ee35 fix: 简化包安装检查逻辑并添加二次确认
移除复杂的ACE环境检查逻辑,仅保留基本的dpkg检查
在App.vue中添加二次确认步骤以确保包真实安装
2026-04-15 23:40:30 +08:00
momen f9aa31d257 fix(update-center): align modal actions and tests 2026-04-15 22:21:35 +08:00
momen 1410a80df5 fix(installed-apps): restore open and detail actions 2026-04-15 22:10:02 +08:00
momen fcdd982637 docs(update-center): add no-aptss handling design 2026-04-15 21:49:25 +08:00
momen bed2d43e0e fix(update): 聚合 Spark 和 APM 升级通知 2026-04-15 20:49:15 +08:00
momen 44587e299a fix(lint): 清理未使用的安装器符号 2026-04-15 14:11:46 +08:00
momen 36f5d3831e fix(update): 统一忽略更新配置到用户目录 2026-04-15 11:44:18 +08:00
momen 51664619f5 修复更新器打开卡顿,优化更新中心 2026-04-15 10:55:47 +08:00
xiyidaiwa bd8b50677e !385 !1 refactor(AppHeader): 优化搜索输入框交互及样式
Merge pull request !385 from xiyidaiwa/Erotica
2026-04-15 02:45:07 +00:00
shenmo7192 78c9679f88 !383 feat(搜索): 为搜索输入框添加清除按钮功能
Merge pull request !383 from xiyidaiwa/Erotica
2026-04-14 07:49:56 +00:00
xiyidaiwa c9c84e518b feat(搜索): 为搜索输入框添加清除按钮功能
在AppHeader和UpdateCenterToolbar组件中为搜索输入框添加清除按钮
点击按钮可清空搜索内容并触发相应事件
2026-04-14 14:07:23 +08:00
momen f044c6c3df 修复更新中心发送的下载项和普通下载故障覆盖的问题 2026-04-13 13:29:58 +08:00
shenmo7192 763af5c37e feat(update-center): 添加全选功能及状态管理
添加全选复选框组件及相关状态管理逻辑
实现全选/取消全选功能
添加部分选中状态显示
更新工具栏组件以支持新功能
2026-04-12 22:02:01 +08:00
shenmo7192 ca7520cb2e fix(modal): 修复模态框滚动和点击事件处理
为多个模态框组件添加滚动和点击事件处理,防止背景滚动时内容滚动
当点击模态框背景时关闭模态框,同时阻止事件冒泡到内容区域
2026-04-12 21:34:51 +08:00
shenmo7192 ba10f90dde fix(滚动): 为多个组件添加overscroll-contain并处理滚轮事件
为多个模态框和列表组件添加overscroll-contain类以防止滚动链
添加处理函数阻止模态框背景的滚轮事件传播到内容区域
2026-04-12 21:30:33 +08:00
shenmo7192 a280d44481 fix(下载队列): 为滚动容器添加overscroll-contain防止滚动溢出
refactor(安装管理器): 移除upgradeOnly逻辑并统一使用ssinstall命令

test(更新中心): 更新测试用例以匹配新的安装逻辑
2026-04-12 21:25:10 +08:00
shenmo7192 9244708b90 feat(安装管理器): 添加安装参数以禁用桌面快捷方式和使用原生安装
添加 --no-create-desktop-entry 和 --native 参数以避免创建桌面快捷方式并确保使用原生安装方式
2026-04-12 21:14:06 +08:00
shenmo7192 c46bb03e3f fix: 将host-spawn替换为systemd-run --user以提升兼容性 2026-04-12 21:01:33 +08:00
momen 71db2f2b71 fix: 现在软件管理器滚到底部后应用列表不会透滚 2026-04-12 19:44:54 +08:00
momen 67aa83fe26 update 修复更新工具缺少软件名检查的问题 2026-04-12 19:39:17 +08:00
momen 60628ff1fa test: 支持更新下载时展示图标 2026-04-12 19:11:11 +08:00
shenmo7192 81cd00661c docs: 添加项目主页链接到package.json 2026-04-12 19:04:10 +08:00
shenmo7192 5ebbf8c223 build: 更新electron构建配置和vite别名设置
更新electron-builder.yml中的linux平台图标配置
在vite.config.ts中添加路径别名解析配置
2026-04-12 19:03:56 +08:00
momen 68ab999eed update 尝试修复点击更新后无法推送到下载列表的问题 2026-04-12 19:00:14 +08:00
momen 9080d76575 docs(update-center): add implementation notes 2026-04-12 18:00:06 +08:00
shenmo7192 e2f59b3cdf 复用下载中心(1/2) 2026-04-12 17:53:16 +08:00
shenmo7192 6fcfa438d9 feat(update-center): 统一使用下载包文件进行安装
- 移除 buildLegacySparkUpgradeCommand,所有更新现在需要先下载 deb 包
- 为 APTSS 添加元数据查询功能
- 优化 aria2c 下载参数,使用 metalink URL
- 版本号更新至 5.0.0beta4
2026-04-12 16:44:55 +08:00
momen fa2689c753 feat(search): prioritize app name matches 2026-04-11 16:47:51 +08:00
shenmo7192 7bf2a5c55b beta4 集成更新器
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2026-04-11 08:34:00 +00:00
momen 62c1e51223 chore: 移除并重新添加 engines 字段到 package-lock.jsonm,就解决风险插件问题 2026-04-11 14:26:55 +08:00
momen a4a2ec4216 chore(deps): secure electron builder toolchain
Refresh the Loong electron-builder stack to clear npm audit findings and declare the Node.js floor required by the updated build tooling.
2026-04-11 14:13:32 +08:00
momen a513c81606 !382 fix(update-center): cascade local and remote icon fallbacks
Merge pull request !382 from momen/update-center-icon-fallback
2026-04-11 03:55:27 +00:00
momen 180b88b5c0 fix(update-center): cascade local and remote icon fallbacks
Keep update list icons from dropping straight to placeholders by retrying the remote store icon after local load failures. Align the update-center IPC and renderer types with the split local/remote icon contract.
2026-04-11 11:41:01 +08:00
momen c16ba5536f feat(update-center): add update list icons 2026-04-10 21:15:43 +08:00
shenmo7192 bcef173049 !381 feat(滚动): 添加分类切换时重置虚拟滚动位置功能
Merge pull request !381 from momen/feat-electron-update-center
2026-04-10 09:28:47 +00:00
momen 1d51f38e64 feat(滚动): 添加分类切换时重置虚拟滚动位置功能
添加 scrollKey 属性到 AppGrid 组件,当分类变化时自动重置滚动位置
添加相关单元测试验证滚动重置功能
2026-04-10 16:17:38 +08:00
momen 4a2cbe1f2a fix(update-center): 将apm命令从ssaudit改为ssinstall并优化打印URI命令
更新apm安装命令,使用ssinstall替代ssaudit以正确执行安装操作。同时优化获取包URI的命令,使用更可靠的bash调用方式。
2026-04-10 15:34:33 +08:00
momen 0b17ada45a feat(update-center): 实现集中式软件更新中心功能
新增更新中心模块,支持管理 APM 和传统 deb 软件更新任务
- 添加更新任务队列管理、状态跟踪和日志记录功能
- 实现更新项忽略配置持久化存储
- 新增更新确认对话框和迁移提示
- 优化主窗口关闭时的任务保护机制
- 添加单元测试覆盖核心逻辑
2026-04-09 08:19:51 +08:00
shenmo7192 97bb8e5f59 LICENSE to GPL3 2026-04-05 22:56:11 +08:00
shenmo7192 a1e0d7f301 fix: 将aptss升级失败的错误提示从弹窗改为日志输出 2026-04-05 22:50:45 +08:00
shenmo7192 593cb8ea75 feat(应用管理): 添加 APM 可用性检查并调整相关逻辑
当 APM 不可用时,自动切换到 Spark 应用管理
禁用 APM 软件标签页的切换按钮
移除侧边栏中 APM 可用性检查的冗余条件
2026-04-05 22:48:19 +08:00
shenmo7192 f7424ba4a7 修复 shell-caller 无法安装 apm 的问题 2026-04-05 22:34:39 +08:00
shenmo7192 04004c2b85 修复fedora安装指令 2026-04-05 21:07:17 +08:00
shenmo7192 445fbba391 更新: 优化readme格式 2026-04-05 16:39:06 +08:00
shenmo7192 1618b9a82f fix(install-manager): 修正APM安装成功后的提示信息
更新安装成功提示信息,移除关于启动器展示应用的说明,并明确重启电脑后才能使用全部功能
2026-04-05 11:58:22 +08:00
shenmo7192 bcae531387 feat(组件): --no-spark时不展示 Spark 应用管理
在InstalledAppsModal和AppSidebar组件中添加storeFilter属性,用于控制不同应用商店的显示逻辑
2026-04-05 11:53:12 +08:00
shenmo7192 8be9e1a6cb chore: 更新图库中的图片文件 2026-04-05 11:30:34 +08:00
shenmo7192 62a5adf13c modified: README.md 2026-04-05 11:29:07 +08:00
shenmo7192 21366b7fc7 docs: 更新README文档内容
- 精简并重构README文档结构
- 更新支持的Linux发行版列表
- 简化安装说明流程
- 优化APM特性描述
- 移除过时和冗余的技术细节
2026-04-05 11:27:39 +08:00
shenmo7192 012c589fba fix(spark-store): 调整zenity提示框宽度并添加银河麒麟说明
增加zenity提示框的宽度以避免文本显示不全,并针对银河麒麟用户添加APM网页版商店的说明
2026-04-05 11:09:44 +08:00
shenmo7192 462cdc38bf feat(aptssupdater): 添加包安装状态检查方法并优化更新合并逻辑
添加 isPackageInstalledInAptss 和 isPackageInstalledInApm 方法检查包安装状态
优化 mergeUpdateInfo 逻辑,根据包安装状态判断是否为迁移场景
2026-04-05 10:57:22 +08:00
shenmo7192 1becfbc9be feat(迁移功能): 添加包迁移功能支持
实现从aptss到apm的包迁移功能
- 添加迁移包集合存储用户确认的迁移项
- 在数据模型中添加迁移相关字段
- 修改合并逻辑以识别迁移场景
- 添加迁移确认对话框
- 处理迁移安装时的特殊逻辑
2026-04-05 10:49:03 +08:00
shenmo7192 f395d654ea fix(aptss): 添加aptss命令存在性检查并支持apm更新
在运行aptss相关操作前检查命令是否存在,避免错误执行
同时添加对apm命令的支持,当aptss不存在时尝试使用apm更新
2026-04-05 10:26:09 +08:00
shenmo7192 3214a5a18c docs: 更新项目文档以反映从APM到星火应用商店的变更
更新项目名称、仓库地址、技术栈和目录结构,新增配套工具Spark Update Tool的详细说明
2026-04-05 10:23:08 +08:00
shenmo7192 b5d7708b58 feat(组件): 为应用详情模态框添加网站链接点击功能 2026-04-05 10:08:45 +08:00
shenmo7192 4e9fc30616 feat(storeConfig): 添加配置文件存在标记并调整默认优先级规则
添加 hasPriorityConfigFile 标记以区分服务器是否存在配置文件
当没有配置文件时默认优先 Spark,有配置文件但规则为空时默认优先 APM
移除未使用的 matchesRule 方法并添加 isConfigEmpty 方法
2026-04-05 09:55:47 +08:00
shenmo7192 d74e05a327 feat(store): 实现混合仓库优先级配置功能
添加优先级配置文件支持,根据配置决定默认展示的仓库版本
新增优先级规则匹配逻辑,支持包名、分类和标签匹配
修改应用详情和合并应用的默认来源判断逻辑
2026-04-05 09:52:06 +08:00
shenmo7192 70f6c8e812 feat 启动脚本检查换成 apt
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2026-04-04 14:19:32 +00:00
shenmo7192 80291aef7c Merge V4 2026-04-04 17:28:58 +08:00
momen b836392ffb update:应用列表中,spark软件列表加入图标 2026-03-31 20:31:45 +08:00
momen fdb5f4a51c update:apm管理改为应用管理 2026-03-31 20:25:44 +08:00
shenmo7192 57410370b7 feat(apm): 在安装和更新应用前检查并提示安装APM
添加APM可用性检查逻辑,在安装或更新APM应用时,若检测到APM未安装,则弹出对话框提示用户安装
安装流程完成后显示成功提示并告知需要重启电脑
2026-03-30 18:39:03 +08:00
shenmo7192 dd7e4adead beta3 2026-03-29 19:54:04 +08:00
shenmo7192 845904c0d1 build: 更新版本号至5.0.0beta2 2026-03-29 19:44:22 +08:00
shenmo7192 0dedd0faf0 feat(组件): 添加虚拟滚动优化应用网格性能
为AppGrid组件添加vue-virtual-scroller实现虚拟滚动功能,当应用数量超过50个时自动启用
更新package.json添加vue-virtual-scroller依赖
添加vue-virtual-scroller的类型声明
优化网格布局响应式处理,根据窗口宽度动态调整列数
2026-03-29 19:43:53 +08:00
shenmo7192 f382e6d75d feat(组件): 添加应用商店过滤功能并优化来源标识显示
在AppGrid组件中添加storeFilter属性以支持应用商店过滤
重构AppCard组件的来源标识显示逻辑,新增合并标识显示
当storeFilter为'both'时显示合并标识,否则显示单独标识
2026-03-29 19:34:38 +08:00
shenmo7192 dd0a17d674 style(组件): 优化应用详情模态框按钮样式和布局
- 调整按钮圆角、内边距和阴影样式
- 修改安装按钮颜色方案
- 重构已安装应用的按钮布局为水平排列
- 更新卸载按钮样式为轮廓风格
- 统一图标大小
2026-03-29 18:31:14 +08:00
shenmo7192 cbea4745a5 fix(InstalledAppsModal): 添加点击遮罩层关闭模态框功能 2026-03-29 18:26:39 +08:00
shenmo7192 29460e727b feat(组件): 添加搜索结果为空时的提示界面 2026-03-29 17:25:15 +08:00
shenmo7192 e7fb8e689a feat(应用详情): 增强应用详情页功能并优化代码格式
重构应用详情页逻辑,支持从首页和深度链接直接打开应用时自动获取完整信息
优化应用卡片来源标识显示,支持同时显示多个来源
统一代码格式,修复多行字符串和模板字符串的换行问题
2026-03-29 17:21:17 +08:00
shenmo7192 94f4307783 perf(安装日志): 优化安装日志处理性能
添加日志缓冲和批量发送机制以减少IPC通信次数
限制前端日志条目数量防止内存泄漏
2026-03-29 16:36:58 +08:00
shenmo7192 a8d462395a chore: 更新版本号至5.0.0beta1 2026-03-29 15:40:46 +08:00
shenmo7192 2d02e2afee fix(install-manager): 取消安装时删除下载目录
在取消安装任务时,增加删除下载目录的逻辑以避免残留文件
2026-03-29 15:23:24 +08:00
shenmo7192 ad5562700f feat: 优化应用商店界面布局和交互体验
refactor(HomeView): 调整网格布局和卡片样式,增加欢迎页面
refactor(AppDetailModal): 重构应用详情弹窗布局,增加元数据展示和返回按钮
fix(spark-store): 添加dpkg命令检查逻辑
style: 统一调整部分间距和颜色样式
2026-03-29 15:22:55 +08:00
shenmo7192 33c48f4543 fix(安装管理): 将 ssaudit 命令替换为 ssinstall 并添加版本检查
弃用 ssaudit 命令,统一使用 ssinstall 进行安装
在 shell-caller.sh 中添加对 ssaudit 的禁用检查和 ssinstall 失败时的版本提示
2026-03-29 14:24:58 +08:00
shenmo7192 5b2d96cf0a feat: 实现搜索结果的分类计数功能
添加搜索关键词时显示匹配结果数量的功能,同时优化了应用卡片和网格的UI样式
2026-03-29 14:21:48 +08:00
shenmo7192 d144d0d398 feat(UI): 优化应用加载体验和界面样式
改进应用网格布局的边距设置
在App.vue中改为非阻塞方式加载数据
为侧边栏添加内边距
在HomeView中优化图片加载状态显示和条件渲染
2026-03-29 14:07:54 +08:00
shenmo7192 3f9447d2cc feat(deep-link): 支持通过 store 协议直接打开应用详情
添加对 legacy store 协议格式的支持,当收到 spk://store/category/pkgname 格式的 deep link 时,忽略 category 直接使用 pkgname 查找并打开应用详情。如果应用未找到,则回退到搜索模式。
2026-03-29 13:58:52 +08:00
shenmo7192 1e6e776afe fix(install-manager): 改进已安装应用列表的解析逻辑
增强对APM包名的解析,支持带或不带section的格式
添加更多调试日志以帮助排查问题
2026-03-29 12:48:09 +08:00
shenmo7192 596515e0a4 fix(install-manager): 优化已安装应用列表获取逻辑并改进安装成功提示
使用 `apm list --installed` 命令替代直接读取文件系统来获取已安装应用列表,提高可靠性
改进安装成功提示信息,更清晰地说明重启和立即使用的选项
2026-03-29 12:43:05 +08:00
shenmo7192 aec1faf964 fix(install): 允许添加不同来源的安装相同包名任务
改进任务重复检查逻辑,现在会同时检查软件包名称和来源
修复取消下载时未正确处理任务状态的问题
```

```msg
ci: 添加测试和构建的GitHub Actions配置文件

添加test.yml和build.yml的备份文件,包含单元测试、E2E测试和构建流程
2026-03-29 12:23:32 +08:00
shenmo7192 033735d476 fix(下载): 优化下载重试逻辑,使用递增超时时间
将固定30秒超时改为递增超时机制(3秒/5秒/15秒)
缩短进度检查间隔至1秒,提高响应速度
2026-03-29 12:06:10 +08:00
shenmo 5951bd1d35 Ban apm debug 2026-03-29 01:54:10 +08:00
momen d638ef7122 fix:修复取消下载后无法重试下载的问题,修复重试下载后没有日志输出的问题 2026-03-27 11:39:36 +08:00
momen 835572dabd update:重复下载包时删除掉已有包 2026-03-27 11:33:57 +08:00
shenmo7192 b9c431ffdc 提升安装 APM 的体验 2026-03-25 18:35:01 +08:00
shenmo7192 d314ad6548 去除应用计数 2026-03-24 21:26:31 +08:00
shenmo7192 d8758834c3 APM 应用管理界面不再随着滚轮滚动 2026-03-24 21:20:59 +08:00
shenmo7192 308f5b7ce6 feat: 通过 IPC 实现应用版本号获取功能
移除预加载脚本中的版本号获取逻辑,改为通过 IPC 从主进程获取
2026-03-24 20:58:15 +08:00
shenmo7192 7b71522afb refactor: 简化安装完成回调函数的条件判断 2026-03-24 20:50:38 +08:00
shenmo7192 7ff079276e feat: 添加 APM 应用管理功能并优化界面
- 新增 APM 应用管理功能,支持显示已安装应用及其依赖项
- 优化已安装应用列表界面,增加应用图标和名称显示
- 调整顶部操作栏布局,将设置和关于按钮移至搜索框旁
- 修复类型定义,增加 isDependency 字段和更多应用信息
- 改进暗色模式下的界面显示效果
2026-03-24 20:47:55 +08:00
shenmo7192 480a7f3b77 update 降低超时时长 2026-03-22 19:29:33 +08:00
shenmo7192 cd43f34cbd feat: 添加关于对话框并优化主题切换按钮样式
- 新增 AboutModal 组件显示应用版本和相关信息
- 重构 ThemeToggle 组件为更简洁的图标按钮
- 在侧边栏添加关于按钮并实现打开对话框功能
- 通过预加载脚本获取 package.json 版本号
- 支持命令行参数 --version/-v 显示版本号
2026-03-22 19:18:19 +08:00
shenmo7192 c7761e8468 fix(下载): 增强aria2c下载的稳定性和重试机制
添加连接超时、下载超时和重试参数配置
实现0%卡死检测和自动重试逻辑
移除冗余的dpkg-query检测代码
优化安装按钮状态判断逻辑
更新版本号至4.9.9alpha4
2026-03-22 18:35:41 +08:00
shenmo 788cf2ecf0 Update spark-store 2026-03-17 19:02:36 +08:00
shenmo7192 bf6113581b 禁止ACE自动尝试 2026-03-15 17:55:13 +08:00
shenmo7192 6729e321a6 去除界面优化 2026-03-15 17:00:58 +08:00
shenmo7192 74b1f65ab1 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-15 16:44:46 +08:00
shenmo7192 5d58f2a801 modified: .vscode/launch.json 2026-03-15 16:43:44 +08:00
shenmo7192 dbfe86aa64 feat: enhance UI and functionality across components
- Added Google Fonts preconnect and stylesheet link in `index.html` for improved typography.
- Updated version in `package.json` to `4.9.9alpha3`.
- Refined launch configuration by removing deprecated arguments.
- Improved app detail modal and card components for better accessibility and visual consistency.
- Enhanced download queue and sidebar components with updated styles and functionality.
- Implemented new utility classes for better styling control in CSS.
- Adjusted various components for improved responsiveness and user experience.
2026-03-15 15:21:29 +08:00
shenmo7192 7e1f85c058 修复切换页签时会清空搜索框的问题 2026-03-15 14:47:48 +08:00
shenmo7192 6e725e25c8 refactor: update tray icon handling and add APM installation checks
- Removed the deprecated `--no-spark` argument from launch configuration.
- Enhanced tray icon management by introducing a new function to resolve icon paths based on application packaging status.
- Implemented APM installation checks in the install manager, prompting users to install APM if not available, with appropriate dialog messages and handling for installation success or failure.
- Added a new shell script for executing the Spark Store with environment checks for container and architecture compatibility.
2026-03-15 14:20:28 +08:00
shenmo7192 7e18ba7981 update:修复无法创建托盘的问题 2026-03-15 11:27:53 +08:00
shenmo7192 b3ca2973f1 feat: implement store filter based on launch arguments
- Added a new function to determine the store filter based on the `--no-apm` and `--no-spark` launch arguments.
- Integrated IPC to retrieve the store filter in the main process and updated the Vue component to reflect the selected filter.
- Adjusted logic in the app loading functions to conditionally display apps based on the determined filter.
2026-03-15 11:04:22 +08:00
shenmo7192 4ecea4a8b8 feat: enhance app detail modal to prioritize installed version based on installation status
- Updated `openDetail` function to check installation status for both Spark and APM versions, setting `viewingOrigin` accordingly.
- Modified logic to determine which app version to display in screenshots based on installation status.
- Improved handling of `viewingOrigin` in `AppDetailModal.vue` to default to Spark if no specific version is installed.
2026-03-15 10:54:33 +08:00
shenmo b0ec3d50c4 Merge pull request #13 from vmomenv/main
将apm和spark合并显示
2026-03-15 08:52:53 +08:00
momen cbaf55cbb9 Merge pull request #10 from vmomenv/fix-download-source-display-1703167915447601691
fix: correctly display download source based on app origin
2026-03-12 17:15:51 +08:00
vmomenv 16066d0b5f fix: correctly display download source based on app origin
When downloading applications, the download source was incorrectly
hardcoded to always show "APM Store" in the DownloadDetail component.
This changes it to use the `download.origin` property to accurately
display either "Spark Store" or "APM Store" based on the application's
origin, without altering any underlying download logic.
2026-03-12 09:12:38 +00:00
momen 006a5df550 Merge pull request #9 from vmomenv/feat/app-detail-version-install-status-3216925028679313814
feat: display cross-version installation status in app detail modal
2026-03-12 16:54:55 +08:00
vmomenv 7635697495 test(e2e): fix failing playwright tests by mocking electron ipc and api calls
- Updated `e2e/basic.spec.ts` to inject a mock `window.ipcRenderer` and `window.apm_store` on test startup. Playwright connects to the Vite dev server via standard Chromium, which previously caused the app to crash due to missing Electron contexts.
- Added `page.route` intercepts to return valid mock data for categories and apps, ensuring that components like `.app-card` actually render in the E2E environment instead of being stuck in a loading state or failing.
- Removed arbitrary timeouts and `127.0.0.1:3344` URL.
2026-03-12 08:46:49 +00:00
vmomenv 034f86b82f fix: add origin property to DownloadResult and update test config
- Updated `src/global/typedefinition.ts` to include optional `origin` property in `DownloadResult` to fix TypeScript compilation error where `remove-complete` payload didn't have it defined.
- Added `origin` payload in `electron/main/backend/install-manager.ts`.
- Updated `e2e/basic.spec.ts` URL to `/` and expecting title including `星火应用商店` to match E2E setup.
2026-03-12 08:27:37 +00:00
vmomenv 1fb81c0409 feat: display cross-version installation status in app detail modal
- Replaced single `currentAppIsInstalled` boolean with `currentAppSparkInstalled` and `currentAppApmInstalled` in global store.
- Updated `checkAppInstalled` logic in `App.vue` to fetch the installation status for both Spark and APM versions via `ipcRenderer`.
- Passed both flags to `AppDetailModal.vue` as props.
- Enhanced `AppDetailModal.vue` to compute the "install" button text dynamically: if viewing Spark and APM is installed, it displays `(已安装apm版)`; if viewing APM and Spark is installed, it displays `(已安装spark版)`. The button is also disabled in these scenarios to prevent duplicate cross-version installations.
2026-03-12 08:19:37 +00:00
momen 7aa51746c4 Merge pull request #8 from vmomenv/fix/apm-uninstall-origin-15839187749437554166
fix: pass app origin to remove-installed ipc in UninstallConfirmModal
2026-03-12 15:41:51 +08:00
vmomenv 3677019543 test: fix playwright timeout due to localhost resolution
Playwright tests were timing out on CI because the Vite dev server was
listening on `http://localhost:5173/` but `playwright.config.ts` was
configured to wait for `http://127.0.0.1:5173/`. Node 17+ resolves
`localhost` to IPv6 (`::1`), causing Playwright's strict IPv4 wait
to time out.

This commit updates `playwright.config.ts` to use `http://localhost:5173`
for both `baseURL` and the `webServer.url`.

The e2e tests were left unmodified, as previous attempts to mock them out
broke intended test behavior. This fix correctly targets only the underlying
network connection refusal between Playwright and Vite.
2026-03-12 07:32:36 +00:00
vmomenv 6cbcf6fae3 test: fix playwright e2e connection refused error
The e2e test was hardcoded to navigate to `http://127.0.0.1:3344` instead
of using the configured `baseURL` in `playwright.config.ts` which points
to the Vite dev server (`http://localhost:5173`). This caused tests to
fail with `net::ERR_CONNECTION_REFUSED`.

This commit replaces the hardcoded URL with `/` so that Playwright
correctly uses the `baseURL` setting. It also updates the title assertion
to include "星火应用商店".
2026-03-12 07:06:28 +00:00
vmomenv fa990cb974 test: fix playwright timeout due to localhost resolution
Playwright tests were timing out on CI because the Vite dev server was
listening on `http://localhost:5173/` but `playwright.config.ts` was
configured to wait for `http://127.0.0.1:5173/`. Node 17+ resolves
`localhost` to IPv6 (`::1`), causing Playwright's strict IPv4 wait
to time out.

This commit updates `playwright.config.ts` to use `http://localhost:5173`
for both `baseURL` and the `webServer.url`.
2026-03-12 07:01:40 +00:00
vmomenv 3995d2bbc0 fix: pass app origin to remove-installed ipc in UninstallConfirmModal
When triggering the uninstall process from the uninstall confirmation modal,
only the package name string was passed. This caused the backend to
default the origin to 'spark', which meant APM applications were incorrectly
attempted to be uninstalled using `aptss remove` instead of `apm remove`.

This commit changes the `remove-installed` ipc payload in
`UninstallConfirmModal.vue` to an object containing both `pkgname` and
`origin`, ensuring the backend correctly routes the uninstallation
through the APM package manager with `pkexec` when needed.
2026-03-12 06:55:48 +00:00
momen c81871f00b update:提权支持apm命令 2026-03-12 12:32:40 +08:00
momen b90b7afc28 Merge pull request #7 from vmomenv/feat/apm-install-uninstall-logic-2595854606713089615
feat: improve apm install and uninstall logic with correct privilege escalation
2026-03-12 11:26:34 +08:00
vmomenv a1c5db3a11 feat: implement apm app install and uninstall logic with pkexec elevation
- Modify `queue-install` logic to wrap `apm` commands with `superUserCmd` and `SHELL_CALLER_PATH` when origin is apm.
- Update `remove-installed` to correctly execute `apm remove -y pkgname` with required privilege elevation when origin is apm.
- Add payload parsing logic in `uninstall-installed` handler to identify origin and apply correct `apm` uninstall command dynamically.
2026-03-12 03:23:16 +00:00
momen cb8ac768a6 Merge pull request #6 from vmomenv/remove-store-mode-and-fix-arch-3296001085136830138
保留混合模式并根据架构调整网页请求路径
2026-03-12 09:41:51 +08:00
vmomenv 70cab0182d feat: 仅保留混合模式并根据架构动态构建请求路径
- 删除 AppSidebar.vue 中的 StoreModeSwitcher 引入并删除该组件。
- 强制设置当前商店模式为 'hybrid'。
- 修复了因为 `window.apm_store.arch` 包含 `-store` 或 `-apm` 后缀导致路径替换异常的问题,现在会通过动态添加后缀来构建资源请求路径,以兼容 Spark Store 和 APM Store 服务器不同的资源组织结构。
2026-03-12 01:39:00 +00:00
momen 16f7b62491 fix:修复商店无法调起apm软件的问题 2026-03-11 16:08:51 +08:00
momen 19b96c93f6 update:添加apm启动脚本 2026-03-11 15:54:02 +08:00
momen b3cef63bf5 feat:混合模式下,当点击“Spark”或“APM”的子开关时,也会刷新是否已安装逻辑 2026-03-11 14:24:14 +08:00
momen 207334608c fix:已安装的软件不显示打开软件的按钮问题 2026-03-11 14:20:23 +08:00
momen e3134afbfb feat:加入查找apm包脚本 2026-03-11 13:15:38 +08:00
momen a68638ef51 Merge pull request #4 from vmomenv/cleanup-process-install-dead-code-708801762184763180
🧹 [code health improvement] Remove dead code in processInstall.ts
2026-03-11 10:36:43 +08:00
google-labs-jules[bot] 51bf8b9304 refactor(modules): remove commented-out console.log in IPC listener
This block of code in `src/modules/processInstall.ts` was leftover debug
code and is no longer needed. Removing it improves the maintainability
and readability of the file.

Co-authored-by: vmomenv <51269338+vmomenv@users.noreply.github.com>
2026-03-11 02:34:36 +00:00
momen 5bc68f5a9a update:修复github工作流问题 2026-03-11 09:38:28 +08:00
momen a2671e2968 udpate:新增构建软件包工作流 2026-03-11 09:23:20 +08:00
momen d24a5225de update:在商店混合模式下,同包名的软件合并在同一个详情页面并加入切换开关 2026-03-11 09:18:59 +08:00
momen 66bf0124bd fix:修复混合模式下计数器问题 2026-03-11 08:51:10 +08:00
momen 257065018b fix:当用户切换商店模式(星火、APM、混合)时,目前应用会通过 window.location.reload() 重新加载整个页面。这会导致性能损耗和重复的网络请求。本计划旨在取消页面重载,并实现模式数据的缓存。 2026-03-11 08:45:28 +08:00
momen edd9368c56 update:添加apm与普通商店双支持 2026-03-11 08:36:24 +08:00
momen 8f2c758bf5 update:更新服务器接口规范 2026-03-11 08:04:43 +08:00
momen 876a3715bf Merge pull request #2 from vmomenv/feat-improve-download-status-tests-11721872646402320389
🧪 Improve removeDownloadItem tests
2026-03-11 00:13:34 +08:00
google-labs-jules[bot] 4dafedec12 test: improve removeDownloadItem tests
Expanded the test suite for `removeDownloadItem` in `src/__tests__/unit/downloadStatus.test.ts` to include:
- Removing multiple items with the same pkgname.
- Handling non-matching and non-existent pkgnames.
- Removing from an empty list.
- Ensuring exact string matching.
- Removing items from the start, middle, and end of the list.

Introduced a `createMockDownload` helper to reduce boilerplate in tests.

Co-authored-by: vmomenv <51269338+vmomenv@users.noreply.github.com>
2026-03-10 16:09:31 +00:00
momen 7dc8b7f77f Merge pull request #1 from vmomenv/security-fix-command-injection-install-manager-3820575162219224633
🔒 [security fix] Fix Command Injection in install-manager.ts
2026-03-11 00:08:50 +08:00
google-labs-jules[bot] 1270405907 🔒 fix: Command Injection in install-manager.ts and CI failures
- Set `shell: false` in `spawn` calls in `install-manager.ts` to prevent command injection.
- Updated `AGENTS.md` to use the secure `shell: false` pattern in examples.
- Removed `package-lock.json` from `.gitignore` to support reproducible builds.
- Updated GitHub Actions workflows to use `npm install` instead of `npm ci` as a robust fallback.

Co-authored-by: vmomenv <51269338+vmomenv@users.noreply.github.com>
2026-03-10 16:08:16 +00:00
google-labs-jules[bot] 828ffd86e8 🔒 fix: Command Injection vulnerability in install-manager.ts
- Changed `shell: true` to `shell: false` in `spawn` calls within `electron/main/backend/install-manager.ts`.
- Updated `AGENTS.md` documentation to reflect the security best practice.
- Verified that the fix prevents command injection using a reproduction script.

Co-authored-by: vmomenv <51269338+vmomenv@users.noreply.github.com>
2026-03-10 15:53:44 +00:00
shenmo7192 4fd280cf85 修复 check-is-installed 无法正确检查在主机是否安装的问题 2026-03-10 18:47:35 +08:00
shenmo7192 bee046dcf2 修复编译不通过的问题 2026-03-10 18:46:56 +08:00
shenmo7192 a98b3ec5b1 不再使用dpkg-query检测是否安装 2026-03-10 18:36:35 +08:00
momen 3231a3ced7 update:更新下载量统计接口信息 2026-03-10 17:34:53 +08:00
momen 3cea59f47b update:更新服务器接口信息 2026-03-10 17:34:35 +08:00
momen 94392c0f72 update:加入项目运行工作流 2026-03-10 09:23:22 +08:00
momen 762c2f550d update:更新readme 2026-03-10 09:13:58 +08:00
momen 522af7c3a3 update:主页更换图标 2026-03-10 09:03:24 +08:00
momen 105563fe1d update:忽略test-results.json 2026-03-10 00:53:44 +08:00
momen d206c79c24 fix:通过E2E测试 2026-03-10 00:52:59 +08:00
momen cef68a95d9 chore: add comprehensive documentation and testing infrastructure
## 文档(全部中文)
- AGENTS.md - 完整的 AI 编码指南(中文版)
- CONTRIBUTING.md - 贡献指南
- DEVELOPMENT.md - 开发文档
- DEPLOYMENT.md - 部署文档
- TESTING.md - 测试文档
- TROUBLESHOOTING.md - 问题排查指南
- FAQ.md - 常见问题
- WORKFLOW.md - 标准开发流程文档
## AI 工作流(9个详细工作流)
- feature-development.md - 新功能开发流程
- bug-fix.md - Bug 修复流程
- code-review.md - 代码审查流程
- testing.md - 测试编写流程
- release.md - 发布流程
- refactoring.md - 代码重构流程
- documentation.md - 文档更新流程
- performance-optimization.md - 性能优化流程
- security-audit.md - 安全审计流程
## 测试基础设施
- vitest.config.ts - Vitest 单元测试配置
- playwright.config.ts - Playwright E2E 测试配置
- src/__tests__/setup.ts - 测试环境设置
- src/__tests__/unit/downloadStatus.test.ts - 示例单元测试
- e2e/basic.spec.ts - 示例 E2E 测试
## CI/CD
- .github/workflows/test.yml - 新建测试 CI 工作流
- .github/workflows/build.yml - 更新构建工作流,添加测试步骤
## Issue 模板
- 更新 bug_report.md 为标准 Bug 报告模板
- 更新 help_wanted.md 为标准功能请求模板
## 配置更新
- package.json - 添加测试依赖和 7 个新的 npm 脚本
- .gitignore - 添加测试相关忽略项
## 新增 npm 脚本
- test - 运行单元测试
- test:watch - 监听模式
- test:coverage - 生成覆盖率报告
- test:e2e - 运行 E2E 测试
- test:e2e:ui - E2E UI 模式
- test:e2e:debug - E2E 调试模式
- test:all - 运行所有测试
## 新增测试依赖
- @playwright/test ^1.40.0
- @testing-library/jest-dom ^6.1.5
- @testing-library/vue ^8.0.1
- @vitest/coverage-v8 ^1.0.0
- @vue/test-utils ^2.4.3
- jsdom ^23.0.1
- vitest ^1.0.0
2026-03-10 00:42:56 +08:00
momen 0035b3000d feat:修改1.md改为代码审查.md 2026-03-09 23:58:05 +08:00
momen 2df695fca1 feat:添加代码审查工作流 2026-03-09 23:57:29 +08:00
momen 21ea334e79 feat:修复基础格式问题 2026-03-09 23:56:44 +08:00
shenmo 1e2047e7f1 Merge pull request #6 from vmomenv/momen-dev
Momen dev
2026-03-09 11:32:40 +08:00
momen a9a6b6bdc6 fix:首页推荐软件安装失败问题 2026-02-28 02:28:50 +08:00
momen 749cf3d3bf feat:引入懒加载,防止弱网情况下无法正常加载应用图标或详情页图片 2026-02-27 23:25:38 +08:00
momen 88670be15e feat:针对弱网环境,侧边栏添加并行加载,重试机制,初始化优化 2026-02-27 23:18:06 +08:00
momen 6ea628d869 feat: 修改应用信息界面,对于已安装应用,安装按钮变为打开按钮,并添加卸载按钮 2026-02-27 23:03:10 +08:00
shenmo7192 3a9c9dda22 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-02-25 20:47:13 +08:00
shenmo7192 21b069d7ef 添加主页功能,支持加载和展示首页数据,包括链接和推荐应用列表 2026-02-25 20:46:28 +08:00
shenmo 95e22894a7 修复:安装状态判断错误的问题 2026-02-19 21:07:00 +08:00
shenmo a37ee1cd31 sync: https://gitee.com/spark-store-project/spark-store/commit/fda3f70d5dcf2cc50e2bf42f1430d7c218d303d9 2026-02-19 20:40:02 +08:00
shenmo7192 b72f5f8da6 完成 -apm 的全部更改,实现 spk://search,移除 spk://store 2026-02-19 19:56:32 +08:00
shenmo7192 3165304016 修改应用名称 2026-02-19 19:27:19 +08:00
shenmo7192 6df612889b bump-version to 4.9.9 2026-02-19 19:23:38 +08:00
shenmo7192 1cf729e7fd 优化启动速度 2026-02-19 19:22:18 +08:00
shenmo7192 058b128eec 添加 policy 2026-02-19 19:10:47 +08:00
shenmo7192 69d9c23cff 完成aptss对接 2026-02-19 18:35:41 +08:00
shenmo7192 44a55249db 更换安装指令为 aptss 2026-02-19 18:01:16 +08:00
shenmo7192 d16dec09a6 修改上游链接 2026-02-19 17:56:30 +08:00
Elysia c27c1f1697 feat: add sidebar toggle functionality
Signed-off-by: Elysia <a.elysia@proton.me>
2026-02-17 23:23:20 +08:00
Elysia 7b3bd110a9 docs: update changelog for v1.1.1 release
Signed-off-by: Elysia <a.elysia@proton.me>
2026-02-17 22:23:59 +08:00
Elysia 4a0467536c build: bump version to 1.1.1
Signed-off-by: Elysia <a.elysia@proton.me>
2026-02-17 22:22:52 +08:00
Elysia d45d5082f4 fix(main): use app.getVersion() for packaged app
Signed-off-by: Elysia <a.elysia@proton.me>
2026-02-17 22:08:51 +08:00
Yinan Qin d2703a1c86 chore: update license badge to MulanPSL 2.0
[no ci]
2026-02-16 13:16:16 +08:00
Yinan Qin c080bcfb27 docs: add DeepWiki badge to README
Added DeepWiki badge to README.
2026-02-15 00:55:16 +08:00
Elysia 00ea841241 docs(README): add a screenshot 2026-02-15 00:49:49 +08:00
Yinan Qin bc673c0998 chore: update Dependabot schedule for npm and GitHub Actions
Changed npm update schedule from monthly to weekly and added GitHub Actions updates with a weekly schedule.
2026-02-15 00:36:07 +08:00
Elysia 6a39a7448b restore README.md :( 2026-02-15 00:30:47 +08:00
Elysia a1cd7ab38f docs: update changelog for version 1.1.0 2026-02-15 00:29:05 +08:00
Elysia f2c64c111b build: bump version to 1.1.0 2026-02-15 00:27:54 +08:00
Elysia 12b604dbad docs: update changelog generation command 2026-02-15 00:25:39 +08:00
Elysia dccfa6029a build: add --skip-unstable flag to changelog command 2026-02-15 00:19:29 +08:00
Elysia 0aaaabe31b chore: add changelog generation script 2026-02-15 00:16:45 +08:00
Elysia 7aae00e272 ops(ci): add release job and update node version 2026-02-15 00:09:29 +08:00
Elysia ed92145f91 fix(app): floor download progress percentage 2026-02-14 23:56:49 +08:00
Elysia 7a97333bf7 refactor(download): update download management comments and behavior 2026-02-14 23:33:36 +08:00
Elysia 524627c585 build: bump version to 1.1.0-beta.1 2026-02-14 23:23:39 +08:00
Elysia a3f18bb593 feat(app): add download count display 2026-02-14 23:22:41 +08:00
Elysia 5ac9376200 feat: support download statistics
close #15
2026-02-14 23:11:43 +08:00
Elysia c4ffc880e4 chore(main): clean up temp dir on quit 2026-02-14 19:06:58 +08:00
Elysia 9f50e25dc0 feat(app): add cache buster for API requests
close #16
2026-02-14 18:58:29 +08:00
Elysia 37673ca3e1 build(deb, rpm): add aria2 dependency 2026-02-14 18:40:19 +08:00
Elysia 832839c14f build: bump version to 1.1.0-beta.0 2026-02-14 00:26:26 +08:00
Elysia 2eb56079cb docs: fix typo in directory path and update date 2026-02-14 00:17:46 +08:00
Elysia 74c4eb4fbc feat(install): add metalink download support and progress tracking
close #12
2026-02-14 00:16:18 +08:00
Elysia 7aeb3d5dd4 feat(theme): add system theme support
close #13
2026-02-13 14:49:41 +08:00
Elysia 1d808b035a refactor(app): change to sequential loading and increase timeout
Co-authored-by: shenmo <jifengshenmo@outlook.com>
Signed-off-by: elysia-best <a.elysia@proton.me>
2026-02-13 14:11:13 +08:00
Elysia 10808c8f3b feat: 更新类型系统指南,添加代码检查和格式化要求 2026-02-12 20:14:12 +08:00
Elysia d5266c6af8 feat: 更新搜索逻辑
现在更换app类别时将默认清空搜索。
2026-02-12 20:11:54 +08:00
Elysia c3ae477497 feat(docs): 添加 AI 编码指导文档以概述项目架构和核心概念 2026-02-12 19:51:52 +08:00
Elysia 9a2d3a8ac1 refactor: fix typo in module path 2026-02-12 19:21:17 +08:00
Elysia 6622e70033 refactor: improve code formatting and consistency across components
- Updated button and span elements in ThemeToggle.vue and TopActions.vue for better readability.
- Enhanced UninstallConfirmModal.vue and UpdateAppsModal.vue with consistent indentation and spacing.
- Refactored downloadStatus.ts and storeConfig.ts for improved code clarity.
- Standardized string quotes and spacing in typedefinition.ts and processInstall.ts.
- Ensured consistent use of arrow functions and improved variable declarations throughout the codebase.
2026-02-12 18:32:41 +08:00
Elysia e11740ad4c feat: 添加 ESLint 配置并优化代码风格,移除未使用的功能 2026-02-12 18:31:09 +08:00
Delta1035 b43c6117ec fix: 修复应用还没有安装完,按钮就重新变成可安装状态 (#11)
fix:先用比较简单的方案解决安装之后卸载了还是显示已安装的问题

fix: 在安装成功的ipc信息之后再删除安装队列的任务

删除pnpm workspace
2026-02-04 13:06:01 +08:00
Yinan Qin 53eb307f5c Fix formatting in LICENSE.md and update copyright
Correct formatting of section headings and add copyright notice.
2026-02-04 10:46:09 +08:00
Yinan Qin 86b98ed49f chore: Change license to MulanPSL-2.0 2026-02-04 10:43:02 +08:00
dependabot[bot] 8c37f67379 build(deps-dev): bump @vitejs/plugin-vue from 5.2.4 to 6.0.3 (#9)
Bumps [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/HEAD/packages/plugin-vue) from 5.2.4 to 6.0.3.
- [Release notes](https://github.com/vitejs/vite-plugin-vue/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-vue/blob/main/packages/plugin-vue/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-vue/commits/plugin-vue@6.0.3/packages/plugin-vue)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-vue"
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Reviewed-by: Yinan Qin <a.elysia@proton.me>
2026-02-03 11:09:10 +08:00
Copilot 73de0a171f build: Remove unused electron-app-universal-protocol-client dependency (#8)
* Initial plan

* Remove unused electron-app-universal-protocol-client dependency

Co-authored-by: elysia-best <39023210+elysia-best@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: elysia-best <39023210+elysia-best@users.noreply.github.com>
2026-02-01 12:04:56 +08:00
Yinan Qin 35c192e9ee chore: 更新.desktop 文件中文和英文名称
参考 https://gitee.com/amber-ce/amber-pm-store/blob/master/src/usr/share/applications/amber-pm-store.desktop
2026-02-01 11:57:52 +08:00
Yinan Qin 98cc18dc96 Delete .github/workflows/ci.yml 2026-01-31 23:29:26 +08:00
Yinan Qin 2dd9d1f27a docs: Enhance SECURITY.md with bilingual support and details
Updated the security policy to include both English and Chinese versions, detailing supported versions and vulnerability reporting guidelines.
2026-01-31 23:19:54 +08:00
Elysia c8709711df bump: v1.0.4 2026-01-31 21:45:48 +08:00
Elysia 95d358fb6e chore: 更新版本号至 1.0.4-beta.1,并为 host-spawn 添加可执行权限 2026-01-31 21:36:13 +08:00
Elysia 850b8dcd1f feat: 添加 host-spawn 下载步骤并更新应用启动命令 2026-01-31 21:27:31 +08:00
Elysia 2f7af3ca8f fix: 修复应用启动命令,移除交互式模式 2026-01-31 20:53:48 +08:00
Elysia eb386ec23e chore: 更新版本号至 1.0.4-beta.0,移除重复任务检查逻辑 2026-01-31 20:21:02 +08:00
Elysia 0d1d4e5679 feat: 添加重复任务检查,避免重复下载任务 2026-01-31 20:19:52 +08:00
Elysia 92d1573cf0 feat: 现在仅在有任务时才会到托盘 2026-01-31 20:13:05 +08:00
Elysia eeefe5295b feat: enhance install manager to prevent duplicate package installations and improve app launching command 2026-01-31 20:08:35 +08:00
Elysia a4049ba30b chore: update version to 1.0.3 and remove release event from build workflow 2026-01-31 18:33:34 +08:00
Elysia 641589f875 feat: update application name and paths to reflect new branding 2026-01-31 18:32:52 +08:00
Elysia 6154d75fa6 feat: add app launching functionality and update related components 2026-01-31 18:21:16 +08:00
Elysia 39e40ff946 feat: enhance application type definitions and improve app management logic 2026-01-31 17:48:06 +08:00
Elysia 3221cb6d5e refactor: standardize app property names and improve TypeScript definitions
- Updated property names in AppCard.vue, AppDetailModal.vue, AppGrid.vue, and other components to use camelCase for consistency.
- Enhanced TypeScript definitions for props and emits in various components to improve type safety.
- Refactored download status handling in processInstall.ts to align with updated App interface.
- Improved error handling and type definitions in DownloadDetail.vue and related components.
- Added optional properties and refined existing interfaces in typedefinition.ts for better clarity and usability.
2026-01-31 17:16:02 +08:00
Elysia f89b9ebfd9 feat: update application icons and implement tray functionality 2026-01-31 16:37:51 +08:00
Elysia 0ed7f64a21 fix: deep link handling at electron startup 2026-01-31 16:07:15 +08:00
Elysia 3fe37f2773 build: add architecture to artifact name 2026-01-31 10:47:15 +08:00
Elysia 354eea3626 fix(build): add bash shell to build release files 2026-01-31 10:46:37 +08:00
Elysia 3a4a116a7c refactor(ci): replace inline conditionals with if-else in build.yml 2026-01-31 10:42:54 +08:00
Elysia b185b40161 build: add arm64 architecture support 2026-01-31 10:40:11 +08:00
Elysia 5b09dfb3d9 feat(preload): expose architecture detection to renderer process
add multiarch support
2026-01-31 10:26:52 +08:00
Elysia 698c0b5420 docs: add UninstallConfirmModal.vue to README structure 2026-01-31 09:58:23 +08:00
Elysia 61790a8588 feat: 更新模态框样式,添加最大高度限制 2026-01-31 09:55:25 +08:00
Elysia 327ee5400e feat: 更新版本号至 1.0.3-beta.0 2026-01-31 01:08:09 +08:00
Elysia 588eaf9746 feat: 更新本地应用列表,区分依赖和用户安装的包 2026-01-31 01:07:05 +08:00
Elysia 4ce097bae0 feat: 更新安装按钮状态反馈,添加安装队列提示 2026-01-31 00:59:23 +08:00
Elysia 97997182bc fix: 修复卸载请求中的应用名称查找逻辑
更新下载详情组件样式以支持自定义滚动条
2026-01-31 00:53:40 +08:00
Elysia b4ef653299 fix: 修复确认卸载界面应用名称显示 2026-01-31 00:17:07 +08:00
Elysia b9325db8b0 feat: 添加卸载确认模态框,支持卸载进度显示 2026-01-31 00:01:32 +08:00
Elysia 9d92bac6cc refactor: 更新应用详情模态框样式,添加自定义滚动条
更新README文档,添加安装/卸载时UI提示的待办事项
2026-01-30 23:48:47 +08:00
Elysia eaa28686a3 perf: 移除模态框背景模糊效果
动态模糊背景太吃资源了,遂移除
2026-01-30 23:04:53 +08:00
Elysia 150c57038d refactor: 更新构建配置,添加对发布事件的支持;更新依赖项以确保兼容性 2026-01-30 22:27:48 +08:00
Elysia a517d03da8 refactor: 更新README文档,修复URL Scheme协议支持的状态;修改深度链接处理逻辑以优化用户体验 2026-01-30 22:16:01 +08:00
Elysia de1fe65045 refactor: 添加深度链接处理程序以支持更新、安装和已安装事件 2026-01-30 21:54:51 +08:00
Elysia fff4a4bd22 refactor: 更新README文档,添加动画性能问题的待办事项;修改安装管理器以使用完整路径查找pkexec命令;删除未使用的下载管理模拟方法 2026-01-30 21:39:50 +08:00
Elysia 681780f712 refactor: 修改开发工具打开模式为分离,优化调试体验;更新ThemeToggle组件样式;删除不再使用的IPC和Node示例代码 2026-01-30 21:31:13 +08:00
Elysia 569cc87994 refactor: 优化AppDetailModal组件的布局和样式,增强可用性 2026-01-30 21:22:01 +08:00
Elysia 2625d24668 refactor: enhance UI components with improved styling and transitions
- Updated DownloadQueue.vue to use Tailwind CSS for styling and added transition effects for better user experience.
- Refactored InstalledAppsModal.vue to improve layout and responsiveness, incorporating Tailwind CSS styles.
- Enhanced ScreenPreview.vue with transitions and improved button styles for navigation.
- Revamped ThemeToggle.vue to provide a more modern toggle button design with accessibility features.
- Updated TopActions.vue to use Tailwind CSS for buttons and layout adjustments.
- Refined UpdateAppsModal.vue with a cleaner layout, improved button styles, and better handling of loading states.
2026-01-30 21:02:31 +08:00
Elysia 0002c2f9e1 chore: prepare to change to tailwindcss 2026-01-30 19:53:46 +08:00
dependabot[bot] 5f89436106 Bump vite-plugin-electron from 0.28.8 to 0.29.0 (#1)
Bumps [vite-plugin-electron](https://github.com/electron-vite/vite-plugin-electron) from 0.28.8 to 0.29.0.
- [Release notes](https://github.com/electron-vite/vite-plugin-electron/releases)
- [Changelog](https://github.com/electron-vite/vite-plugin-electron/blob/main/CHANGELOG.md)
- [Commits](https://github.com/electron-vite/vite-plugin-electron/compare/v0.28.8...v0.29.0)

---
updated-dependencies:
- dependency-name: vite-plugin-electron
  dependency-version: 0.29.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 09:07:49 +08:00
dependabot[bot] d61c7cc5e5 Bump vue-tsc from 2.2.12 to 3.2.2 (#2)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.2.12 to 3.2.2.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v3.2.2/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-version: 3.2.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-28 23:46:54 +08:00
Elysia 51ee4019d9 fix: 更新vite版本至6.4.1 2026-01-28 23:44:54 +08:00
Yinan Qin 7162f8dd56 Merge pull request #4 from elysia-best/dependabot/npm_and_yarn/electron-40.0.0
Bump electron from 29.4.6 to 40.0.0
2026-01-28 23:25:31 +08:00
dependabot[bot] 75f67e4236 Bump electron from 29.4.6 to 40.0.0
Bumps [electron](https://github.com/electron/electron) from 29.4.6 to 40.0.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v29.4.6...v40.0.0)

---
updated-dependencies:
- dependency-name: electron
  dependency-version: 40.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-28 15:23:11 +00:00
Elysia c2f66321a8 chore: add more todo 2026-01-28 23:22:32 +08:00
Elysia e62f4c0336 bump: 更新版本号至1.0.1 2026-01-28 23:20:32 +08:00
Elysia 402ba1fb00 feat: 更新TODO列表,添加应用更新和显示已安装应用功能 2026-01-28 23:20:13 +08:00
Elysia 0c2ec65dca refactor(install-manager): 更新可升级软件包列表命令路径 2026-01-28 23:19:15 +08:00
Elysia f7eedcd4fd fix: 将依赖项'apm'更改为'amber-package-manager' 2026-01-28 22:50:57 +08:00
Elysia f15fb28d80 feat: 统一安装和卸载脚本以支持PolicyKit权限配置
rpm应该能通用这两个脚本
2026-01-28 22:41:00 +08:00
Elysia d529dd6e5e refactor(install-manager): update apm execution path to shell-caller.sh 2026-01-28 22:26:37 +08:00
Elysia 071aa36fb4 feat: 添加PolicyKit权限配置和安装/卸载脚本 2026-01-28 22:10:03 +08:00
Elysia 185b4984c6 feat: 更新窗口标题和尺寸,优化按钮样式 2026-01-28 20:59:25 +08:00
Elysia 38a4d4512f feat: 添加electron-builder.yml配置文件并更新构建脚本 2026-01-28 20:33:12 +08:00
Elysia 9ee8339577 fix: 更新上传工件路径以支持不同包类型 2026-01-28 19:54:55 +08:00
Elysia 847bcc7885 feat: 添加deb和rpm包的依赖项配置 2026-01-28 19:54:17 +08:00
Elysia bc2f79114c fix: 更新构建依赖,添加构建工具支持 2026-01-28 19:25:50 +08:00
Elysia f8f163e3b8 fix: 更新构建依赖,添加python3支持 2026-01-28 19:23:05 +08:00
Elysia 1c791cd3c8 fix: 更新构建依赖,移除不必要的包并优化安装命令 2026-01-28 19:21:16 +08:00
Elysia 640e0bd69d feat: 添加对deb和rpm包的构建支持,更新构建依赖和版本信息 2026-01-28 19:18:45 +08:00
Elysia 4b49424105 fix: 更新应用图标格式为ICNS,优化安装管理器命令执行 2026-01-28 18:38:52 +08:00
Elysia a3d50e026a fix: 更新应用ID和版本信息,修复许可证类型 2026-01-28 18:24:02 +08:00
Elysia ea0261a192 feat: 添加已安装应用和可更新应用的管理功能,支持卸载和升级操作 2026-01-28 18:14:04 +08:00
Elysia ac0dc225bc feat(install): add app uninstall functionality 2026-01-26 00:57:15 +08:00
Elysia d51756c124 docs: update build badge and fix indentation 2026-01-26 00:21:19 +08:00
Elysia bf93059da1 feat(install): 实现安装管理器,支持安装、检查已安装状态和初步卸载功能 2026-01-26 00:12:01 +08:00
Elysia bdf51a1037 feat(download): 支持重试下载功能并更新相关逻辑 2026-01-25 23:29:58 +08:00
Elysia 37c35c4519 doc(README): 添加TODO 2026-01-25 22:40:06 +08:00
Elysia 50fb1a0065 feat(install): added basis install process
Now it is able to install apps from the render process and properly display logs on the app detial page.
2026-01-25 22:30:39 +08:00
Elysia 22435a5e1b docs(deeplink): add file header documentation 2026-01-18 00:46:57 +08:00
Elysia c7b3257a2c feat(deeplink): implement custom deep link handling and remove electron-app-universal-protocol-client 2026-01-18 00:45:25 +08:00
Elysia a476db84ee build: update dependencies and build configuration 2026-01-18 00:21:44 +08:00
Elysia c342be45c2 build: 修改依赖安装步骤,移除 electron-app-universal-protocol-client 直接安装,改为通过 devDependencies 安装 2026-01-18 00:18:00 +08:00
Elysia 5fd1b75309 build(workflows): update npm install build-from-source flag 2026-01-18 00:16:09 +08:00
Elysia f75b1681a2 build: 更新 electron-app-universal-protocol-client 到 v2.1.1,并修改安装依赖的构建选项 2026-01-18 00:12:32 +08:00
Elysia 141315f362 build: update electron-app-universal-protocol-client to v2.1.0 2026-01-18 00:09:54 +08:00
Elysia c8965297f2 build: 更新 GitHub Actions 工作流以忽略不必要的文件并优化依赖安装 2026-01-18 00:05:59 +08:00
Elysia 184072d5d2 build(workflow): update install dependencies step 2026-01-17 23:55:17 +08:00
Elysia 8cddebf39c build: move electron-app-universal-protocol-client to devDependencies 2026-01-17 23:48:26 +08:00
Elysia 0faf741d0b build: update Node.js version to 20.x 2026-01-17 23:44:18 +08:00
Elysia d8dee6e26f ci: 更新 GitHub Actions 工作流,升级依赖版本并简化操作系统矩阵 2026-01-17 23:40:54 +08:00
Elysia 4f77ab4bc3 docs: 更新许可证徽章为 MIT 2026-01-17 23:37:35 +08:00
Elysia 428512eae8 docs: 更新 README 中的 APM Logo 显示方式 2026-01-17 23:36:53 +08:00
Elysia d1ac6d616b docs: update logo path in README 2026-01-17 23:35:58 +08:00
Elysia 9b17c57c5c feat: overhaul application to APM 应用商店 with enhanced download management
- Removed CHANGELOG.md and electron-vite-vue.gif files.
- Updated LICENSE to reflect new copyright holder.
- Transformed README.md to reflect new project identity and features.
- Introduced DownloadQueue and DownloadDetail components for managing downloads.
- Implemented download simulation and management logic in App.vue.
- Added URL scheme handling in Electron main process.
- Integrated electron-app-universal-protocol-client for protocol handling.
- Updated package.json to include new dependencies.
2026-01-17 23:17:14 +08:00
Elysia 4dd3bd321c 更新应用程序配置,修改图标和标题,优化截图加载逻辑,移除懒加载初始化 2026-01-17 21:47:39 +08:00
Elysia 74615a5ce9 更新 AppHeader 和 AppGrid 组件以使用过滤后的应用列表 2026-01-17 21:09:06 +08:00
Elysia 0d16434374 添加环境配置文件,更新 Vite 配置以支持本地代理,优化 AppCard 组件的懒加载逻辑 2026-01-17 21:00:21 +08:00
Elysia a5b3d1278c add store 2026-01-17 20:07:27 +08:00
Yinan Qin 2250f89266 Initial commit 2026-01-17 00:15:37 +08:00
2528 changed files with 447744 additions and 13236 deletions
+139
View File
@@ -0,0 +1,139 @@
---
description: Bug 修复流程
---
## 工作流说明
此工作流指导如何修复 Bug。
## 步骤
### 1. 复现 Bug
- 根据 Issue 描述复现问题
- 记录详细的复现步骤
- 收集相关日志和错误信息
- 确认环境信息
### 2. 分析问题
- 查看相关代码
- 使用调试器定位问题
- 检查日志输出
- 识别根本原因
### 3. 创建修复分支
```bash
git checkout -b fix/your-bug-fix
```
### 4. 编写回归测试
先编写测试来复现 Bug
```typescript
// src/__tests__/unit/bugFix.test.ts
import { describe, it, expect } from "vitest";
import { buggyFunction } from "@/modules/example";
describe("buggyFunction", () => {
it("should not crash with null input", () => {
expect(() => buggyFunction(null)).not.toThrow();
});
});
```
### 5. 修复代码
- 最小化修改
- 保持代码可读性
- 添加必要的注释
- 更新相关类型定义
### 6. 运行测试
```bash
# 确保新测试通过
npm run test
# 运行所有测试
npm run test:all
# 代码检查
npm run lint
npm run format
```
### 7. 本地验证
- 验证 Bug 已修复
- 测试相关功能
- 检查是否引入新问题
- 测试边界情况
### 8. 更新文档
- 更新 CHANGELOG.md(如果需要)
- 更新相关文档(如需要)
### 9. 提交代码
```bash
git add .
git commit -m "fix(scope): describe the bug fix" -s
git push origin fix/your-bug-fix
```
### 10. 创建 Pull Request
- 引用相关 Issue`Fixes #123`
- 描述修复方法
- 说明复现步骤
- 添加测试说明
### 11. 代码审查
- 响应审查意见
- 进行必要的修改
- 确保所有 CI 检查通过
### 12. 合并
- 等待审查批准
- Squash 合并到 main 分支
- 删除修复分支
## 注意事项
- ⚠️ 修复前先理解问题根源
- ⚠️ 最小化修改范围
- ⚠️ 添加回归测试防止复发
- ⚠️ 考虑向后兼容性
- ⚠️ 测试所有受影响的功能
## 常见 Bug 类型
### IPC 通信问题
- 检查事件名称是否匹配
- 检查数据格式是否正确
- 检查异步处理
### 状态管理问题
- 检查响应式依赖
- 检查状态更新时机
- 检查内存泄漏
### 类型错误
- 检查类型定义
- 检查类型断言
- 检查可选值处理
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [TESTING.md](../../TESTING.md) - 测试文档
- [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md) - 问题排查
+47
View File
@@ -0,0 +1,47 @@
---
description: 为 Spark Store 构建DEB软件包
---
本工作流将指导你如何构建适用于 Linux 的 Spark Store 软件包。
### 1. 安装依赖
确保你已经安装了所有的项目依赖。如果你还没有安装,可以使用 `/run-project` 工作流。
// turbo
```bash
npm install
```
### 2. 构建生产版本
你可以选择构建所有支持的格式,或者仅构建特定的格式(deb 或 rpm)。
#### 构建所有格式 (deb, rpm, AppImage)
// turbo
```bash
npm run build
```
#### 仅构建 deb 包
// turbo
```bash
npm run build:deb
```
### 3. 查看构建产物
构建完成后的安装包将存放在项目根目录下的 `release` 目录中。
```bash
ls -l release/$(node -p "require('./package.json').version")
```
### 4. 常见问题排查
如果构建失败,请检查以下几点:
- 确保 Node.js 版本符合要求 (>= 20.x)。
- 确保系统已安装必要的编译工具。
- 检查 `electron-builder.yml` 中的配置是否正确。
+245
View File
@@ -0,0 +1,245 @@
---
description: 代码审查流程
---
## 工作流说明
此工作流指导如何进行代码审查。
## 审查清单
### 代码质量
- [ ] 代码遵循项目规范
- [ ] TypeScript 类型正确
- [ ] 没有 `any` 类型(除非必要)
- [ ] ESLint 和 Prettier 通过
- [ ] 代码可读性良好
### 功能实现
- [ ] 实现符合需求
- [ ] 边界情况处理
- [ ] 错误处理完善
- [ ] 没有引入新 Bug
### 测试
- [ ] 包含足够的测试
- [ ] 测试覆盖率合理
- [ ] 所有测试通过
- [ ] E2E 测试(如需要)
### 文档
- [ ] 更新了相关文档
- [ ] 代码注释充分
- [ ] API 文档(如需要)
- [ ] CHANGELOG.md(如需要)
### 安全性
- [ ] 没有安全漏洞
- [ ] 输入验证完善
- [ ] 权限检查正确
- [ ] 敏感信息保护
### 性能
- [ ] 没有明显的性能问题
- [ ] 内存使用合理
- [ ] 没有不必要的渲染
- [ ] 资源加载优化
## 审查流程
### 1. 理解变更
- 阅读 PR 描述
- 查看 Issue 链接
- 理解变更目的
- 检查变更范围
### 2. 代码审查
**主进程代码:**
```bash
# 检查类型安全
npx tsc --noEmit
# 检查代码质量
npm run lint
```
**渲染进程代码:**
- 组件结构
- 状态管理
- 事件处理
- 样式实现
### 3. 测试验证
```bash
# 运行单元测试
npm run test
# 运行 E2E 测试
npm run test:e2e
# 检查覆盖率
npm run test:coverage
```
### 4. 提供反馈
**正面反馈:**
- 好的实现
- 优秀的代码
- 有价值的贡献
**建设性反馈:**
- 指出问题
- 提出建议
- 解释原因
**反馈格式:**
````markdown
### 问题
**位置:** `src/components/AppCard.vue:45`
**描述:** 这里缺少错误处理,可能导致应用崩溃。
**建议:**
```typescript
try {
await installPackage();
} catch (error) {
console.error("Install failed:", error);
showError(error.message);
}
```
````
````
### 5. 批准或要求修改
**批准条件:**
- 所有审查项目通过
- 所有测试通过
- CI 检查通过
- 没有阻塞问题
**要求修改:**
- 指出必须修复的问题
- 给出明确的修改建议
- 等待作者响应
## 审查原则
### 及时性
- 尽快响应 PR
- 设定响应时间预期
- 优先处理紧急 PR
### 建设性
- 提供具体的反馈
- 给出改进建议
- 解释审查理由
### 尊重
- 尊重作者的贡献
- 使用礼貌的语言
- 认可好的实现
### 一致性
- 遵循项目规范
- 保持审查标准一致
- 参考之前类似 PR
## 常见问题
### 类型安全问题
**问题:** 使用了 `any` 类型
**建议:**
```typescript
// ❌ 避免
const data: any = response;
// ✅ 推荐
interface ResponseData {
id: string;
name: string;
}
const data: ResponseData = response;
````
### 代码重复
**问题:** 代码重复
**建议:**
```typescript
// 提取公共函数
function formatSize(size: number): string {
return size > 1024 ? `${size / 1024} MB` : `${size} KB`;
}
```
### 错误处理
**问题:** 缺少错误处理
**建议:**
```typescript
async function loadApps() {
try {
const response = await axios.get("/api/apps");
return response.data;
} catch (error) {
logger.error({ err: error }, "Failed to load apps");
throw error;
}
}
```
## 审查后操作
### 批准
- 点击 "Approve review"
- 添加评论(可选)
- 等待合并
### 要求修改
- 选择 "Request changes"
- 提供详细反馈
- 等待作者更新
### 评论
- 选择 "Comment"
- 提供建议或问题
- 不阻止合并
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [AGENTS.md](../../AGENTS.md) - AI 编码指南
+264
View File
@@ -0,0 +1,264 @@
---
description: 文档更新流程
---
## 工作流说明
此工作流指导如何更新项目文档。
## 步骤
### 1. 确定需要更新的文档
根据变更内容确定需要更新的文档:
- README.md - 主要说明
- DEVELOPMENT.md - 开发指南
- CONTRIBUTING.md - 贡献指南
- TESTING.md - 测试文档
- DEPLOYMENT.md - 部署文档
- TROUBLESHOOTING.md - 问题排查
- FAQ.md - 常见问题
- AGENTS.md - AI 编码指南
- CHANGELOG.md - 变更日志
### 2. 创建文档分支
```bash
git checkout -b docs/update-documentation
```
### 3. 更新文档
#### README.md
添加新功能说明:
```markdown
## 新功能
### 应用更新
现在支持一键更新所有可更新的应用。
### 下载管理
改进了下载队列管理,支持暂停和继续。
```
#### DEVELOPMENT.md
添加开发指南:
```markdown
## 新功能开发
### 添加新功能步骤
1. 理解需求
2. 设计方案
3. 实现功能
4. 编写测试
5. 提交 PR
```
#### CONTRIBUTING.md
更新贡献指南:
```markdown
### 新功能贡献
- 遵循现有代码风格
- 编写充分的测试
- 更新相关文档
```
#### TESTING.md
添加测试示例:
```typescript
describe("New Feature", () => {
it("should work correctly", () => {
// 测试代码
});
});
```
#### CHANGELOG.md
添加变更记录:
```markdown
## [4.10.0](https://github.com/elysia-best/apm-app-store/compare/v4.9.9...v4.10.0) (2026-03-10)
### Features
- feat(download): add pause and resume for downloads
- feat(update): add batch update for apps
### Bug Fixes
- fix(ui): correct dark mode toggle persistence
```
### 4. 检查文档质量
- [ ] 语法正确
- [ ] 格式统一
- [ ] 链接有效
- [ ] 内容准确
- [ ] 示例可运行
### 5. 运行文档测试
```bash
# 如果有文档测试
npm run test:docs
# 检查链接
npm run check-links
```
### 6. 本地预览
使用 Markdown 预览工具查看效果。
### 7. 提交文档
```bash
git add .
git commit -m "docs: update documentation for new features" -s
git push origin docs/update-documentation
```
### 8. 创建 Pull Request
- 说明更新的内容
- 提供预览截图(如需要)
- 引用相关 Issue
### 9. 代码审查
- 响应审查意见
- 确保文档质量
- 合并到 main 分支
## 文档编写规范
### 格式规范
- 使用 Markdown
- 保持一致的标题层级
- 使用代码块展示示例
- 使用表格对比选项
### 语言规范
- 使用简洁清晰的语言
- 避免技术术语(或解释)
- 保持中英文术语一致
- 使用被动语态
### 示例规范
```typescript
// 好的示例
import { ref } from "vue";
const count = ref(0);
function increment() {
count.value++;
}
```
### 链接规范
```markdown
- 内部链接: [文档名](./document.md)
- 外部链接: [Vue 文档](https://vuejs.org/)
- 锚点链接: [章节](#section-name)
```
## 文档模板
### 新功能文档
````markdown
## 功能名称
### 描述
简要描述功能
### 使用方法
```typescript
// 示例代码
```
````
### 配置选项
| 选项 | 类型 | 默认值 | 说明 |
| ------ | ------ | --------- | -------- |
| option | string | 'default' | 选项说明 |
### 注意事项
- 注意事项 1
- 注意事项 2
````
### API 文档
```markdown
## API 函数名
### 签名
```typescript
function functionName(param1: Type1, param2: Type2): ReturnType
````
### 参数
| 参数 | 类型 | 必填 | 说明 |
| ------ | ----- | ---- | -------- |
| param1 | Type1 | 是 | 参数说明 |
| param2 | Type2 | 否 | 参数说明 |
### 返回值
| 类型 | 说明 |
| ---------- | ---------- |
| ReturnType | 返回值说明 |
### 示例
```typescript
const result = functionName(arg1, arg2);
```
### 错误
抛出 `Error` 异常的情况说明。
```
## 注意事项
- ⚠️ 保持文档与代码同步
- ⚠️ 更新示例代码
- ⚠️ 检查链接有效性
- ⚠️ 使用统一的格式
- ⚠️ 提供清晰的说明
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [AGENTS.md](../../AGENTS.md) - AI 编码指南
```
+135
View File
@@ -0,0 +1,135 @@
---
description: 新功能开发流程
---
## 工作流说明
此工作流指导如何开发新功能。
## 步骤
### 1. 理解需求
- 阅读 Issue 描述
- 确认功能范围
- 识别依赖关系
- 设计 API 和数据结构
### 2. 设计方案
- 设计 UI/UX(如需要)
- 设计数据流
- 确定 IPC 通信(如需要)
- 编写技术方案文档(可选)
### 3. 创建功能分支
```bash
git checkout -b feature/your-feature-name
```
### 4. 更新类型定义
`src/global/typedefinition.ts` 中添加新的类型定义:
```typescript
export interface NewFeatureData {
id: string;
name: string;
// ...其他字段
}
```
### 5. 编写测试
先编写测试,遵循 TDD 原则:
```typescript
// src/__tests__/unit/newFeature.test.ts
import { describe, it, expect } from "vitest";
import { newFunction } from "@/modules/newFeature";
describe("newFunction", () => {
it("should work correctly", () => {
const result = newFunction(input);
expect(result).toBe(expected);
});
});
```
### 6. 实现功能
按照以下顺序实现:
- 后端逻辑(Electron 主进程)
- 前端逻辑(Vue 组件)
- IPC 通信(如需要)
- 样式和布局
### 7. 运行测试
```bash
# 单元测试
npm run test
# E2E 测试
npm run test:e2e
# 代码检查
npm run lint
npm run format
```
### 8. 本地测试
- 测试所有功能场景
- 测试边界情况
- 测试错误处理
- 检查性能影响
### 9. 更新文档
- 更新 API 文档(如需要)
- 更新用户文档(如需要)
- 更新 CHANGELOG.md
### 10. 提交代码
```bash
git add .
git commit -m "feat(scope): add new feature" -s
git push origin feature/your-feature-name
```
### 11. 创建 Pull Request
- 使用 PR 模板
- 引用相关 Issue
- 添加测试说明
- 添加截图/录屏(UI 变更)
### 12. 代码审查
- 响应审查意见
- 进行必要的修改
- 确保所有 CI 检查通过
### 13. 合并
- 等待审查批准
- Squash 合并到 main 分支
- 删除功能分支
## 注意事项
- ⚠️ 保持 PR 小而聚焦(建议 < 500 行)
- ⚠️ 确保 TypeScript 严格模式通过
- ⚠️ 不引入 `any` 类型(必要时使用 `eslint-disable`
- ⚠️ 所有新功能必须有测试
- ⚠️ 遵循代码规范
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [TESTING.md](../../TESTING.md) - 测试文档
@@ -0,0 +1,333 @@
---
description: 性能优化流程
---
## 工作流说明
此工作流指导如何优化应用性能。
## 步骤
### 1. 识别性能问题
使用工具分析性能:
- Chrome DevTools Performance
- Vue DevTools
- Vite Build Analysis
- 内存分析工具
### 2. 分析瓶颈
确定性能瓶颈:
- 渲染性能
- 网络请求
- 内存使用
- CPU 使用
- 磁盘 I/O
### 3. 创建优化分支
```bash
git checkout -b perf/optimize-performance
```
### 4. 添加性能测试
```typescript
// src/__tests__/perf/performance.test.ts
import { describe, it, expect } from "vitest";
import { heavyFunction } from "@/modules/example";
describe("heavyFunction", () => {
it("should complete within 100ms", () => {
const start = performance.now();
heavyFunction();
const duration = performance.now() - start;
expect(duration).toBeLessThan(100);
});
});
```
### 5. 实施优化
#### 渲染性能优化
```typescript
// 使用 computed 缓存计算结果
const filteredApps = computed(() => {
return apps.value.filter(app => app.category === selectedCategory);
});
// 使用 v-memo 优化列表渲染
<template>
<div v-for="app in apps" :key="app.pkgname" v-memo="[app.id]">
{{ app.name }}
</div>
</template>
// 防抖和节流
import { debounce } from 'lodash-es';
const debouncedSearch = debounce((query: string) => {
searchApps(query);
}, 300);
```
#### 网络请求优化
```typescript
// 使用缓存
const appCache = new Map<string, App[]>();
async function fetchApps(category: string): Promise<App[]> {
if (appCache.has(category)) {
return appCache.get(category)!;
}
const apps = await axios.get(`/api/apps/${category}`);
appCache.set(category, apps.data);
return apps.data;
}
// 并发请求
const [apps1, apps2] = await Promise.all([
fetchApps("category1"),
fetchApps("category2"),
]);
```
#### 内存优化
```typescript
// 及时清理事件监听
onMounted(() => {
window.addEventListener("resize", handleResize);
});
onUnmounted(() => {
window.removeEventListener("resize", handleResize);
});
// 避免内存泄漏
let timer: number;
function startTimer() {
clearInterval(timer);
timer = setInterval(() => {
// 定时任务
}, 1000);
}
onUnmounted(() => {
clearInterval(timer);
});
```
#### 代码分割
```typescript
// 动态导入组件
const AppDetailModal = defineAsyncComponent(
() => import("@/components/AppDetailModal.vue"),
);
// 路由懒加载
const routes = [
{
path: "/app/:id",
component: () => import("@/views/AppDetail.vue"),
},
];
```
### 6. 测试性能
```bash
# 运行性能测试
npm run test:perf
# 使用 DevTools 分析
# 1. 打开 DevTools
# 2. 切换到 Performance 标签
# 3. 点击 Record
# 4. 执行操作
# 5. 停止录制并分析
```
### 7. 对比优化效果
记录优化前后的数据:
- 渲染时间
- 内存使用
- 网络请求数
- 应用启动时间
### 8. 验证功能
```bash
# 确保功能正常
npm run test
# 手动测试主要流程
```
### 9. 代码审查
检查优化是否:
- 提升了性能
- 没有破坏功能
- 代码可读
- 易于维护
### 10. 更新文档
- 记录优化内容
- 更新性能指标
- 添加优化说明
### 11. 提交代码
```bash
git add .
git commit -m "perf(scope): optimize performance" -s
git push origin perf/optimize-performance
```
### 12. 创建 Pull Request
- 说明优化内容
- 提供性能对比
- 展示优化效果
## 性能优化清单
### 渲染性能
- [ ] 使用 computed 缓存
- [ ] 使用 v-memo 优化
- [ ] 避免不必要的重新渲染
- [ ] 使用虚拟滚动(大数据集)
- [ ] 图片懒加载
### 网络性能
- [ ] 减少请求数量
- [ ] 使用缓存
- [ ] 压缩资源
- [ ] 使用 CDN
- [ ] 并发请求
### 内存性能
- [ ] 清理事件监听
- [ ] 避免内存泄漏
- [ ] 释放不再使用的资源
- [ ] 使用对象池(如需要)
- [ ] 优化数据结构
### 构建性能
- [ ] 代码分割
- [ ] Tree shaking
- [ ] 压缩代码
- [ ] 优化依赖
- [ ] 使用缓存
## 性能监控
### 关键指标
- **FCP (First Contentful Paint):** < 1.5s
- **LCP (Largest Contentful Paint):** < 2.5s
- **TTI (Time to Interactive):** < 3.5s
- **CLS (Cumulative Layout Shift):** < 0.1
- **FID (First Input Delay):** < 100ms
### 监控工具
```typescript
// 使用 Performance API
const perfData = performance.getEntriesByType("navigation")[0];
console.log("Page Load Time:", perfData.loadEventEnd - perfData.fetchStart);
// 使用 Vue DevTools
// 监控组件渲染时间
```
## 常见性能问题
### 1. 大列表渲染
**问题:** 渲染大量数据导致卡顿
**解决方案:**
```vue
<template>
<RecycleScroller :items="largeList" :item-size="50" key-field="id">
<template #default="{ item }">
<div>{{ item.name }}</div>
</template>
</RecycleScroller>
</template>
```
### 2. 频繁的 DOM 更新
**问题:** 频繁更新 DOM 导致性能下降
**解决方案:**
```typescript
// 使用 requestAnimationFrame
function animate() {
updatePosition();
requestAnimationFrame(animate);
}
```
### 3. 内存泄漏
**问题:** 内存持续增长
**解决方案:**
```typescript
// 及时清理
onUnmounted(() => {
clearInterval(timer);
removeEventListener("resize", handleResize);
clearTimeout(timeout);
});
```
### 4. 不必要的计算
**问题:** 重复计算相同结果
**解决方案:**
```typescript
// 使用 computed
const expensiveValue = computed(() => {
return heavyCalculation(data.value);
});
```
## 注意事项
- ⚠️ 不要过早优化
- ⚠️ 先测量再优化
- ⚠️ 保持代码可读
- ⚠️ 避免过度优化
- ⚠️ 持续监控性能
## 相关文档
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [TESTING.md](../../TESTING.md) - 测试文档
- [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md) - 问题排查
+284
View File
@@ -0,0 +1,284 @@
---
description: 代码重构流程
---
## 工作流说明
此工作流指导如何安全地重构代码。
## 步骤
### 1. 识别重构需求
分析代码中的问题:
- 代码重复
- 复杂度过高
- 性能问题
- 可读性差
- 难以维护
### 2. 制定重构计划
- 确定重构范围
- 列出具体改进点
- 评估影响范围
- 制定测试策略
### 3. 创建重构分支
```bash
git checkout -b refactor/your-refactor
```
### 4. 编写测试
如果代码缺少测试,先添加测试:
```typescript
// src/__tests__/unit/refactorTarget.test.ts
import { describe, it, expect } from "vitest";
import { functionToRefactor } from "@/modules/example";
describe("functionToRefactor", () => {
it("should maintain existing behavior", () => {
const result = functionToRefactor(input);
expect(result).toBe(expected);
});
});
```
### 5. 逐步重构
**原则:**
- 小步迭代
- 保持测试通过
- 不改变外部行为
**示例:**
```typescript
// 重构前
function processApp(app: any) {
if (app) {
return {
name: app.name,
pkgname: app.pkgname,
version: app.version,
};
}
return null;
}
// 重构后 - 添加类型
interface App {
name: string;
pkgname: string;
version: string;
}
function processApp(app: App | null): App | null {
if (!app) return null;
return {
name: app.name,
pkgname: app.pkgname,
version: app.version,
};
}
```
### 6. 运行测试
```bash
# 每次重构后运行测试
npm run test
# 确保所有测试通过
npm run test:all
```
### 7. 性能验证
如果重构涉及性能:
```bash
# 运行性能测试
npm run test:perf
# 对比重构前后性能
```
### 8. 代码审查
自我检查:
- 代码更清晰
- 性能未下降
- 测试全部通过
- 没有引入新问题
### 9. 更新文档
- 更新相关文档
- 添加注释说明
- 更新 CHANGELOG.md
### 10. 提交代码
```bash
git add .
git commit -m "refactor(scope): describe the refactoring" -s
git push origin refactor/your-refactor
```
### 11. 创建 Pull Request
- 说明重构原因
- 展示改进效果
- 提供性能对比(如需要)
### 12. 代码审查
- 响应审查意见
- 确保所有测试通过
- 合并到 main 分支
## 重构原则
### 不改变外部行为
- 保持 API 兼容
- 保持输出一致
- 保持错误处理
### 小步迭代
- 每次只改一处
- 频繁运行测试
- 及时提交代码
### 测试驱动
- 先写测试
- 重构代码
- 确保通过
### 保持简单
- 减少复杂度
- 提高可读性
- 增强可维护性
## 常见重构模式
### 提取函数
```typescript
// 重构前
function processApps(apps: App[]) {
for (const app of apps) {
if (app.installed) {
console.log(app.name + " is installed");
}
}
}
// 重构后
function logInstalledApp(app: App) {
if (app.installed) {
console.log(`${app.name} is installed`);
}
}
function processApps(apps: App[]) {
apps.forEach(logInstalledApp);
}
```
### 提取类型
```typescript
// 重构前
function createDownload(data: any) {
return {
id: data.id,
name: data.name,
pkgname: data.pkgname,
};
}
// 重构后
interface DownloadData {
id: number;
name: string;
pkgname: string;
}
function createDownload(data: DownloadData): DownloadItem {
return {
id: data.id,
name: data.name,
pkgname: data.pkgname,
status: "queued",
progress: 0,
downloadedSize: 0,
totalSize: 0,
speed: 0,
timeRemaining: 0,
startTime: Date.now(),
logs: [],
source: "APM Store",
retry: false,
};
}
```
### 简化条件
```typescript
// 重构前
function getStatus(status: string): string {
if (status === "queued") {
return "Queued";
} else if (status === "downloading") {
return "Downloading";
} else if (status === "installing") {
return "Installing";
} else if (status === "completed") {
return "Completed";
} else if (status === "failed") {
return "Failed";
} else {
return "Unknown";
}
}
// 重构后
const statusMap: Record<string, string> = {
queued: "Queued",
downloading: "Downloading",
installing: "Installing",
completed: "Completed",
failed: "Failed",
};
function getStatus(status: string): string {
return statusMap[status] || "Unknown";
}
```
## 注意事项
- ⚠️ 不要在重构中引入新功能
- ⚠️ 不要同时重构多处
- ⚠️ 确保测试覆盖充分
- ⚠️ 保持提交历史清晰
- ⚠️ 及时回退有问题的重构
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [TESTING.md](../../TESTING.md) - 测试文档
+211
View File
@@ -0,0 +1,211 @@
---
description: 发布流程
---
## 工作流说明
此工作流指导如何发布新版本。
## 步骤
### 1. 更新版本号
```bash
# 更新版本
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
# 或手动编辑 package.json
```
### 2. 更新 CHANGELOG.md
```bash
# 生成变更日志
npm run changelog
```
或手动更新:
```markdown
## [1.0.1](https://github.com/elysia-best/apm-app-store/compare/v1.0.0...v1.0.1) (2026-03-10)
### Bug Fixes
- fix(ui): correct dark mode toggle persistence (#123)
### Features
- feat(install): add retry mechanism for failed installations (#124)
```
### 3. 运行完整测试
```bash
# 运行所有测试
npm run test:all
# 运行代码检查
npm run lint
npm run format
# 构建项目
npm run build:vite
```
### 4. 提交变更
```bash
git add .
git commit -m "chore(release): bump version to x.x.x" -s
git push origin main
```
### 5. 创建 Git 标签
```bash
# 创建标签
git tag v{version}
# 推送标签
git push origin v{version}
```
### 6. 触发 CI 构建
推送标签后会自动触发 GitHub Actions 构建。
### 7. 验证构建
在 GitHub Actions 页面查看:
- 所有测试通过
- 构建成功
- 构建产物生成
### 8. 检查 Release
GitHub Actions 会自动创建 Release
- 访问 Releases 页面
- 检查版本信息
- 确认构建产物
### 9. 发布说明
如果需要,更新 Release 说明:
- 添加主要变更
- 添加已知问题
- 添加升级说明
### 10. 通知用户
- 更新 README
- 发布公告
- 通知用户
## 发布检查清单
### 代码质量
- [ ] 所有测试通过
- [ ] 代码检查通过
- [ ] 没有已知严重 Bug
- [ ] 性能测试通过
### 文档
- [ ] CHANGELOG.md 更新
- [ ] README.md 更新(如需要)
- [ ] API 文档更新(如需要)
### 构建
- [ ] 本地构建成功
- [ ] CI 构建成功
- [ ] 构建产物正确
### 发布
- [ ] 版本号正确
- [ ] 标签已推送
- [ ] Release 已创建
- [ ] 构建产物已上传
## 版本号规范
遵循 [Semantic Versioning](https://semver.org/)
- **MAJOR:** 不兼容的 API 变更
- **MINOR:** 向后兼容的功能新增
- **PATCH:** 向后兼容的 Bug 修复
### 示例
```
4.9.9 → 4.9.10 (PATCH: Bug 修复)
4.9.9 → 4.10.0 (MINOR: 新功能)
4.9.9 → 5.0.0 (MAJOR: 重大变更)
```
## 发布后
### 更新开发分支
```bash
git checkout develop
git merge main
git push origin develop
```
### 监控反馈
- 收集用户反馈
- 监控 Bug 报告
- 记录性能数据
### 准备下一个版本
- 创建新的 Issue
- 规划新功能
- 评估技术债务
## 回滚流程
如果发现严重问题:
### 1. 立即停止推广
- 通知用户暂停升级
- 更新下载页面
### 2. 修复问题
```bash
git checkout main
git checkout -b fix/critical-issue
# 修复问题
git push origin fix/critical-issue
```
### 3. 紧急发布
```bash
npm version patch
git tag -a v{x.x.x} -m "Hotfix: description"
git push origin v{x.x.x}
```
### 4. 通知用户
- 发布新版本
- 说明问题和修复
- 提供升级说明
## 相关文档
- [DEPLOYMENT.md](../../DEPLOYMENT.md) - 部署文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [CHANGELOG.md](../../CHANGELOG.md) - 变更日志
+47
View File
@@ -0,0 +1,47 @@
---
description: 运行项目 (自动安装依赖)
---
## 工作流说明
此工作流将检查运行环境,自动安装缺失的依赖,并启动开发服务器。
## 步骤
### 1. 检查 Node.js 环境
确保已安装 Node.js 和 npm。
// turbo
```bash
node -v && npm -v
```
### 2. 检查并安装依赖
检查 `node_modules` 是否存在。如果不存在,将自动运行 `npm install`
// turbo
```bash
if [ ! -d "node_modules" ]; then
echo "检测到缺少依赖,正在安装..."
npm install
else
echo "依赖已安装,准备启动..."
fi
```
### 3. 运行开发服务器
启动项目开发模式。
// turbo
```bash
npm run dev
```
## 注意事项
- 首次运行可能需要一些时间安装依赖。
- 如果安装失败,请手动运行 `npm install` 查看详细错误。
- 确保您的系统中已安装并配置好 Electron 所需的系统依赖。
+435
View File
@@ -0,0 +1,435 @@
---
description: 安全审计流程
---
## 工作流说明
此工作流指导如何进行安全审计。
## 步骤
### 1. 确定审计范围
确定需要审计的方面:
- 代码安全
- 依赖安全
- 数据安全
- 网络安全
- 权限管理
### 2. 创建审计分支
```bash
git checkout -b security/security-audit
```
### 3. 代码安全审计
#### 检查 SQL 注入
```typescript
// ❌ 不安全
const query = `SELECT * FROM apps WHERE name = '${appName}'`;
// ✅ 安全
const query = "SELECT * FROM apps WHERE name = ?";
db.query(query, [appName]);
```
#### 检查 XSS 攻击
```typescript
// ❌ 不安全
element.innerHTML = userInput;
// ✅ 安全
element.textContent = userInput;
// 或使用 DOMPurify
import DOMPurify from "dompurify";
element.innerHTML = DOMPurify.sanitize(userInput);
```
#### 检查命令注入
```typescript
// ❌ 不安全
const cmd = `apm install ${packageName}`;
exec(cmd);
// ✅ 安全
const args = ["apm", "install", packageName];
spawn("apm", args);
```
#### 检查路径遍历
```typescript
// ❌ 不安全
const filePath = path.join(basePath, userInput);
// ✅ 安全
const safePath = path.normalize(userInput).replace(/^(\.\.(\/|\\|$))+/, "");
const filePath = path.join(basePath, safePath);
```
### 4. 依赖安全审计
```bash
# 检查依赖漏洞
npm audit
# 自动修复
npm audit fix
# 手动修复
npm audit fix --force
```
#### 检查 package.json
```json
{
"dependencies": {
"axios": "^1.13.2",
"pino": "^10.3.0"
},
"devDependencies": {
"@playwright/test": "^1.40.0"
}
}
```
### 5. 数据安全审计
#### 检查敏感信息
```typescript
// ❌ 不安全 - 硬编码密钥
const apiKey = "sk-1234567890";
// ✅ 安全 - 使用环境变量
const apiKey = process.env.API_KEY;
// ❌ 不安全 - 记录敏感信息
logger.info({ password: user.password }, "User logged in");
// ✅ 安全 - 不记录敏感信息
logger.info({ userId: user.id }, "User logged in");
```
#### 检查数据加密
```typescript
// 加密敏感数据
import crypto from "crypto";
function encrypt(text: string, key: string): string {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
let encrypted = cipher.update(text, "utf8", "hex");
encrypted += cipher.final("hex");
return iv.toString("hex") + ":" + encrypted;
}
```
### 6. 网络安全审计
#### 检查 HTTPS
```typescript
// ❌ 不安全 - HTTP
const baseURL = "http://api.example.com";
// ✅ 安全 - HTTPS
const baseURL = "https://api.example.com";
```
#### 检查证书验证
```typescript
// 配置 Axios 验证证书
const axiosInstance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: true,
}),
});
```
#### 检查 CORS
```typescript
// 配置 CORS
app.use(
cors({
origin: "https://yourdomain.com",
credentials: true,
}),
);
```
### 7. 权限管理审计
#### 检查权限提升
```typescript
// 检查 pkexec 可用性
const checkSuperUserCommand = async (): Promise<string> => {
if (process.getuid && process.getuid() !== 0) {
const { stdout } = await execAsync("which /usr/bin/pkexec");
return stdout.trim().length > 0 ? "/usr/bin/pkexec" : "";
}
return "";
};
```
#### 检查上下文隔离
```typescript
// electron/preload/index.ts
// ✅ 安全 - 启用上下文隔离
contextBridge.exposeInMainWorld("ipcRenderer", {
send: (...args) => ipcRenderer.send(...args),
on: (...args) => ipcRenderer.on(...args),
invoke: (...args) => ipcRenderer.invoke(...args),
});
// ❌ 不安全 - 禁用上下文隔离
contextIsolation: false;
```
### 8. 运行安全工具
```bash
# 使用 Snyk 扫描
npx snyk test
# 使用 npm audit
npm audit
# 使用 ESLint 安全规则
npm run lint
```
### 9. 修复安全问题
根据审计结果修复发现的问题:
```typescript
// 修复示例
function validateInput(input: string): boolean {
// 验证输入
const regex = /^[a-zA-Z0-9-_]+$/;
return regex.test(input);
}
function sanitizeInput(input: string): string {
// 清理输入
return input.trim().replace(/[<>]/g, "");
}
```
### 10. 安全测试
```typescript
// src/__tests__/security/security.test.ts
import { describe, it, expect } from "vitest";
import { validateInput, sanitizeInput } from "@/modules/security";
describe("Security", () => {
describe("validateInput", () => {
it("should reject malicious input", () => {
expect(validateInput('<script>alert("xss")</script>')).toBe(false);
});
it("should accept valid input", () => {
expect(validateInput("valid-app-name")).toBe(true);
});
});
describe("sanitizeInput", () => {
it("should remove dangerous characters", () => {
expect(sanitizeInput("<script>app</script>")).toBe("scriptapp/script");
});
});
});
```
### 11. 更新文档
- 记录安全问题
- 说明修复方法
- 更新安全指南
### 12. 提交代码
```bash
git add .
git commit -m "security: fix security vulnerabilities" -s
git push origin security/security-audit
```
### 13. 创建 Pull Request
- 说明安全问题
- 展示修复方法
- 提供安全测试结果
## 安全检查清单
### 代码安全
- [ ] 输入验证
- [ ] 输出编码
- [ ] 参数化查询
- [ ] 错误处理
- [ ] 日志安全
### 依赖安全
- [ ] 定期更新依赖
- [ ] 使用 `npm audit`
- [ ] 检查已知漏洞
- [ ] 使用可信源
### 数据安全
- [ ] 敏感数据加密
- [ ] 不记录敏感信息
- [ ] 使用环境变量
- [ ] 安全存储
### 网络安全
- [ ] 使用 HTTPS
- [ ] 验证证书
- [ ] 配置 CORS
- [ ] 防止 CSRF
### 权限管理
- [ ] 最小权限原则
- [ ] 上下文隔离
- [ ] 权限检查
- [ ] 审计日志
## 常见安全问题
### 1. XSS 攻击
**问题:** 用户输入包含恶意脚本
**解决方案:**
```typescript
import DOMPurify from "dompurify";
function sanitizeHTML(html: string): string {
return DOMPurify.sanitize(html);
}
```
### 2. SQL 注入
**问题:** 恶意 SQL 代码注入
**解决方案:**
```typescript
// 使用参数化查询
db.query("SELECT * FROM apps WHERE name = ?", [appName]);
```
### 3. 命令注入
**问题:** 恶意命令注入
**解决方案:**
```typescript
// 使用 spawn 而非 exec
const args = ["apm", "install", packageName];
spawn("apm", args);
```
### 4. 路径遍历
**问题:** 访问未授权文件
**解决方案:**
```typescript
// 验证路径
const safePath = path.normalize(userPath).replace(/^(\.\.(\/|\\|$))+/, "");
```
### 5. 敏感信息泄露
**问题:** 日志中包含敏感信息
**解决方案:**
```typescript
// 不记录敏感信息
logger.info({ userId: user.id }, "User logged in");
```
## 安全最佳实践
### 1. 最小权限原则
只授予必要的权限,避免过度授权。
### 2. 深度防御
多层安全防护,不依赖单一安全措施。
### 3. 输入验证
验证所有输入,包括用户输入和 API 响应。
### 4. 输出编码
对输出进行编码,防止 XSS 攻击。
### 5. 定期审计
定期进行安全审计,及时发现和修复问题。
### 6. 安全更新
及时更新依赖和系统,修复已知漏洞。
## 安全工具
### 静态分析
- ESLint
- TypeScript
- SonarQube
### 动态分析
- OWASP ZAP
- Burp Suite
- Snyk
### 依赖扫描
- npm audit
- Snyk
- Dependabot
## 注意事项
- ⚠️ 不要忽视安全问题
- ⚠️ 及时修复漏洞
- ⚠️ 定期更新依赖
- ⚠️ 保持安全意识
- ⚠️ 遵循安全最佳实践
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [SECURITY.md](../../SECURITY.md) - 安全政策
+108
View File
@@ -0,0 +1,108 @@
---
description: 测试编写流程
---
## 工作流说明
此工作流指导如何为新功能或 Bug 修复编写测试。
## 步骤
### 1. 确定测试范围
分析需要测试的功能点:
- 单元测试:测试独立函数/组件
- 集成测试:测试模块间交互
- E2E 测试:测试完整用户流程
### 2. 编写单元测试(Vitest
`src/__tests__/unit/` 目录下创建测试文件:
```typescript
import { describe, it, expect } from "vitest";
import { someFunction } from "@/modules/example";
describe("someFunction", () => {
it("should return expected result", () => {
const result = someFunction(input);
expect(result).toBe(expected);
});
});
```
### 3. 编写组件测试
```typescript
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import AppCard from "@/components/AppCard.vue";
describe("AppCard", () => {
it("should render app name", () => {
const wrapper = mount(AppCard, {
props: {
app: {
name: "Test App",
pkgname: "test-app",
},
},
});
expect(wrapper.text()).toContain("Test App");
});
});
```
### 4. 编写 E2E 测试(Playwright
`e2e/` 目录下创建测试文件:
```typescript
import { test, expect } from "@playwright/test";
test("install app from store", async ({ page }) => {
await page.goto("http://localhost:3344");
await page.click("text=Test App");
await page.click('button:has-text("安装")');
await expect(page.locator(".install-progress")).toBeVisible();
});
```
### 5. 运行测试
```bash
# 运行单元测试
npm run test
# 运行测试并监听
npm run test:watch
# 运行 E2E 测试
npm run test:e2e
# 生成覆盖率报告
npm run test:coverage
```
### 6. 确保测试通过
- 所有单元测试必须通过
- E2E 测试覆盖主要用户流程
- 测试覆盖率不低于 70%
### 7. 提交代码
测试通过后,提交代码并创建 PR。
## 注意事项
- ⚠️ 不要测试第三方库的功能
- ⚠️ 保持测试独立性和可重复性
- ⚠️ 使用有意义的测试名称
- ⚠️ Mock 外部依赖(APM 命令、API 调用)
## 相关文档
- [TESTING.md](../../TESTING.md) - 测试框架和规范
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
+3
View File
@@ -0,0 +1,3 @@
VITE_APM_STORE_LOCAL_MODE=true
VITE_APM_STORE_BASE_URL=/local_amd64-store
VITE_APM_STORE_STATS_BASE_URL=/local_stats
+2
View File
@@ -0,0 +1,2 @@
VITE_APM_STORE_BASE_URL=https://erotica.spark-app.store
VITE_APM_STORE_STATS_BASE_URL=https://feedback.spark-app.store
-4
View File
@@ -1,4 +0,0 @@
FROM shenmo7192/uos-21-dtk5.4:1.0
ADD . /root/workdir
WORKDIR /root/workdir
RUN dpkg-buildpackage
-31
View File
@@ -1,31 +0,0 @@
import os
import requests
import json
# sha=os.system("git rev-parse HEAD")
sha = os.getenv("GIT_COMMIT")
# sha = '48fed26c51a8c42554e45f72f43e49703e04c97f'
#get sha from environment
url = "https://gitee.com/api/v5/repos/deepin-community-store/spark-store/commits/{}/comments".format(sha)
token = os.getenv("gitee_token")
# process = os.popen("git symbolic-ref --short -q HEAD")
body = "构建详情请见" + os.getenv("JENKINS_URL") + "blue/organizations/jenkins/" + os.getenv("JOB_NAME").replace("/", "/detail/") + "/" + str(os.getenv("BUILD_ID"))
# process.close()
d = {
'access_token': token,
"body": body
}
h = {
"Content-Type": "application/json;charset=UTF-8"
}
res = requests.post(url,headers=h, data=json.dumps(d))
# print(res.status_code)
# print(res.content)
+52
View File
@@ -0,0 +1,52 @@
---
name: Bug 报告
about: 创建一个 Bug 报告以帮助我们改进
title: "[Bug] "
labels: bug
assignees: ""
---
## 描述
清晰简洁地描述这个 Bug 是什么。
## 复现步骤
1. 打开 '...'
2. 点击 '....'
3. 滚动到 '....'
4. 看到错误
## 期望行为
清晰简洁地描述你期望发生什么。
## 实际行为
清晰简洁地描述实际发生了什么。
## 截图
如果适用,添加截图以帮助解释你的问题。
## 环境信息
**操作系统:** [例如: Ubuntu 22.04]
**APM 版本:** [例如: 1.0.0]
**应用商店版本:** [例如: 4.9.9]
**桌面环境:** [例如: GNOME, KDE]
## 日志
如果相关,粘贴日志到以下区域(使用代码块):
```
粘贴日志内容
```
## 额外上下文
添加任何其他关于问题的上下文信息。
+23
View File
@@ -0,0 +1,23 @@
---
name: 功能请求 / 帮助请求
about: 为这个项目建议一个新想法
title: "[Feature] "
labels: enhancement
assignees: ""
---
## 你的功能请求是否与问题有关?
清晰简洁地描述问题。例如:我在 [...] 时总是感到沮丧
## 你想要的解决方案是什么?
清晰简洁地描述你想要发生什么。
## 你考虑过哪些替代方案?
清晰简洁地描述你考虑过的任何替代解决方案或功能。
## 额外上下文
添加任何其他关于功能请求的上下文或截图。
+12
View File
@@ -0,0 +1,12 @@
<!-- Thank you for contributing! -->
### Description
<!-- Please insert your description here and provide especially info about the "what" this PR is solving -->
### What is the purpose of this pull request? <!-- (put an "X" next to an item) -->
- [ ] Bug fix
- [ ] New Feature
- [ ] Documentation update
- [ ] Other
+15
View File
@@ -0,0 +1,15 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
+143
View File
@@ -0,0 +1,143 @@
name: Build
on:
push:
branches: [main]
tags:
- "*"
paths-ignore:
- "**.md"
- "**.spec.js"
- ".idea"
- ".vscode"
- ".dockerignore"
- "Dockerfile"
- ".gitignore"
- ".github/**"
- "!.github/workflows/build.yml"
- "!.github/workflows/test.yml"
pull_request:
branches: [main]
paths-ignore:
- "**.md"
- "**.spec.js"
- ".idea"
- ".vscode"
- ".dockerignore"
- "Dockerfile"
- ".gitignore"
- ".github/**"
- "!.github/workflows/build.yml"
permissions:
contents: write
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm install
- name: Run tests
run: npm run test
- name: Run lint
run: npm run lint
build:
needs: test
runs-on: ${{ matrix.os }}
container: ${{ matrix.docker_image }}
strategy:
matrix:
os: [ubuntu-latest]
package: [deb, rpm]
architecture: [x64, arm64]
include:
- package: deb
docker_image: "debian:12"
- package: rpm
docker_image: "almalinux:8"
steps:
- name: Install Build Dependencies
if: matrix.package == 'deb'
run: |
apt-get update
apt-get install -y curl git wget devscripts fakeroot equivs lintian python3
apt-get install -y build-essential
- name: Install Build Dependencies
if: matrix.package == 'rpm'
run: |
dnf install -y curl git wget rpm-build rpmdevtools rpmlint python3
dnf group install -y "Development Tools"
- name: Checkout Code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install Dependencies
run: |
npm install
- name: Download host-spawn
shell: bash
run: |
if [ "${{ matrix.architecture }}" == "x64" ]; then
curl -fsSL -o ./extras/host-spawn https://github.com/1player/host-spawn/releases/latest/download/host-spawn-x86_64
elif [ "${{ matrix.architecture }}" == "arm64" ]; then
curl -fsSL -o ./extras/host-spawn https://github.com/1player/host-spawn/releases/latest/download/host-spawn-aarch64
fi
chmod +x ./extras/host-spawn
- name: Build Release Files
shell: bash
run: |
if [ "${{ matrix.package }}" == "deb" ]; then
npm run build:deb -- --${{ matrix.architecture }}
elif [ "${{ matrix.package }}" == "rpm" ]; then
npm run build:rpm -- --${{ matrix.architecture }}
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Artifact
uses: actions/upload-artifact@v6
with:
name: release_for_${{ matrix.package }}_${{ matrix.architecture }}
path: release/**/*.${{ matrix.package }}
retention-days: 5
release:
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: artifacts
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
files: |
artifacts/**/*.deb
artifacts/**/*.rpm
generate_release_notes: true
+83
View File
@@ -0,0 +1,83 @@
name: Test
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm install
- name: Run unit tests
run: npm run test -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella
e2e-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm install
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
- name: Run E2E tests
run: xvfb-run npm run test:e2e
- name: Upload test results
if: always()
uses: actions/upload-artifact@v6
with:
name: playwright-report
path: playwright-report/
retention-days: 30
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm install
- name: Run ESLint
run: npm run lint
- name: Check formatting
run: npm run format -- --check
+36 -48
View File
@@ -1,54 +1,42 @@
# C++ objects and libs # Logs
*.slo logs
*.lo *.log
*.o npm-debug.log*
*.a yarn-debug.log*
*.la yarn-error.log*
*.lai pnpm-debug.log*
*.so lerna-debug.log*
*.dll
*.dylib
# Qt-es node_modules
object_script.*.Release dist
object_script.*.Debug dist-ssr
*_plugin_import.cpp dist-electron
/.qmake.cache release
/.qmake.stash *.local
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
# Qt unit tests # Test coverage
target_wrapper.* coverage
.nyc_output
# Qt qm files # Playwright
translations/*.qm test-results
playwright-report
playwright/.cache
# QtCreator # Editor directories and files
*.autosave .vscode/.debug.env
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# QtCreator Qml # lockfile
*.qmlproject.user pnpm-lock.yaml
*.qmlproject.user.* yarn.lock
.lock
# QtCreator CMake
CMakeLists.txt.user*
build
# Debian dpkg-buildpackage
debian/*.debhelper*
debian/files
debian/*.substvars
debian/spark-store
test-results.json
.worktrees/
+6
View File
@@ -0,0 +1,6 @@
# For electron-builder
# https://github.com/electron-userland/electron-builder/issues/6289#issuecomment-1042620422
shamefully-hoist=true
# For China 🇨🇳 developers
# electron_mirror=https://npmmirror.com/mirrors/electron/
+23
View File
@@ -0,0 +1,23 @@
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { createRequire } from 'node:module'
import { spawn } from 'node:child_process'
const pkg = createRequire(import.meta.url)('../package.json')
const __dirname = path.dirname(fileURLToPath(import.meta.url))
// write .debug.env
const envContent = Object.entries(pkg.debug.env).map(([key, val]) => `${key}=${val}`)
fs.writeFileSync(path.join(__dirname, '.debug.env'), envContent.join('\n'))
// bootstrap
spawn(
// TODO: terminate `npm run dev` when Debug exits.
process.platform === 'win32' ? 'npm.cmd' : 'npm',
['run', 'dev'],
{
stdio: 'inherit',
env: Object.assign(process.env, { VSCODE_DEBUG: 'true' }),
},
)
+6
View File
@@ -0,0 +1,6 @@
{
"recommendations": [
"Vue.volar",
"Vue.vscode-typescript-vue-plugin"
]
}
+53
View File
@@ -0,0 +1,53 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"compounds": [
{
"name": "Debug App",
"preLaunchTask": "Before Debug",
"configurations": [
"Debug Main Process",
"Debug Renderer Process"
],
"presentation": {
"hidden": false,
"group": "",
"order": 1
},
"stopAll": true
}
],
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
// "windows": {
// "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
// },
"runtimeArgs": [
"--remote-debugging-port=9229",
"."
],
"envFile": "${workspaceFolder}/.vscode/.debug.env",
"console": "integratedTerminal"
},
{
"name": "Debug Renderer Process",
"port": 9229,
"request": "attach",
"type": "chrome",
"timeout": 60000,
"skipFiles": [
"<node_internals>/**",
"${workspaceRoot}/node_modules/**",
"${workspaceRoot}/dist-electron/**",
// Skip files in host(VITE_DEV_SERVER_URL)
"http://127.0.0.1:3344/**"
]
},
]
}
+18
View File
@@ -0,0 +1,18 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.tsc.autoDetect": "off",
"json.schemas": [
{
"fileMatch": [
"/*electron-builder.json5",
"/*electron-builder.json"
],
"url": "https://json.schemastore.org/electron-builder"
}
],
"eslint.validate": [
"javascript",
"javascriptreact",
"vue"
]
}
+31
View File
@@ -0,0 +1,31 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Before Debug",
"type": "shell",
"command": "node .vscode/.debug.script.mjs",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"fileLocation": "relative",
"pattern": {
// TODO: correct "regexp"
"regexp": "^([a-zA-Z]\\:\/?([\\w\\-]\/?)+\\.\\w+):(\\d+):(\\d+): (ERROR|WARNING)\\: (.*)$",
"file": 1,
"line": 3,
"column": 4,
"code": 5,
"message": 6
},
"background": {
"activeOnStart": true,
"beginsPattern": "^.*VITE v.* ready in \\d* ms.*$",
"endsPattern": "^.*\\[startup\\] Electron App.*$"
}
}
}
]
}
-39
View File
@@ -1,39 +0,0 @@
version: '1.0'
name: dtk-build-commit-20220425
displayName: dtk-build-commit
triggers:
trigger: auto
pr:
branches:
prefix:
- ''
stages:
- name: stage-4e566164
displayName: build
strategy: naturally
trigger: auto
executor: []
steps:
- step: execute@docker
name: execute_by_docker
displayName: 基于镜像的脚本执行
certificate: ''
image: docker.io/debian:buster-slim
command:
- sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
- '# 换源'
- apt update
- export DEBIAN_FRONTEND=noninteractive
- echo "安装git devscripts equivs ..."
- apt install git devscripts equivs curl -y >/dev/null 2>&1
- git clone https://gitlink.org.cn/shenmo7192/dtk-old-bundle.git
- cd dtk-old-bundle
- apt install ./*.deb -y
- cd ..
- rm -rf dtk-old-bundle
- 'mk-build-deps --install --tool "apt-get -o Debug::pkgProblemResolver=yes -y" '
- dpkg-buildpackage -b -us -uc
- cd ..
- ls -all
- pwd
strategy: {}
@@ -1,57 +0,0 @@
version: '1.0'
name: dtk-build-release-tag-20220425
displayName: dtk-build-release-tag
triggers:
trigger: auto
push:
tags:
prefix:
- ''
stages:
- name: stage-4e566164
displayName: build
strategy: naturally
trigger: auto
executor: []
steps:
- step: build@nodejs
name: build_dtk
displayName: DTK构建
nodeVersion: 14.16.0
commands:
- git clone https://gitlink.org.cn/shenmo7192/debian-10-container.git
- mv debian-10-container/Debian-10.tar.xz /mnt
- rm -rf debian-10-container
- WORK_DIR=`pwd`
- cd /mnt/
- tar -xf Debian-10.tar.xz
- cd Debian-10
- wget https://gitee.com/deepin-community-store/repo_auto_update_script/raw/master/spark-build.sh
- chmod +x spark-build.sh
- mkdir build-spark
- cp -r $WORK_DIR build-spark/spark-store
- echo "进入Debian 10环境"
- chroot /mnt/Debian-10 /bin/bash /spark-build.sh
- cd /mnt/Debian-10/build-spark
artifacts:
- name: BUILD_ARTIFACT
path:
- /mnt/Debian-10/build-spark/target
caches: []
notify: []
strategy:
retry: '0'
- name: stage-29f3ffbb
displayName: 上传
strategy: naturally
trigger: auto
executor: []
steps:
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
dependArtifact: BUILD_ARTIFACT
artifactName: output
notify: []
strategy:
retry: '0'
+1021
View File
File diff suppressed because it is too large Load Diff
+146
View File
@@ -0,0 +1,146 @@
## [1.1.1](https://github.com/elysia-best/apm-app-store/compare/v1.1.0...v1.1.1) (2026-02-17)
### Bug Fixes
* **main:** use app.getVersion() for packaged app ([d45d508](https://github.com/elysia-best/apm-app-store/commit/d45d5082f45d60de69d07998429d6f49c64a7b95))
# [1.1.0](https://github.com/elysia-best/apm-app-store/compare/v1.1.0-beta.1...v1.1.0) (2026-02-14)
### Bug Fixes
* **app:** floor download progress percentage ([ed92145](https://github.com/elysia-best/apm-app-store/commit/ed92145f9145b9190858e1cf4c2a722efe0e2ff0))
# [1.1.0-beta.1](https://github.com/elysia-best/apm-app-store/compare/v1.0.4...v1.1.0-beta.1) (2026-02-14)
### Bug Fixes
* 修复应用还没有安装完,按钮就重新变成可安装状态 ([#11](https://github.com/elysia-best/apm-app-store/issues/11)) ([b43c611](https://github.com/elysia-best/apm-app-store/commit/b43c6117ecb1ec12f590667dfad7db13263d9d68))
### Features
* 更新类型系统指南,添加代码检查和格式化要求 ([10808c8](https://github.com/elysia-best/apm-app-store/commit/10808c8f3b2f5535c7dfca6fc8a1e7a45cb5b95c))
* 更新搜索逻辑 ([d5266c6](https://github.com/elysia-best/apm-app-store/commit/d5266c6af81eb6aa28e2f376c88affbea227a5f7))
* 添加 ESLint 配置并优化代码风格,移除未使用的功能 ([e11740a](https://github.com/elysia-best/apm-app-store/commit/e11740ad4cff877d93e409bc8adb28f15717e97e))
* **app:** add cache buster for API requests ([9f50e25](https://github.com/elysia-best/apm-app-store/commit/9f50e25dc09cc0bf1d8e68cefb6843aa9bd8b7e6)), closes [#16](https://github.com/elysia-best/apm-app-store/issues/16)
* **app:** add download count display ([a3f18bb](https://github.com/elysia-best/apm-app-store/commit/a3f18bb593a8b3b1da9927582eb9f6fb5ef18e24))
* **docs:** 添加 AI 编码指导文档以概述项目架构和核心概念 ([c3ae477](https://github.com/elysia-best/apm-app-store/commit/c3ae4774976bd0464ca8d500792f4865f0b589e9))
* **install:** add metalink download support and progress tracking ([74c4eb4](https://github.com/elysia-best/apm-app-store/commit/74c4eb4fbc7dd0d91bbbfac2b91bbb2bf1fa0b68)), closes [#12](https://github.com/elysia-best/apm-app-store/issues/12)
* support download statistics ([5ac9376](https://github.com/elysia-best/apm-app-store/commit/5ac9376200e54e331d22564424db4c41564d23d3)), closes [#15](https://github.com/elysia-best/apm-app-store/issues/15)
* **theme:** add system theme support ([7aeb3d5](https://github.com/elysia-best/apm-app-store/commit/7aeb3d5dd4d53ce6a6fed03957ee6f5d9eee0f39)), closes [#13](https://github.com/elysia-best/apm-app-store/issues/13)
## [1.0.4](https://github.com/elysia-best/apm-app-store/compare/v1.0.4-beta.1...v1.0.4) (2026-01-31)
## [1.0.4-beta.1](https://github.com/elysia-best/apm-app-store/compare/v1.0.4-beta.0...v1.0.4-beta.1) (2026-01-31)
### Bug Fixes
* 修复应用启动命令,移除交互式模式 ([2f7af3c](https://github.com/elysia-best/apm-app-store/commit/2f7af3ca8f704ae0ae9aba572f3f451c7d5a701c))
### Features
* 添加 host-spawn 下载步骤并更新应用启动命令 ([850b8dc](https://github.com/elysia-best/apm-app-store/commit/850b8dcd1ff9789960dca38527cfa03008fa8c89))
## [1.0.4-beta.0](https://github.com/elysia-best/apm-app-store/compare/v1.0.3...v1.0.4-beta.0) (2026-01-31)
### Features
* 添加重复任务检查,避免重复下载任务 ([0d1d4e5](https://github.com/elysia-best/apm-app-store/commit/0d1d4e567940366c5754f4dcdb83213f8fe87d7d))
* 现在仅在有任务时才会到托盘 ([92d1573](https://github.com/elysia-best/apm-app-store/commit/92d1573cf082402b7f44a6beedbc47f58dc91781))
* enhance install manager to prevent duplicate package installations and improve app launching command ([eeefe52](https://github.com/elysia-best/apm-app-store/commit/eeefe5295b8698b887afad467c8151add6e4e8f5))
## [1.0.3](https://github.com/elysia-best/apm-app-store/compare/v1.0.3-beta.1...v1.0.3) (2026-01-31)
### Bug Fixes
* deep link handling at electron startup ([0ed7f64](https://github.com/elysia-best/apm-app-store/commit/0ed7f64a218e0a26b384810b1a0ac8ae314c2501))
### Features
* add app launching functionality and update related components ([6154d75](https://github.com/elysia-best/apm-app-store/commit/6154d75fa6893825e74f7bc421fa91eef0fc4f3f))
* enhance application type definitions and improve app management logic ([39e40ff](https://github.com/elysia-best/apm-app-store/commit/39e40ff946911c82190c7f0158b5bab9287ac3e4))
* update application icons and implement tray functionality ([f89b9eb](https://github.com/elysia-best/apm-app-store/commit/f89b9ebfd9ba75fef675d063bf8632143fd125d4))
* update application name and paths to reflect new branding ([641589f](https://github.com/elysia-best/apm-app-store/commit/641589f8754b638a7f53c729a2930f33884cd51e))
## [1.0.3-beta.1](https://github.com/elysia-best/apm-app-store/compare/v1.0.2...v1.0.3-beta.1) (2026-01-31)
### Bug Fixes
* 修复确认卸载界面应用名称显示 ([b4ef653](https://github.com/elysia-best/apm-app-store/commit/b4ef6532997fdfeb950af16edfa718d1c19507f5))
* 修复卸载请求中的应用名称查找逻辑 ([9799718](https://github.com/elysia-best/apm-app-store/commit/97997182bc2bf7b8d3a34f062deadfd910987b09))
* **build:** add bash shell to build release files ([354eea3](https://github.com/elysia-best/apm-app-store/commit/354eea36267f0284381521ee401d15256ecf8151))
### Features
* 更新安装按钮状态反馈,添加安装队列提示 ([4ce097b](https://github.com/elysia-best/apm-app-store/commit/4ce097bae032601572112d4647f6374875ca9719))
* 更新版本号至 1.0.3-beta.0 ([327ee54](https://github.com/elysia-best/apm-app-store/commit/327ee5400e1b967902734d381411a2cf239ddb16))
* 更新本地应用列表,区分依赖和用户安装的包 ([588eaf9](https://github.com/elysia-best/apm-app-store/commit/588eaf9746482d18716c4f929a3150b560aa5a62))
* 更新模态框样式,添加最大高度限制 ([61790a8](https://github.com/elysia-best/apm-app-store/commit/61790a85882b6c4ef3ac6b3d60de2f7a7d852025))
* 添加卸载确认模态框,支持卸载进度显示 ([b9325db](https://github.com/elysia-best/apm-app-store/commit/b9325db8b0d3e426d7f2e443069a4641aab7d581))
* **preload:** expose architecture detection to renderer process ([5b09dfb](https://github.com/elysia-best/apm-app-store/commit/5b09dfb3d985a0fd6dcd222e33312f957c330cd5))
### Performance Improvements
* 移除模态框背景模糊效果 ([eaa2868](https://github.com/elysia-best/apm-app-store/commit/eaa28686a36dd7c5942e227ba30e4ffae249fa2f))
## [1.0.2](https://github.com/elysia-best/apm-app-store/compare/9b17c57c5cb6ef6848fdc83f37d1b4d317e2b9a1...v1.0.2) (2026-01-30)
### Bug Fixes
* 更新构建依赖,添加构建工具支持 ([bc2f791](https://github.com/elysia-best/apm-app-store/commit/bc2f79114c700dc98426379703383873908f8f21))
* 更新构建依赖,添加python3支持 ([f8f163e](https://github.com/elysia-best/apm-app-store/commit/f8f163e3b87ea0dae7e3af0645ae4620c468479b))
* 更新构建依赖,移除不必要的包并优化安装命令 ([1c791cd](https://github.com/elysia-best/apm-app-store/commit/1c791cd3c83ebc51db8348c6ebce8b4d4eff42d9))
* 更新上传工件路径以支持不同包类型 ([9ee8339](https://github.com/elysia-best/apm-app-store/commit/9ee8339577ee93f5c7c47be119a6275379321bfe))
* 更新应用图标格式为ICNS,优化安装管理器命令执行 ([4b49424](https://github.com/elysia-best/apm-app-store/commit/4b49424105451eceb6653fd2974fad7021a4b2cd))
* 更新应用ID和版本信息,修复许可证类型 ([a3d50e0](https://github.com/elysia-best/apm-app-store/commit/a3d50e026aa570cd2a49da0acd604f4db682bd72))
* 更新vite版本至6.4.1 ([51ee401](https://github.com/elysia-best/apm-app-store/commit/51ee4019d969767f313cd8af23ea1f0e310b3f4b))
* 将依赖项'apm'更改为'amber-package-manager' ([f7eedcd](https://github.com/elysia-best/apm-app-store/commit/f7eedcd4fd3a073dd1b2c5623c9fe12bb43b43a1))
### Features
* 统一安装和卸载脚本以支持PolicyKit权限配置 ([f15fb28](https://github.com/elysia-best/apm-app-store/commit/f15fb28d80c481a40d768c12cb5f28a4daa6a5a6))
* 更新窗口标题和尺寸,优化按钮样式 ([185b498](https://github.com/elysia-best/apm-app-store/commit/185b4984c60a3b5049d44d8e8dc4ff45384b9000))
* 更新TODO列表,添加应用更新和显示已安装应用功能 ([402ba1f](https://github.com/elysia-best/apm-app-store/commit/402ba1fb00d81828f6c228fb1012203861629fab))
* 添加对deb和rpm包的构建支持,更新构建依赖和版本信息 ([640e0bd](https://github.com/elysia-best/apm-app-store/commit/640e0bd69df90e278803a14e30aa50c99123db95))
* 添加已安装应用和可更新应用的管理功能,支持卸载和升级操作 ([ea0261a](https://github.com/elysia-best/apm-app-store/commit/ea0261a1923fbc692ab0480374f7232759446dc7))
* 添加deb和rpm包的依赖项配置 ([847bcc7](https://github.com/elysia-best/apm-app-store/commit/847bcc7885708a3a2c83f78a951ac3608fc6356c))
* 添加electron-builder.yml配置文件并更新构建脚本 ([38a4d45](https://github.com/elysia-best/apm-app-store/commit/38a4d4512f3c634e923192f01bbcbd2cc0687634))
* 添加PolicyKit权限配置和安装/卸载脚本 ([071aa36](https://github.com/elysia-best/apm-app-store/commit/071aa36fb417478d79db0f0e62aebefe573a699a))
* **deeplink:** implement custom deep link handling and remove electron-app-universal-protocol-client ([c7b3257](https://github.com/elysia-best/apm-app-store/commit/c7b3257a2cefade75a6bc5a82313b38d9acc5d06))
* **download:** 支持重试下载功能并更新相关逻辑 ([bdf51a1](https://github.com/elysia-best/apm-app-store/commit/bdf51a1037822d117a84a1b2914d6c3c39387d57))
* **install:** 实现安装管理器,支持安装、检查已安装状态和初步卸载功能 ([bf93059](https://github.com/elysia-best/apm-app-store/commit/bf93059da177c2403c2c6f5b31b8855220d032b2))
* **install:** add app uninstall functionality ([ac0dc22](https://github.com/elysia-best/apm-app-store/commit/ac0dc225bcd8e202489a0b733449a3d8071a4a60))
* **install:** added basis install process ([50fb1a0](https://github.com/elysia-best/apm-app-store/commit/50fb1a00658119191a35e98413c13b39d5e5699e))
* overhaul application to APM 应用商店 with enhanced download management ([9b17c57](https://github.com/elysia-best/apm-app-store/commit/9b17c57c5cb6ef6848fdc83f37d1b4d317e2b9a1))
+247
View File
@@ -0,0 +1,247 @@
# 贡献指南
感谢您对 APM 应用商店项目的关注!我们欢迎任何形式的贡献。
## 📋 目录
- [行为准则](#行为准则)
- [如何贡献](#如何贡献)
- [开发流程](#开发流程)
- [代码规范](#代码规范)
- [提交信息规范](#提交信息规范)
- [Pull Request 流程](#pull-request-流程)
- [问题报告](#问题报告)
## 行为准则
- 尊重所有贡献者
- 接受建设性批评
- 专注于对项目最有利的事情
- 对社区表现出同理心
## 如何贡献
### 报告 Bug
1. 使用 [Bug 报告模板](.github/ISSUE_TEMPLATE/bug_report.md)
2. 搜索现有 Issue,避免重复
3. 提供清晰的重现步骤
4. 包含相关日志和截图
### 建议新功能
1. 使用 [功能请求模板](.github/ISSUE_TEMPLATE/help_wanted.md)
2. 解释使用场景和需求
3. 考虑是否值得投入开发资源
4. 愿意帮助实现吗?
### 提交代码
1. Fork 项目并创建分支
2. 编写代码和测试
3. 确保所有测试通过
4. 提交 Pull Request
### 改进文档
- 修正错误或不清晰之处
- 添加示例和教程
- 翻译文档
- 提出文档改进建议
## 开发流程
### 环境搭建
```bash
# 克隆仓库
git clone https://github.com/elysia-best/apm-app-store.git
cd apm-app-store
# 安装依赖
npm install
# 启动开发服务器
npm run dev
```
### 创建分支
```bash
# 功能分支
git checkout -b feature/your-feature-name
# Bug 修复分支
git checkout -b fix/your-bug-fix
```
### 本地开发
1. 遵循 [代码规范](#代码规范)
2. 编写 [单元测试](TESTING.md)
3. 运行 `npm run lint``npm run format`
4. 运行 `npm run test` 确保测试通过
### 代码审查
- 保持 PR 小而聚焦
- 添加清晰的描述
- 引用相关的 Issue
- 回应审查意见
## 代码规范
### TypeScript
- 使用严格模式 (`strict: true`)
- 避免使用 `any` 类型(必要时使用 `eslint-disable` 注释)
- 使用显式类型注解
- 优先使用 `interface` 而非 `type`
### Vue 3
- 使用 Composition API 和 `<script setup>`
- 使用 `ref``computed` 管理状态
- 遵循 Props 和 Events 模式
- 组件名使用 PascalCase
### 样式(Tailwind CSS
- 优先使用 Tailwind 工具类
- 支持暗色模式(`dark:` 前缀)
- 响应式设计(`md:`, `lg:` 前缀)
### 命名约定
- **组件:** PascalCase (`AppCard.vue`)
- **函数:** camelCase (`handleInstall`)
- **常量:** UPPER_SNAKE_CASE (`SHELL_CALLER_PATH`)
- **文件:** kebab-case (`install-manager.ts`)
## 提交信息规范
遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范。
### 格式
```
type(scope): subject
[可选的正文]
[可选的脚注]
```
### Type 类型
- `feat`: 新功能
- `fix`: Bug 修复
- `docs`: 文档更新
- `style`: 代码格式(不影响功能)
- `refactor`: 重构
- `perf`: 性能优化
- `test`: 测试相关
- `chore`: 构建/工具相关
### Scope 范围
- `app`: 应用核心
- `install`: 安装/卸载
- `ui`: UI 组件
- `ipc`: IPC 通信
- `api`: API 集成
- `theme`: 主题
- `build`: 构建
- `docs`: 文档
### Subject 主题
- 使用现在时态("add" 而非 "added"
- 首字母小写
- 不以句号结尾
### 示例
```bash
feat(install): add retry mechanism for failed installations
fix(ui): correct dark mode toggle persistence
refactor(ipc): simplify install manager event handling
docs(readme): update build instructions
test(download): add unit tests for download queue
```
### 签名(可选)
添加签名以遵守 DCODeveloper Certificate of Origin):
```bash
git commit -m "feat(example): add new feature" -s
```
或在 `~/.gitconfig` 中配置:
```ini
[commit]
gpgsign = true
```
## Pull Request 流程
### PR 前检查
- [ ] 代码通过 `npm run lint`
- [ ] 代码通过 `npm run format`
- [ ] 所有测试通过 (`npm run test`)
- [ ] 新功能包含测试
- [ ] 文档已更新(如需要)
### PR 描述
使用 [PR 模板](.github/PULL_REQUEST_TEMPLATE.md),包括:
1. **变更类型:** feat / fix / refactor 等
2. **变更描述:** 清晰说明做了什么
3. **相关 Issue:** 引用 `#123`
4. **测试说明:** 如何测试这些变更
5. **截图/录屏:** UI 变更需要
6. **检查清单:** 完成上述 PR 前检查
### 审查流程
1. 至少一位维护者审查通过
2. 解决所有审查意见
3. 确保所有 CI 检查通过
4. Squash 并合并到 main 分支
### 合并要求
- CI 检查全部通过
- 至少一次审查批准
- 无冲突
- 分支最新
## 问题报告
### Bug 报告
使用 [Bug 报告模板](.github/ISSUE_TEMPLATE/bug_report.md),包含:
- 描述
- 复现步骤
- 期望行为
- 实际行为
- 环境信息
- 截图/日志
### 功能请求
使用 [功能请求模板](.github/ISSUE_TEMPLATE/help_wanted.md),包含:
- 问题描述
- 期望的解决方案
- 替代方案
- 额外上下文
---
**© 2026 APM 应用商店项目**
+45
View File
@@ -0,0 +1,45 @@
# List of referenced projects
1. https://github.com/electron-vite/electron-vite-vue MIT License
MIT License
Copyright (c) 2023 草鞋没号
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2. https://github.com/elysia-best/apm-app-store MulanPSL-2.0
Copyright (c) 2026-present The Spark Project Contributors
apm-store is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
+156
View File
@@ -0,0 +1,156 @@
# 部署文档
## 📋 目录
- [构建配置](#构建配置)
- [打包流程](#打包流程)
- [发布流程](#发布流程)
- [CI/CD 工作流](#cicd-工作流)
- [版本管理](#版本管理)
## 构建配置
### electron-builder.yml
主要配置项:
- **appId:** `store.spark-app.apm`
- **productName:** `spark-store`
- **打包格式:** deb, rpm, AppImage
- **输出目录:** `release/${version}`
### 环境变量
| 变量 | 说明 |
| --------------------- | ------------------------ |
| `GITHUB_TOKEN` | GitHub Token(用于发布) |
| `VITE_DEV_SERVER_URL` | 开发服务器地址 |
## 打包流程
### 本地构建
```bash
# 构建所有格式
npm run build
# 仅构建 deb
npm run build:deb
# 仅构建 rpm
npm run build:rpm
# 仅构建前端(不打包)
npm run build:vite
```
### 构建产物
构建完成后,产物位于:
```
release/
└── {version}/
├── spark-store_{version}_linux_amd64.deb
├── spark-store_{version}_linux_amd64.rpm
├── spark-store_{version}_linux_arm64.deb
└── spark-store_{version}_linux_arm64.rpm
```
## 发布流程
### 1. 更新版本号
```bash
# 更新 package.json 中的版本
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
```
### 2. 更新 CHANGELOG.md
```bash
# 生成变更日志
npm run changelog
```
### 3. 提交并推送
```bash
git add .
git commit -m "chore(release): bump version to x.x.x" -s
git push origin main
```
### 4. 创建 Git 标签
```bash
git tag v{version}
git push origin v{version}
```
### 5. 触发 CI 构建
推送标签后会自动触发 GitHub Actions 构建。
### 6. 检查构建结果
在 GitHub Actions 页面查看构建状态。
### 7. 发布到 GitHub Release
构建成功后,GitHub Actions 会自动创建 Release 并上传构建产物。
## CI/CD 工作流
### test.yml
每次推送或 PR 时运行:
- 单元测试
- E2E 测试
- Lint 检查
### build.yml
推送到 main 分支或标签时运行:
- 运行测试(前置依赖)
- 构建 deb 和 rpm 包
- 支持 x64 和 arm64 架构
- 标签推送时自动创建 Release
## 版本管理
### 语义化版本
遵循 [Semantic Versioning](https://semver.org/)
- **MAJOR:** 不兼容的 API 变更
- **MINOR:** 向后兼容的功能新增
- **PATCH:** 向后兼容的 Bug 修复
### 版本号示例
```
4.9.9
│ └─ PATCH (Bug 修复)
│ └─ MINOR (新功能)
└───── MAJOR (重大变更)
```
### 发布流程检查清单
- [ ] 版本号已更新
- [ ] CHANGELOG.md 已更新
- [ ] 所有测试通过
- [ ] 代码已审查
- [ ] Lint 检查通过
- [ ] 构建成功
- [ ] Release 已创建
- [ ] 构建产物已上传
---
**© 2026 APM 应用商店项目**
+380
View File
@@ -0,0 +1,380 @@
# 开发文档
## 📋 目录
- [环境搭建](#环境搭建)
- [项目结构详解](#项目结构详解)
- [开发工作流](#开发工作流)
- [调试技巧](#调试技巧)
- [本地开发最佳实践](#本地开发最佳实践)
## 环境搭建
### 系统要求
- **Node.js:** >= 22.12.0
- **npm:** >= 9.x 或 pnpm >= 8.x
- **操作系统:** Linux(推荐 Ubuntu 22.04+
- **可选:** APM 包管理器(用于测试)
### 安装依赖
```bash
# 克隆仓库
git clone https://github.com/elysia-best/apm-app-store.git
cd apm-app-store
# 安装依赖
npm install
# 或使用 pnpm
pnpm install
```
### 开发服务器启动
```bash
# 启动开发模式
npm run dev
# 应用将在以下地址启动
# Vite 开发服务器: http://127.0.0.1:3344/
# Electron 窗口将自动打开
```
### 构建项目
```bash
# 构建生产版本(deb + rpm
npm run build
# 仅构建前端
npm run build:vite
# 仅构建 deb 包
npm run build:deb
# 仅构建 rpm 包
npm run build:rpm
```
## 项目结构详解
### Electron 主进程
**目录:** `electron/main/`
**核心文件:**
- **`index.ts`** - 主进程入口
- 创建应用窗口
- 管理 IPC 通信
- 处理生命周期事件
- **`backend/install-manager.ts`** - 安装管理器
- 管理安装任务队列
- 执行 APM 命令
- 流式输出日志
- 解析安装结果
- **`deeplink.ts`** - Deep Link 处理
- 解析 `spk://` 协议
- 路由到对应操作
### Vue 渲染进程
**目录:** `src/`
**核心模块:**
- **`App.vue`** - 根组件
- 应用状态管理
- 分类和应用加载
- 模态框协调
- Deep Link 监听
- **`components/`** - UI 组件
- `AppCard.vue` - 应用卡片
- `AppDetailModal.vue` - 应用详情
- `DownloadQueue.vue` - 下载队列
- 其他 11 个组件
- **`global/`** - 全局状态
- `downloadStatus.ts` - 下载队列
- `storeConfig.ts` - API 配置
- `typedefinition.ts` - 类型定义
- **`modules/`** - 业务逻辑
- `processInstall.ts` - 安装/卸载
### 共享模块
**目录:** `electron/global.ts`
- 进程间共享的常量和配置
- 系统架构检测
### 配置文件
- **`vite.config.ts`** - Vite 构建配置
- **`electron-builder.yml`** - 打包配置
- **`tsconfig.json`** - TypeScript 配置
- **`eslint.config.ts`** - ESLint 配置
## 开发工作流
### 功能开发流程
1. **需求分析**
- 理解功能需求
- 设计 API 和数据结构
- 确定影响范围
2. **创建分支**
```bash
git checkout -b feature/your-feature
```
3. **实现功能**
- 更新类型定义 (`src/global/typedefinition.ts`)
- 实现 Vue 组件
- 添加 IPC 处理(如需要)
- 编写测试
4. **测试**
```bash
npm run test
npm run test:e2e
```
5. **代码检查**
```bash
npm run lint
npm run format
```
6. **提交 PR**
- 使用 `feat(scope): description` 格式
- 引用相关 Issue
- 添加详细描述
### Bug 修复流程
1. **复现 Bug**
- 确认 Bug 存在
- 添加复现步骤到 Issue
2. **定位问题**
- 查看日志
- 使用调试器
- 检查相关代码
3. **创建分支**
```bash
git checkout -b fix/your-bug-fix
```
4. **修复代码**
- 最小化修改
- 添加回归测试
- 更新文档(如需要)
5. **验证修复**
- 本地测试
- 确保测试通过
6. **提交 PR**
- 使用 `fix(scope): description` 格式
- 说明修复方法
### 重构流程
1. **识别需要重构的代码**
- 代码重复
- 复杂度过高
- 性能问题
2. **制定重构计划**
- 不改变外部行为
- 逐步进行
- 保持测试通过
3. **执行重构**
```bash
git checkout -b refactor/your-refactor
```
4. **验证**
- 所有测试通过
- 性能未下降
- 代码可读性提升
## 调试技巧
### 主进程调试
**VS Code 配置:**
创建 `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Electron: Main",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args": ["."],
"outputCapture": "std"
}
]
}
```
**日志调试:**
```typescript
import pino from "pino";
const logger = pino({ name: "module-name" });
logger.info("Application started");
logger.error({ err }, "Failed to load apps");
logger.debug("Debug information");
```
### 渲染进程调试
**使用 Vue DevTools:**
1. 安装 Vue DevTools 浏览器扩展
2. Electron 会自动检测
3. 检查组件树和状态
**控制台日志:**
```typescript
console.log("Debug:", data);
console.error("Error:", error);
console.table(apps);
```
### IPC 通信调试
**主进程:**
```typescript
ipcMain.on("test-channel", (event, data) => {
console.log("Received:", data);
event.sender.send("test-response", { result: "ok" });
});
```
**渲染进程:**
```typescript
window.ipcRenderer.send("test-channel", { test: "data" });
window.ipcRenderer.on("test-response", (_event, data) => {
console.log("Response:", data);
});
```
### 性能分析
**Chrome DevTools:**
1. 打开 DevTools (Ctrl+Shift+I)
2. Performance 面板
3. 录制并分析
**Vite 分析:**
```bash
npm run build:vite -- --mode profile
```
## 本地开发最佳实践
### 代码组织
1. **组件拆分**
- 单一职责原则
- 组件不超过 300 行
- 提取可复用逻辑
2. **状态管理**
- 使用 Vue 响应式系统
- 全局状态放在 `src/global/`
- 组件状态使用 `ref` 和 `computed`
3. **类型定义**
- 所有数据结构都有类型
- 避免 `any` 类型
- 使用 TypeScript 工具类型
### 组件复用
1. **Props 设计**
- 明确的类型定义
- 合理的默认值
- 必填项标注
2. **Events 设计**
- 使用 TypeScript 定义
- 清晰的事件命名
3. **插槽使用**
- 提供灵活的内容布局
- 具名插槽增强可用性
### 错误处理
1. **Try-Catch**
```typescript
try {
await someAsyncOperation();
} catch (error) {
logger.error({ err: error }, "Operation failed");
showErrorToUser(error.message);
}
```
2. **Promise 错误**
```typescript
somePromise()
.then((result) => {
// handle success
})
.catch((error) => {
// handle error
});
```
3. **Vue 错误捕获**
```typescript
onMounted(() => {
window.addEventListener("error", handleError);
});
```
### 性能优化
1. **列表虚拟化**(大数据集)
2. **图片懒加载**
3. **防抖和节流**
4. **计算结果缓存**
---
**© 2026 APM 应用商店项目**
View File
-328
View File
@@ -1,328 +0,0 @@
#### 说明
当前服务器线路列表(项目中包含):
```
https://d.store.deepinos.org.cn/
https://store.deepinos.org.cn/
```
# 星火应用商店文档
# 目录结构
几个目录结构
```
/
/icons 图标文件夹
/tags 首页图标
/tras 多语言翻译
```
主要的文件分析
```js
spark-store.pro Qt工程配置文件
ssinstall 调用包安装器的脚本
icons.qrc 图标资源文件
main.cpp 入口文件
widget.h widget.cpp widget.ui 主要窗口控件
downloadlist.h downloadlist.cpp downloadlist.ui 单个软件的下载安装展示控件
progressload.h progressload.cpp 网页加载显示 得在deepin上编译运行才能搞清楚
workerthreads.h workerthreads.cpp 应用信息加载线程
image_show.h image_show.cpp 应用页面截图预览控件
big_image.h big_image.cpp 大图查看控件
```
# 使用的开源库及第三方工具
* GDebi 一个 Ubuntu 软件中心的轻量级替代品 https://linux.cn/article-4982-1.html
* libnotify 系统通知 https://developer.gnome.org/libnotify/unstable/
# 源码分析
## 应用的组成部分
左侧应用分类菜单
主窗口的下拉菜单
应用列表页面
应用详情页面
应用首页,有几个链接跳转
商店设置页面
下载列表页面
## 应用初始化,及主控件加载
初始化 `DApplication` 进入事件循环。
设置关于我们弹窗 `DAboutDialog`
主控件 Widget 根据不同屏幕大小自适应。
首页打开webview页面,如果传入了`spk://`参数,会打开应用详情页。
```cpp
// main.cpp
QString arg1=argv[1];
if(arg1.left(6)=="spk://"){
w.openUrl(QUrl(argv[1]));
}
// widget.cpp
void Widget::openUrl(QUrl u)
{
QString app=serverUrl + "store"+u.path()+"/app.json";
ui->webEngineView->setUrl(app); // 会触发 webEngineView 的
}
```
## Tags处理方式
**Tags处理方式**
```cpp
// widget.cpp
QString tags=json["Tags"].toString(); //Read the Tags
QStringList tagList=tags.split(";");
for (int i=0;i<tagList.size();i++) {
if(tagList[i]=="community")
ui->tag_community->show();//Tags icon shows like this
if(tagList[i]=="ubuntu")
ui->tag_ubuntu->show();
if(tagList[i]=="deepin")
ui->tag_deepin->show();
if(tagList[i]=="uos")
ui->tag_uos->show();
if(tagList[i]=="dtk5")
ui->tag_dtk5->show();
if(tagList[i]=="dwine2")
ui->tag_dwine2->show();
if(tagList[i]=="dwine5")
ui->tag_dwine5->show();
if(tagList[i]=="a2d")
ui->tag_a2d->show();
}
```
**Widget 初始化**
```cpp
void Widget::initConfig()
{
...
// 读取服务器URL并初始化菜单项的链接
QSettings readConfig(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat);
if(readConfig.value("server/choose").toString()!=""){
ui->comboBox_server->setCurrentText(readConfig.value("server/choose").toString());
appinfoLoadThread.setServer(serverUrl=readConfig.value("server/choose").toString());
}else {
appinfoLoadThread.setServer(serverUrl="http://sucdn.jerrywang.top/"); // 默认URL
}
configCanSave=true; // 防止触发保存配置信号
menuUrl[0]=serverUrl + "store/#/"; // 首页
// 下面是各个应用分类页面,直接加载的webview的
// 每个连接对应一个左侧的菜单项,在构造函数用连接到 chooseLeftMenu 槽函数
menuUrl[1]=serverUrl + "store/#/network";
...
menuUrl[12]=serverUrl + "store/#/others";
...
ui->webfoot->hide();
//初始化首页
ui->webEngineView->setUrl(menuUrl[0]);
}
/**
* 菜单切换逻辑
*
*/
void Widget::chooseLeftMenu(int index)
{
nowMenu=index;
updateUI();
left_list[index]->setStyleSheet("color:#FFFFFF;background-color:"+main_color.name()+";border-radius:8;border:0px");
// index <=12 加载某个分类的应用列表的webviejw
// index == 13 加载下载列表页面
if(index<=12){
if(themeIsDark){
darkurl = URL
ui->webEngineView->setUrl(darkurl);
}else {
ui->webEngineView->setUrl(menuUrl[index]);
}
ui->stackedWidget->setCurrentIndex(0);
}else if (index==13) {
ui->stackedWidget->setCurrentIndex(1);
}
}
```
## 应用下载安装卸载分析
**应用详情页面加载**
```cpp
/**
* 加载单个应用的信息
*/
void Widget::on_webEngineView_urlChanged(const QUrl &arg1)
{
//分析出服务器中的分类名称
...
//如果是app.json就打开详情页
if(arg1.path().right(8)=="app.json"){
...
// 读取相应的应用信息
appinfoLoadThread.requestInterruption();
appinfoLoadThread.wait(100);
appinfoLoadThread.setUrl(arg1);
appinfoLoadThread.start();
}
}
// 设置详情页的APP信息
SpkAppInfoLoaderThread::requestSetAppInformation() -> Widget::sltAppinfoDetails()
// 设置详情页的APP图标
SpkAppInfoLoaderThread::finishedIconLoad() -> Widget::sltAppinfoIcon()
// 设置详情页的APP截图
SpkAppInfoLoaderThread::finishedScreenshotLoad() -> Widget::sltAppinfoScreenshot()
// 下载APP详情信息线程
void SpkAppInfoLoaderThread::run()
{
QProcess get_json;
get_json.start("curl -o app.json " + targetUrl.toString());
QFile app_json("app.json");
app.json
}
```
**应用下载**
Widget::on_pushButton_download_clicked() 是点击下载的安装方法。
最终使用的是 `QNetwrokAccessManager` 进行GET请求获取数据写入文件。
```cpp
void Widget::on_pushButton_download_clicked()
{
if(!isBusy){
file = new QFile(fileName);
...
nowDownload+=1;
startRequest(urList.at(nowDownload-1)); // 进行链接请求
}
}
void Widget::startRequest(QUrl url)
{
reply = manager->get(QNetworkRequest(url));
// 请求响应完成,关闭文件,清理下载队列
connect(reply,SIGNAL(finished()),this,SLOT(httpFinished()));
// 接收应用下载数据
connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead()));
// 更新应用下载进度
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateDataReadProgress(qint64,qint64)));
}
```
使用 QSettings 来读取配置,更换服务源
```cpp
void Widget::on_comboBox_server_currentIndexChanged(const QString &arg1)
{
appinfoLoadThread.setServer(arg1); // 服务器信息更新
if(configCanSave){
ui->label_setting1->show();
QSettings *setConfig=new QSettings(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat);
setConfig->setValue("server/choose",arg1);
}
}
```
使用 `QProcess` 来调用各种小文件下载、包安装卸载的命令。
**应用安装**
```cpp
void Widget::httpFinished() // 完成下载
{
...
download_list[nowDownload-1].readyInstall();
download_list[nowDownload-1].free=true;
if(nowDownload<allDownload){ // 如果有排队则下载下一个
...
}
}
void downloadlist::readyInstall()
{
...
ui->pushButton_install->setEnabled(true);
ui->pushButton_install->show();
ui->pushButton_2->hide();
Widget::sendNotification(tr("Finished downloading %1, awaiting to install").arg(ui->label->text()), 5000,
"/tmp/spark-store/icon_"+QString::number(num).toUtf8()+".png");
}
void downloadlist::on_pushButton_install_clicked()
{
//弹出菜单
menu_install->exec(cursor().pos());
}
downloadlist menu_install
downloadlist::install()
gdebi, dpkg, deepin-deb-installer
void downloadlist::install(int t)
{
QtConcurrent::run([=](){
QProcess installer;
installer.start("pkexec gdebi -n /tmp/spark-store/"+ui->label_filename->text().toUtf8());
installer.start("pkexec ssinstall /tmp/spark-store/"+ui->label_filename->text().toUtf8());
installer.start("deepin-deb-installer /tmp/spark-store/"+ui->label_filename->text().toUtf8());
});
}
```
**应用卸载**
```cpp
void Widget::on_pushButton_uninstall_clicked()
{
QtConcurrent::run([=](){
uninstall.start("pkexec apt purge -y "+pkgName);
});
}
```
**仓库源更新**
```cpp
// 更新源列表
void Widget::on_pushButton_updateServer_clicked()
{
QtConcurrent::run([=](){
...
QFile::remove(QDir::homePath().toUtf8()+"/.config/spark-store/server.list");
system("curl -o "+QDir::homePath().toUtf8()+"/.config/spark-store/server.list http://dcstore.shenmo.tech/store/server.list");
server.open(QDir::homePath().toUtf8()+"/.config/spark-store/server.list",std::ios::in);
...
while (getline(server,lineTmp)) {
ui->comboBox_server->addItem(QString::fromStdString(lineTmp));
}
});
}
// 更新星火商店apt源
void Widget::on_pushButton_updateApt_clicked()
{
QtConcurrent::run([=](){
comboBox_server /tmp/spark-store/sparkstore.list
bash脚本 sparkstore.list /etc/apt/sources.list.d/
使QProcess pkexec update.sh
}):
}
```
## 发送系统通知
```cpp
#include <libnotify/notify.h>
static NotifyNotification *_notify = nullptr; // 初始化
notify_init(tr("Spark\\ Store").toLocal8Bit()); // 构造函数初始化
notify_uninit(); // 析构函数调用
void Widget::sendNotification(const QString &message, const int msTimeout, const QString &icon)
{
if(_notify == nullptr)
{
_notify = notify_notification_new(tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit());
notify_notification_set_timeout(_notify, msTimeout);
}
else
notify_notification_update(_notify, tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit());
notify_notification_show(_notify, nullptr);
}
```
-25
View File
@@ -1,25 +0,0 @@
#### 调用参数(spk规则)
参数只有一个Url,该url应当遵循这种格式:`spk://<任意合法字符>/web分类/包名`
例如:
[spk://abcdefg/games/store.spark-app.hmcl](spk://abcdefg/games/store.spark-app.hmcl)
可选的web分类:
| 分类名称 | web分类   |
| -------- | -------------- |
| 网络应用 | network |
| 社交沟通 | chat |
| 音乐欣赏 | music |
| 视频播放 | video |
| 图形图像 | graphics |
| 游戏娱乐 | games |
| 办公学习 | office |
| 阅读翻译 | reading |
| 编程开发 | development |
| 系统工具 | tools |
| 主题美化 | beautify |
| 其他应用 | others |
+154
View File
@@ -0,0 +1,154 @@
# 常见问题 (FAQ)
## 基本问题
### Q: APM 应用商店是什么?
**A:** APM 应用商店是基于 Electron + Vue 3 构建的桌面应用商店客户端,用于 APM (AmberPM) 包管理器的图形化界面。
### Q: 支持哪些操作系统?
**A:** 目前支持 Linux 系统,包括但不限于:
- Ubuntu 20.04+
- Debian 11+
- Fedora 35+
- Arch Linux
- 银河麒麟
- 统信 UOS
### Q: 如何安装 APM 应用商店?
**A:**
1. 从 GitHub Releases 下载 deb 或 rpm 包
2. 使用包管理器安装:
```bash
# Debian/Ubuntu
sudo dpkg -i spark-store_*.deb
# Fedora/RHEL
sudo dnf install spark-store_*.rpm
```
### Q: 需要 APM 包管理器吗?
**A:** 是的,APM 应用商店需要 APM 包管理器才能工作。请先安装 APM。
## 使用问题
### Q: 如何安装应用?
**A:**
1. 打开 APM 应用商店
2. 浏览或搜索应用
3. 点击应用卡片查看详情
4. 点击"安装"按钮
5. 等待安装完成
### Q: 如何卸载应用?
**A:**
1. 点击右上角"已安装"按钮
2. 在列表中找到要卸载的应用
3. 点击"卸载"按钮
4. 确认卸载
### Q: 如何更新应用?
**A:**
1. 点击右上角"更新"按钮
2. 选择要更新的应用
3. 点击"更新"按钮
4. 等待更新完成
### Q: 下载的应用在哪里?
**A:**
应用下载后存储在 APM 管理的目录中,通常位于:
```
/opt/spark-store/apps/{pkgname}/
```
## 技术问题
### Q: 应用无法启动怎么办?
**A:** 请参考 [问题排查指南](TROUBLESHOOTING.md)。
### Q: 如何查看日志?
**A:**
日志位置:
- 主进程日志:`~/.config/spark-store/logs/`
- 系统日志:`journalctl -u spark-store`
### Q: 如何切换主题?
**A:**
点击右上角主题切换按钮,或按 `Ctrl+Shift+T`。
### Q: 支持深色模式吗?
**A:** 是的,支持亮色、暗色和跟随系统主题。
## 开发问题
### Q: 如何参与开发?
**A:** 请参考 [贡献指南](CONTRIBUTING.md)。
### Q: 如何运行开发版本?
**A:**
```bash
git clone https://github.com/elysia-best/apm-app-store.git
cd apm-app-store
npm install
npm run dev
```
### Q: 技术栈是什么?
**A:**
- Electron 40.0.0
- Vue 3
- Vite 6.4.1
- TypeScript
- Tailwind CSS 4.1.18
### Q: 如何报告 Bug
**A:**
请在 [GitHub Issues](https://github.com/elysia-best/apm-app-store/issues) 提交 Bug 报告。
## 其他问题
### Q: 可以在 Windows/Mac 上使用吗?
**A:** 目前不支持,但计划在未来添加跨平台支持。
### Q: 如何获取帮助?
**A:**
- 查看 [文档](README.md)
- 提交 [Issue](https://github.com/elysia-best/apm-app-store/issues)
- 加入 [社区论坛](https://bbs.spark-app.store/)
### Q: 许可证是什么?
**A:**
本项目采用 [GPL-3.0](LICENSE.md) 协议开源。
---
**© 2026 APM 应用商店项目**
Vendored
-33
View File
@@ -1,33 +0,0 @@
pipeline {
agent any
stages {
stage('build') {
agent {
docker {
image 'jerry979/dtke:5.11.1'
}
}
steps {
sh 'mkdir build && cd build && qmake .. && make '
archiveArtifacts(artifacts: 'build/src/spark-store', allowEmptyArchive: true, defaultExcludes: true)
}
}
stage('send') {
agent {
dockerfile {
filename '.gitee/Dockerfile'
}
}
environment {
gitee_token = credentials('1')
}
steps {
sh "python3 .gitee/callback.py"
}
}
}
}
+636
View File
@@ -0,0 +1,636 @@
# GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 [Free Software Foundation, Inc.](http://fsf.org/)
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
## Preamble
The GNU General Public License is a free, copyleft license for software and
other kinds of works.
The licenses for most software and other practical works are designed to take
away your freedom to share and change the works. By contrast, the GNU General
Public License is intended to guarantee your freedom to share and change all
versions of a program--to make sure it remains free software for all its users.
We, the Free Software Foundation, use the GNU General Public License for most
of our software; it applies also to any other work released this way by its
authors. You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom to
distribute copies of free software (and charge for them if you wish), that you
receive source code or can get it if you want it, that you can change the
software or use pieces of it in new free programs, and that you know you can do
these things.
To protect your rights, we need to prevent others from denying you these rights
or asking you to surrender the rights. Therefore, you have certain
responsibilities if you distribute copies of the software, or if you modify it:
responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for
a fee, you must pass on to the recipients the same freedoms that you received.
You must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps:
1. assert copyright on the software, and
2. offer you this License giving you legal permission to copy, distribute
and/or modify it.
For the developers' and authors' protection, the GPL clearly explains that
there is no warranty for this free software. For both users' and authors' sake,
the GPL requires that modified versions be marked as changed, so that their
problems will not be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified
versions of the software inside them, although the manufacturer can do so. This
is fundamentally incompatible with the aim of protecting users' freedom to
change the software. The systematic pattern of such abuse occurs in the area of
products for individuals to use, which is precisely where it is most
unacceptable. Therefore, we have designed this version of the GPL to prohibit
the practice for those products. If such problems arise substantially in other
domains, we stand ready to extend this provision to those domains in future
versions of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents. States
should not allow patents to restrict development and use of software on
general-purpose computers, but in those that do, we wish to avoid the special
danger that patents applied to a free program could make it effectively
proprietary. To prevent this, the GPL assures that patents cannot be used to
render the program non-free.
The precise terms and conditions for copying, distribution and modification
follow.
## TERMS AND CONDITIONS
### 0. Definitions.
*This License* refers to version 3 of the GNU General Public License.
*Copyright* also means copyright-like laws that apply to other kinds of works,
such as semiconductor masks.
*The Program* refers to any copyrightable work licensed under this License.
Each licensee is addressed as *you*. *Licensees* and *recipients* may be
individuals or organizations.
To *modify* a work means to copy from or adapt all or part of the work in a
fashion requiring copyright permission, other than the making of an exact copy.
The resulting work is called a *modified version* of the earlier work or a work
*based on* the earlier work.
A *covered work* means either the unmodified Program or a work based on the
Program.
To *propagate* a work means to do anything with it that, without permission,
would make you directly or secondarily liable for infringement under applicable
copyright law, except executing it on a computer or modifying a private copy.
Propagation includes copying, distribution (with or without modification),
making available to the public, and in some countries other activities as well.
To *convey* a work means any kind of propagation that enables other parties to
make or receive copies. Mere interaction with a user through a computer
network, with no transfer of a copy, is not conveying.
An interactive user interface displays *Appropriate Legal Notices* to the
extent that it includes a convenient and prominently visible feature that
1. displays an appropriate copyright notice, and
2. tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the work
under this License, and how to view a copy of this License.
If the interface presents a list of user commands or options, such as a menu, a
prominent item in the list meets this criterion.
### 1. Source Code.
The *source code* for a work means the preferred form of the work for making
modifications to it. *Object code* means any non-source form of a work.
A *Standard Interface* means an interface that either is an official standard
defined by a recognized standards body, or, in the case of interfaces specified
for a particular programming language, one that is widely used among developers
working in that language.
The *System Libraries* of an executable work include anything, other than the
work as a whole, that (a) is included in the normal form of packaging a Major
Component, but which is not part of that Major Component, and (b) serves only
to enable use of the work with that Major Component, or to implement a Standard
Interface for which an implementation is available to the public in source code
form. A *Major Component*, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system (if any) on
which the executable work runs, or a compiler used to produce the work, or an
object code interpreter used to run it.
The *Corresponding Source* for a work in object code form means all the source
code needed to generate, install, and (for an executable work) run the object
code and to modify the work, including scripts to control those activities.
However, it does not include the work's System Libraries, or general-purpose
tools or generally available free programs which are used unmodified in
performing those activities but which are not part of the work. For example,
Corresponding Source includes interface definition files associated with source
files for the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require, such as
by intimate data communication or control flow between those subprograms and
other parts of the work.
The Corresponding Source need not include anything that users can regenerate
automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
### 2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on
the Program, and are irrevocable provided the stated conditions are met. This
License explicitly affirms your unlimited permission to run the unmodified
Program. The output from running a covered work is covered by this License only
if the output, given its content, constitutes a covered work. This License
acknowledges your rights of fair use or other equivalent, as provided by
copyright law.
You may make, run and propagate covered works that you do not convey, without
conditions so long as your license otherwise remains in force. You may convey
covered works to others for the sole purpose of having them make modifications
exclusively for you, or provide you with facilities for running those works,
provided that you comply with the terms of this License in conveying all
material for which you do not control copyright. Those thus making or running
the covered works for you must do so exclusively on your behalf, under your
direction and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the
conditions stated below. Sublicensing is not allowed; section 10 makes it
unnecessary.
### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure
under any applicable law fulfilling obligations under article 11 of the WIPO
copyright treaty adopted on 20 December 1996, or similar laws prohibiting or
restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention is
effected by exercising rights under this License with respect to the covered
work, and you disclaim any intention to limit operation or modification of the
work as a means of enforcing, against the work's users, your or third parties'
legal rights to forbid circumvention of technological measures.
### 4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it,
in any medium, provided that you conspicuously and appropriately publish on
each copy an appropriate copyright notice; keep intact all notices stating that
this License and any non-permissive terms added in accord with section 7 apply
to the code; keep intact all notices of the absence of any warranty; and give
all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may
offer support or warranty protection for a fee.
### 5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it
from the Program, in the form of source code under the terms of section 4,
provided that you also meet all of these conditions:
- a) The work must carry prominent notices stating that you modified it, and
giving a relevant date.
- b) The work must carry prominent notices stating that it is released under
this License and any conditions added under section 7. This requirement
modifies the requirement in section 4 to *keep intact all notices*.
- c) You must license the entire work, as a whole, under this License to
anyone who comes into possession of a copy. This License will therefore
apply, along with any applicable section 7 additional terms, to the whole
of the work, and all its parts, regardless of how they are packaged. This
License gives no permission to license the work in any other way, but it
does not invalidate such permission if you have separately received it.
- d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your work need
not make them do so.
A compilation of a covered work with other separate and independent works,
which are not by their nature extensions of the covered work, and which are not
combined with it such as to form a larger program, in or on a volume of a
storage or distribution medium, is called an *aggregate* if the compilation and
its resulting copyright are not used to limit the access or legal rights of the
compilation's users beyond what the individual works permit. Inclusion of a
covered work in an aggregate does not cause this License to apply to the other
parts of the aggregate.
### 6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4
and 5, provided that you also convey the machine-readable Corresponding Source
under the terms of this License, in one of these ways:
- a) Convey the object code in, or embodied in, a physical product (including
a physical distribution medium), accompanied by the Corresponding Source
fixed on a durable physical medium customarily used for software
interchange.
- b) Convey the object code in, or embodied in, a physical product (including
a physical distribution medium), accompanied by a written offer, valid for
at least three years and valid for as long as you offer spare parts or
customer support for that product model, to give anyone who possesses the
object code either
1. a copy of the Corresponding Source for all the software in the product
that is covered by this License, on a durable physical medium
customarily used for software interchange, for a price no more than your
reasonable cost of physically performing this conveying of source, or
2. access to copy the Corresponding Source from a network server at no
charge.
- c) Convey individual copies of the object code with a copy of the written
offer to provide the Corresponding Source. This alternative is allowed only
occasionally and noncommercially, and only if you received the object code
with such an offer, in accord with subsection 6b.
- d) Convey the object code by offering access from a designated place
(gratis or for a charge), and offer equivalent access to the Corresponding
Source in the same way through the same place at no further charge. You
need not require recipients to copy the Corresponding Source along with the
object code. If the place to copy the object code is a network server, the
Corresponding Source may be on a different server operated by you or a
third party) that supports equivalent copying facilities, provided you
maintain clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the Corresponding
Source, you remain obligated to ensure that it is available for as long as
needed to satisfy these requirements.
- e) Convey the object code using peer-to-peer transmission, provided you
inform other peers where the object code and Corresponding Source of the
work are being offered to the general public at no charge under subsection
6d.
A separable portion of the object code, whose source code is excluded from the
Corresponding Source as a System Library, need not be included in conveying the
object code work.
A *User Product* is either
1. a *consumer product*, which means any tangible personal property which is
normally used for personal, family, or household purposes, or
2. anything designed or sold for incorporation into a dwelling.
In determining whether a product is a consumer product, doubtful cases shall be
resolved in favor of coverage. For a particular product received by a
particular user, *normally used* refers to a typical or common use of that
class of product, regardless of the status of the particular user or of the way
in which the particular user actually uses, or expects or is expected to use,
the product. A product is a consumer product regardless of whether the product
has substantial commercial, industrial or non-consumer uses, unless such uses
represent the only significant mode of use of the product.
*Installation Information* for a User Product means any methods, procedures,
authorization keys, or other information required to install and execute
modified versions of a covered work in that User Product from a modified
version of its Corresponding Source. The information must suffice to ensure
that the continued functioning of the modified object code is in no case
prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as part of a
transaction in which the right of possession and use of the User Product is
transferred to the recipient in perpetuity or for a fixed term (regardless of
how the transaction is characterized), the Corresponding Source conveyed under
this section must be accompanied by the Installation Information. But this
requirement does not apply if neither you nor any third party retains the
ability to install modified object code on the User Product (for example, the
work has been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates for a
work that has been modified or installed by the recipient, or for the User
Product in which it has been modified or installed. Access to a network may be
denied when the modification itself materially and adversely affects the
operation of the network or violates the rules and protocols for communication
across the network.
Corresponding Source conveyed, and Installation Information provided, in accord
with this section must be in a format that is publicly documented (and with an
implementation available to the public in source code form), and must require
no special password or key for unpacking, reading or copying.
### 7. Additional Terms.
*Additional permissions* are terms that supplement the terms of this License by
making exceptions from one or more of its conditions. Additional permissions
that are applicable to the entire Program shall be treated as though they were
included in this License, to the extent that they are valid under applicable
law. If additional permissions apply only to part of the Program, that part may
be used separately under those permissions, but the entire Program remains
governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any
additional permissions from that copy, or from any part of it. (Additional
permissions may be written to require their own removal in certain cases when
you modify the work.) You may place additional permissions on material, added
by you to a covered work, for which you have or can give appropriate copyright
permission.
Notwithstanding any other provision of this License, for material you add to a
covered work, you may (if authorized by the copyright holders of that material)
supplement the terms of this License with terms:
- a) Disclaiming warranty or limiting liability differently from the terms of
sections 15 and 16 of this License; or
- b) Requiring preservation of specified reasonable legal notices or author
attributions in that material or in the Appropriate Legal Notices displayed
by works containing it; or
- c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in reasonable
ways as different from the original version; or
- d) Limiting the use for publicity purposes of names of licensors or authors
of the material; or
- e) Declining to grant rights under trademark law for use of some trade
names, trademarks, or service marks; or
- f) Requiring indemnification of licensors and authors of that material by
anyone who conveys the material (or modified versions of it) with
contractual assumptions of liability to the recipient, for any liability
that these contractual assumptions directly impose on those licensors and
authors.
All other non-permissive additional terms are considered *further restrictions*
within the meaning of section 10. If the Program as you received it, or any
part of it, contains a notice stating that it is governed by this License along
with a term that is a further restriction, you may remove that term. If a
license document contains a further restriction but permits relicensing or
conveying under this License, you may add to a covered work material governed
by the terms of that license document, provided that the further restriction
does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place,
in the relevant source files, a statement of the additional terms that apply to
those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a
separately written license, or stated as exceptions; the above requirements
apply either way.
### 8. Termination.
You may not propagate or modify a covered work except as expressly provided
under this License. Any attempt otherwise to propagate or modify it is void,
and will automatically terminate your rights under this License (including any
patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a
particular copyright holder is reinstated
- a) provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and
- b) permanently, if the copyright holder fails to notify you of the
violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated
permanently if the copyright holder notifies you of the violation by some
reasonable means, this is the first time you have received notice of violation
of this License (for any work) from that copyright holder, and you cure the
violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses
of parties who have received copies or rights from you under this License. If
your rights have been terminated and not permanently reinstated, you do not
qualify to receive new licenses for the same material under section 10.
### 9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy
of the Program. Ancillary propagation of a covered work occurring solely as a
consequence of using peer-to-peer transmission to receive a copy likewise does
not require acceptance. However, nothing other than this License grants you
permission to propagate or modify any covered work. These actions infringe
copyright if you do not accept this License. Therefore, by modifying or
propagating a covered work, you indicate your acceptance of this License to do
so.
### 10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a
license from the original licensors, to run, modify and propagate that work,
subject to this License. You are not responsible for enforcing compliance by
third parties with this License.
An *entity transaction* is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered work
results from an entity transaction, each party to that transaction who receives
a copy of the work also receives whatever licenses to the work the party's
predecessor in interest had or could give under the previous paragraph, plus a
right to possession of the Corresponding Source of the work from the
predecessor in interest, if the predecessor has it or can get it with
reasonable efforts.
You may not impose any further restrictions on the exercise of the rights
granted or affirmed under this License. For example, you may not impose a
license fee, royalty, or other charge for exercise of rights granted under this
License, and you may not initiate litigation (including a cross-claim or
counterclaim in a lawsuit) alleging that any patent claim is infringed by
making, using, selling, offering for sale, or importing the Program or any
portion of it.
### 11. Patents.
A *contributor* is a copyright holder who authorizes use under this License of
the Program or a work on which the Program is based. The work thus licensed is
called the contributor's *contributor version*.
A contributor's *essential patent claims* are all patent claims owned or
controlled by the contributor, whether already acquired or hereafter acquired,
that would be infringed by some manner, permitted by this License, of making,
using, or selling its contributor version, but do not include claims that would
be infringed only as a consequence of further modification of the contributor
version. For purposes of this definition, *control* includes the right to grant
patent sublicenses in a manner consistent with the requirements of this
License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent
license under the contributor's essential patent claims, to make, use, sell,
offer for sale, import and otherwise run, modify and propagate the contents of
its contributor version.
In the following three paragraphs, a *patent license* is any express agreement
or commitment, however denominated, not to enforce a patent (such as an express
permission to practice a patent or covenant not to sue for patent
infringement). To *grant* such a patent license to a party means to make such
an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the
Corresponding Source of the work is not available for anyone to copy, free of
charge and under the terms of this License, through a publicly available
network server or other readily accessible means, then you must either
1. cause the Corresponding Source to be so available, or
2. arrange to deprive yourself of the benefit of the patent license for this
particular work, or
3. arrange, in a manner consistent with the requirements of this License, to
extend the patent license to downstream recipients.
*Knowingly relying* means you have actual knowledge that, but for the patent
license, your conveying the covered work in a country, or your recipient's use
of the covered work in a country, would infringe one or more identifiable
patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you
convey, or propagate by procuring conveyance of, a covered work, and grant a
patent license to some of the parties receiving the covered work authorizing
them to use, propagate, modify or convey a specific copy of the covered work,
then the patent license you grant is automatically extended to all recipients
of the covered work and works based on it.
A patent license is *discriminatory* if it does not include within the scope of
its coverage, prohibits the exercise of, or is conditioned on the non-exercise
of one or more of the rights that are specifically granted under this License.
You may not convey a covered work if you are a party to an arrangement with a
third party that is in the business of distributing software, under which you
make payment to the third party based on the extent of your activity of
conveying the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory patent
license
- a) in connection with copies of the covered work conveyed by you (or copies
made from those copies), or
- b) primarily for and in connection with specific products or compilations
that contain the covered work, unless you entered into that arrangement, or
that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied
license or other defenses to infringement that may otherwise be available to
you under applicable patent law.
### 12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not excuse
you from the conditions of this License. If you cannot convey a covered work so
as to satisfy simultaneously your obligations under this License and any other
pertinent obligations, then as a consequence you may not convey it at all. For
example, if you agree to terms that obligate you to collect a royalty for
further conveying from those to whom you convey the Program, the only way you
could satisfy both those terms and this License would be to refrain entirely
from conveying the Program.
### 13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to
link or combine any covered work with a work licensed under version 3 of the
GNU Affero General Public License into a single combined work, and to convey
the resulting work. The terms of this License will continue to apply to the
part which is the covered work, but the special requirements of the GNU Affero
General Public License, section 13, concerning interaction through a network
will apply to the combination as such.
### 14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU
General Public License from time to time. Such new versions will be similar in
spirit to the present version, but may differ in detail to address new problems
or concerns.
Each version is given a distinguishing version number. If the Program specifies
that a certain numbered version of the GNU General Public License *or any later
version* applies to it, you have the option of following the terms and
conditions either of that numbered version or of any later version published by
the Free Software Foundation. If the Program does not specify a version number
of the GNU General Public License, you may choose any version ever published by
the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the
GNU General Public License can be used, that proxy's public statement of
acceptance of a version permanently authorizes you to choose that version for
the Program.
Later license versions may give you additional or different permissions.
However, no additional obligations are imposed on any author or copyright
holder as a result of your choosing to follow a later version.
### 15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
PARTIES PROVIDE THE PROGRAM *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
### 16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY
COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
### 17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot
be given local legal effect according to their terms, reviewing courts shall
apply local law that most closely approximates an absolute waiver of all civil
liability in connection with the Program, unless a warranty or assumption of
liability accompanies a copy of the Program in return for a fee.
## END OF TERMS AND CONDITIONS ###
### How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible
use to the public, the best way to achieve this is to make it free software
which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach
them to the start of each source file to most effectively state the exclusion
of warranty; and each file should have at least the *copyright* line and a
pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like
this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w` and `show c` should show the appropriate
parts of the General Public License. Of course, your program's commands might
be different; for a GUI interface, you would use an *about box*.
You should also get your employer (if you work as a programmer) or school, if
any, to sign a *copyright disclaimer* for the program, if necessary. For more
information on this, and how to apply and follow the GNU GPL, see
[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
The GNU General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may consider
it more useful to permit linking proprietary applications with the library. If
this is what you want to do, use the GNU Lesser General Public License instead
of this License. But first, please read
[http://www.gnu.org/philosophy/why-not-lgpl.html](http://www.gnu.org/philosophy/why-not-lgpl.html).
+229
View File
@@ -0,0 +1,229 @@
# 项目整理完成总结
## ✅ 完成的工作
### 1. 核心文档(3个文件)
| 文件 | 状态 | 说明 |
| --------------- | ----------------- | --------------------------- |
| AGENTS.md | ✅ 已替换为中文版 | 完整的 AI 编码指南(894行) |
| CONTRIBUTING.md | ✅ 新建 | 贡献指南(中文) |
| DEVELOPMENT.md | ✅ 新建 | 开发文档(中文) |
### 2. 工作流文档(9个文件)
| 文件 | 说明 |
| --------------------------------------------- | -------------- |
| .agents/workflows/feature-development.md | 新功能开发流程 |
| .agents/workflows/bug-fix.md | Bug 修复流程 |
| .agents/workflows/code-review.md | 代码审查流程 |
| .agents/workflows/testing.md | 测试编写流程 |
| .agents/workflows/release.md | 发布流程 |
| .agents/workflows/refactoring.md | 代码重构流程 |
| .agents/workflows/documentation.md | 文档更新流程 |
| .agents/workflows/performance-optimization.md | 性能优化流程 |
| .agents/workflows/security-audit.md | 安全审计流程 |
**删除的文件:**
- .agents/workflows/1.md
- .agents/workflows/代码审查.md
### 3. 测试基础设施(5个文件)
| 文件 | 说明 |
| ----------------------------------------- | ----------------------- |
| vitest.config.ts | Vitest 单元测试配置 |
| playwright.config.ts | Playwright E2E 测试配置 |
| src/**tests**/setup.ts | 测试环境设置 |
| src/**tests**/unit/downloadStatus.test.ts | 示例单元测试 |
| e2e/basic.spec.ts | 示例 E2E 测试 |
### 4. 测试文档(1个文件)
| 文件 | 说明 |
| ---------- | ---------------------- |
| TESTING.md | 完整的测试文档(中文) |
### 5. CI/CD 集成(2个文件)
| 文件 | 操作 |
| --------------------------- | -------------------- |
| .github/workflows/test.yml | 新建(测试 CI |
| .github/workflows/build.yml | 更新(添加测试步骤) |
### 6. 完善文档(3个文件)
| 文件 | 说明 |
| ------------------ | -------------------- |
| DEPLOYMENT.md | 部署文档(中文) |
| TROUBLESHOOTING.md | 问题排查指南(中文) |
| FAQ.md | 常见问题(中文) |
### 7. Issue 模板更新(2个文件)
| 文件 | 操作 |
| ------------------------------------- | -------------- |
| .github/ISSUE_TEMPLATE/bug_report.md | 更新为标准模板 |
| .github/ISSUE_TEMPLATE/help_wanted.md | 更新为标准模板 |
### 8. 配置更新
| 文件 | 操作 |
| ------------ | ------------------ |
| package.json | 添加测试依赖和脚本 |
| .gitignore | 添加测试相关忽略项 |
## 📊 统计数据
- **创建的文件:** 23个
- **更新的文件:** 3个
- **删除的文件:** 2个
- **总计:** 28个文件操作
## 📝 新增的 npm 脚本
```json
{
"test": "vitest",
"test:watch": "vitest --watch",
"test:coverage": "vitest --coverage",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:debug": "playwright test --debug",
"test:all": "npm run test && npm run test:e2e"
}
```
## 📦 新增的依赖
### Dev Dependencies
- `@playwright/test`: ^1.40.0
- `@testing-library/jest-dom`: ^6.1.5
- `@testing-library/vue`: ^8.0.1
- `@vitest/coverage-v8`: ^1.0.0
- `@vue/test-utils`: ^2.4.3
- `jsdom`: ^23.0.1
- `vitest`: ^1.0.0
## 🔍 已知问题
### LSP 类型错误
由于 Vitest 和 Vite 的版本兼容性问题,LSP 会报告一些类型错误,但这些不会影响实际运行:
- `vitest.config.ts` 中的插件类型不匹配(Vite vs Vitest 版本差异)
- 这些错误在运行时不会出现
### ESLint 错误
项目中有一些现有的 ESLint 错误需要修复:
- `src/App.vue`: 3个 `any` 类型错误
- `src/components/HomeView.vue`: 5个错误(未使用变量、any 类型)
- `src/components/TopActions.vue`: 1个未使用变量
这些是原有代码的问题,不是本次整理引入的。
## 🚀 下一步建议
1. **修复 ESLint 错误**
```bash
npm run lint:fix
```
2. **运行测试验证**
```bash
npm run test
```
3. **安装 Playwright 浏览器**
```bash
npx playwright install --with-deps chromium
```
4. **运行 E2E 测试**
```bash
npm run test:e2e
```
5. **提交代码**
```bash
git add .
git commit -m "chore: add comprehensive documentation and testing infrastructure" -s
git push origin main
```
## 📚 文档结构总览
```
apm-app-store/
├── AGENTS.md # AI 编码指南(中文)
├── CONTRIBUTING.md # 贡献指南(中文)
├── DEVELOPMENT.md # 开发文档(中文)
├── DEPLOYMENT.md # 部署文档(中文)
├── TROUBLESHOOTING.md # 问题排查(中文)
├── FAQ.md # 常见问题(中文)
├── TESTING.md # 测试文档(中文)
├── README.md # 项目说明(已存在)
├── CHANGELOG.md # 变更日志(已存在)
├── SECURITY.md # 安全政策(已存在)
├── LICENSE.md # 许可证(已存在)
├── CREDITS.md # 致谢(已存在)
├── vitest.config.ts # Vitest 配置
├── playwright.config.ts # Playwright 配置
├── .agents/
│ └── workflows/
│ ├── feature-development.md # 新功能开发
│ ├── bug-fix.md # Bug 修复
│ ├── code-review.md # 代码审查
│ ├── testing.md # 测试编写
│ ├── release.md # 发布流程
│ ├── refactoring.md # 代码重构
│ ├── documentation.md # 文档更新
│ ├── performance-optimization.md # 性能优化
│ └── security-audit.md # 安全审计
├── .github/
│ ├── workflows/
│ │ ├── test.yml # 测试 CI(新建)
│ │ └── build.yml # 构建 CI(更新)
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md # Bug 报告模板(更新)
│ └── help_wanted.md # 功能请求模板(更新)
├── src/
│ └── __tests__/
│ ├── setup.ts # 测试设置
│ └── unit/
│ └── downloadStatus.test.ts # 示例测试
└── e2e/
└── basic.spec.ts # E2E 测试示例
```
## 🎯 项目成熟度提升
整理前:
- ❌ 缺少完整的开发文档
- ❌ 缺少测试基础设施
- ❌ 工作流文档简单
- ❌ 没有自动化测试 CI
整理后:
- ✅ 完整的中文开发文档
- ✅ 完整的测试基础设施(Vitest + Playwright
- ✅ 9个详细的 AI 工作流
- ✅ 自动化测试 CI/CD
- ✅ 标准化的 Issue 模板
- ✅ 完善的部署和问题排查文档
---
**整理完成时间:** 2026-03-10
**整理执行者:** OpenCode AI Assistant
**文档版本:** 1.0
+54 -33
View File
@@ -1,58 +1,79 @@
# Spark App Store # 星火应用商店
[![star](https://gitee.com/deepin-community-store/spark-store/badge/star.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/stargazers) [![fork](https://gitee.com/deepin-community-store/spark-store/badge/fork.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/members)
Spark Store aims to collect Linux apps for the convieniece of Linux new comers <div align="center">
The collecting process needs everyone's help <img src="icons/spark-store.svg" alt="APM Logo" width="200" height="200" />
We set up this APP Store and collect APPs/tools that everyone need widely. Also we pack Windows apps with wine. **星火应用商店**
All packages will be shared in our repository for users to get freely. ## 简介
Distrobution supportedDeepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(May stop support in the future ; UniontechOS Home 21 欢迎来到**星火应用商店**!这是一个为 Linux 平台用户设计的应用商店,旨在解决 Linux 生态下应用分散、难以获取的问题。无论您使用什么类型的 Linux 发行版,在这里都有可能找到适合您的软件包。
Linux 应用的数量相对有限,Wine 软件的可获取性也颇为困难。优秀的开发套件和工具资源散布在各大社区和论坛之间,这种分散化让整个生态系统难以得到全面的提升。
生态系统的构建并非依赖个体的孤立努力,而需要全社区共同参与。只有当大家的“星火”聚集一处,方可引发“燎原之势”。
为了改善这一现状,我们推出了星火应用商店。星火社区广泛地收录了各种用户需求的软件包,汇集了高质量的小工具,并主动对 Wine 应用进行了适配,一切都储存在我们的软件库中,使得用户可以方便地获取这些应用。
**当前支持的 Linux 发行版包括(但不限于):**
- **amd64 架构:** Debian 10+ / Ubuntu 22.04+ / Arch Linux / Fedora / deepin / UOS / 银河麒麟
- **arm64 架构:** Debian 10+ / Ubuntu 22.04+ / Arch Linux / deepin / UOS / 银河麒麟
- **loong64 架构:** deepin 23/25
对于不同平台,商店展示的应用列表不同,如有需要请提交应用需求,我们会尽快添加。
I hope people who see here can also join our teamdevelopment help or submit applications are welcomed
If you want to submit an APP to share with othersPlease [Click here](https://upload.deepinos.org/index) </div>
## 🙌 A simple start
If you simply want to install the Spark Store,just enter the [Release] page, find the version you want and install. ## 🚀 快速开始
If you are using Debian11/Ubuntu 20.04, you will need extra dependency package. Available [here](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip) ### 安装应用商店
* Debian(包括Ubuntu、deepin、银河麒麟、UOS)
1. 从 Release 下载最新版本的应用商店客户端。
2. 从启动器中打开并使用
* Fedora
1. `sudo dnf copr enable xmp360/spark-store`
2. `sudo dnf install spark-store`
* Arch Linux
1. `paru -S spark-store`
--- ---
#### Compile and developement <div align="center">
<img src="./galleries/image.png" alt="APM Screenshot" width="90%" />
</div>
## 📦 关于 APM
For Deepin V20/UOS 21/ Debian 11 **APM (AmberPM)** 是基于 `fuse-overlayfs` + `dpkg` + `AmberCE` 的容器化兼容层,为多发行版提供轻量级的应用运行方案。星火的 Arch Linux 版本和 Fedora 版本基于APM实现支持。
```shell ### 核心特性
sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
``` **多发行版兼容** — 完美支持 Arch Linux、Fedora、银河麒麟、统信 UOS 等主流发行版,让星火商店应用随处可用
🔄 **智能包转换** — 与 Debian 生态深度兼容,绝大多数 deb 包可一键自动转换为 APM 格式
**轻量兼容层** — 基于 overlayfs 技术打造,极速启动无负担,告别臃肿容器
🎮 **NVIDIA 硬件加速** — 智能识别主机 GPU 驱动,自动配置硬件加速,畅享流畅体验
Ubuntu 22.04 APM的源码:[APM Source Code](https://gitee.com/amber-ce/amber-pm)
```shell
sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
``` ---
Then **重要须知:** 本软件无法保证持续可用、无中断运行或满足特定性能要求。星火社区对其功能完整性、稳定性及无错误运行不作任何承诺。例如,若您计划在 UOS 专业版(或其他类似特定平台)上使用,请务必了解并启用“开发者模式”相关功能。请确保您具备基础的故障排查能力。需要明确的是,星火社区无法在部分特殊平台上进行广泛测试。因此,在这些平台上使用星火应用商店客户端可能会导致一系列问题,如系统更新失败、数据丢失等;使用该软件,即代表您理解并同意所有风险需由用户自行承担。
```shell **© 2026 APM / AmberPM | The Spark Project**
git clone https://gitee.com/deepin-community-store/spark-store.git
cd spark-store
dpkg-buildpackage
```
Made with ❤️ by the Spark Store Team
</div>
## 🚀 Coorperation
We use Gitee as our code hosting platform. Please click here to contact us.
https://gitee.com/deepin-community-store/spark-store
-50
View File
@@ -1,50 +0,0 @@
# 星火应用商店
[![star](https://gitee.com/deepin-community-store/spark-store/badge/star.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/stargazers) [![fork](https://gitee.com/deepin-community-store/spark-store/badge/fork.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/members)
众所周知,国内的Linux应用比较少,wine应用难以获取,优质工具分散在民间各大论坛,无法形成合力,难以改善生态
生态构建需要的不是某一方的单打独斗,而是人人行动起来,汇聚星火,产生燎原之势
我们创建了这个应用商店,广泛收录大家需要的软件包,搜集优质小工具,主动适配wine应用,存放到储存库供大家获取
我们支持:Deepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(将会逐渐停止支持) ; UOS Home 21
希望看到这里的人也可以加入我们的队伍,开发或者投递应用都很欢迎,共同构建Linux应用生态
如果有想要提交的软件包,请 [在这里投稿](https://upload.deepinos.org/index)
## 🙌 简单的开始
如果想安装 `星火应用商店` ,请打开右侧的 [Release] 页面,找到最新版本,并选择适用于当前系统的安装包下载。
如果你在使用 `Debian 11/Ubuntu 20.04`,你需要额外下载[依赖补充包](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip)
---
#### 编译安装
Deepin V20/UOS 21 系统下, 安装依赖
```shell
sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
```
Ubuntu 22.04 系统下, 安装依赖
```shell
sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
```
然后
```shell
git clone https://gitee.com/deepin-community-store/spark-store.git
cd spark-store
dpkg-buildpackage
```
## 🚀 协作
非常感谢有兴趣的开发者或爱好者参与 `星火应用商店` 项目,分享你的见解与思路。
+71
View File
@@ -0,0 +1,71 @@
# Security Policy / 安全策略
---
## 🌐 English Version
### Supported Versions
The following versions currently receive security updates:
| Version | Supported |
|---------|--------------------|
| > 1.0.4 | :white_check_mark: |
| < 1.0.4 | :x: |
> **Note**: Only versions marked with ✅ receive security patches. Upgrade to a supported version immediately if using an unsupported release.
### Reporting a Vulnerability
We deeply appreciate your efforts to responsibly disclose security issues. Please follow these guidelines:
#### 📬 How to Report
- **Preferred**: Use GitHub's [Private Vulnerability Reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities)
#### 📋 Report Should Include
- Clear description of the vulnerability and potential impact
- Affected component/version
- Steps to reproduce (PoC code appreciated but optional)
- Suggested mitigation (if known)
- Contact information and preferred disclosure timeline
#### ⚠️ Important Notes
- **DO NOT** disclose publicly before coordination
- Avoid intrusive testing (e.g., data exfiltration, DoS)
- We comply with [ISO/IEC 29147](https://www.iso.org/standard/45173.html) vulnerability disclosure standards
- Good-faith researchers acting responsibly will not face legal action
Thank you for helping keep our community safe! 🛡️
---
## 🇨🇳 中文版本
### 支持的版本
以下版本当前接收安全更新:
| 版本 | 是否支持 |
|--------|-------------------|
| > 1.0.4 | :white_check_mark: |
| < 1.0.4 | :x: |
> **提示**:仅标记 ✅ 的版本接收安全补丁。如使用不受支持的版本,请立即升级至受支持版本。
### 漏洞报告流程
感谢您负责任地披露安全问题。请遵循以下指南:
#### 📬 报告方式
- **首选**:使用 GitHub [私有漏洞报告](https://docs.github.com/zh/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities) 功能
#### 📋 报告内容建议包含
- 漏洞清晰描述及潜在影响
- 受影响组件/版本
- 复现步骤(提供验证代码更佳,非必需)
- 建议的缓解措施(如已知)
- 联系方式及期望的披露时间
#### ⚠️ 重要提示
- 修复完成前**请勿公开披露**
- 避免侵入性测试(如数据窃取、拒绝服务攻击)
- 本流程遵循 [ISO/IEC 29147](https://www.iso.org/standard/45173.html) 漏洞披露国际标准
- 本着善意负责任研究的安全研究员将不会面临法律追责
感谢您为社区安全贡献力量!🛡️
+436
View File
@@ -0,0 +1,436 @@
# 测试文档
## 📋 目录
- [测试框架](#测试框架)
- [测试规范](#测试规范)
- [编写测试](#编写测试)
- [运行测试](#运行测试)
- [测试覆盖率](#测试覆盖率)
- [Mock 数据](#mock-数据)
- [E2E 测试](#e2e-测试)
## 测试框架
### Vitest(单元测试)
Vitest 是 Vite 原生的测试框架,提供快速的开发体验。
**特点:**
- 与 Vite 配置共享
- 极快的测试执行速度
- 内置 TypeScript 支持
- Jest 兼容的 API
**配置文件:** `vitest.config.ts`
### PlaywrightE2E 测试)
Playwright 用于端到端测试,模拟真实用户操作。
**特点:**
- 支持多浏览器(Chromium, Firefox, WebKit
- 自动等待
- 网络拦截和 mock
- 可视化测试运行
**配置文件:** `playwright.config.ts`
## 测试规范
### 命名规范
**测试文件:** `*.test.ts``*.spec.ts`
**测试目录结构:**
```
src/
├── __tests__/
│ ├── unit/ # 单元测试
│ │ ├── downloadStatus.test.ts
│ │ └── storeConfig.test.ts
│ ├── integration/ # 集成测试
│ │ └── installFlow.test.ts
│ └── setup.ts # 测试设置
└── components/
└── AppCard.test.ts # 组件测试
e2e/
├── install.spec.ts # E2E 测试
└── download.spec.ts
```
### 测试分组
使用 `describe` 分组相关测试:
```typescript
describe("ComponentName", () => {
describe("method", () => {
it("should do something", () => {
// ...
});
});
});
```
### 测试命名
使用清晰的描述性名称:
```typescript
好的:
it('should return true when app is installed')
it('should throw error when package not found')
不好的:
it('test1')
it('works')
```
## 编写测试
### 单元测试
**测试纯函数:**
```typescript
import { describe, it, expect } from "vitest";
import { parseInstalledList } from "@/modules/parse";
describe("parseInstalledList", () => {
it("should parse installed list correctly", () => {
const output = "code/stable,1.108.2 amd64 [installed]";
const result = parseInstalledList(output);
expect(result).toHaveLength(1);
expect(result[0].pkgname).toBe("code");
expect(result[0].version).toBe("1.108.2");
});
});
```
**测试 Vue 组件:**
```typescript
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import AppCard from "@/components/AppCard.vue";
import type { App } from "@/global/typedefinition";
describe("AppCard", () => {
const mockApp: App = {
name: "Test App",
pkgname: "test-app",
version: "1.0.0",
filename: "test.deb",
torrent_address: "",
author: "Test",
contributor: "Test",
website: "https://example.com",
update: "2024-01-01",
size: "100M",
more: "Test app",
tags: "",
img_urls: [],
icons: "",
category: "test",
currentStatus: "not-installed",
};
it("should render app name", () => {
const wrapper = mount(AppCard, {
props: {
app: mockApp,
},
});
expect(wrapper.text()).toContain("Test App");
});
it("should emit install event", async () => {
const wrapper = mount(AppCard, {
props: {
app: mockApp,
},
});
await wrapper.find(".install-button").trigger("click");
expect(wrapper.emitted("install")).toBeTruthy();
});
});
```
### 集成测试
测试模块间的交互:
```typescript
import { describe, it, expect, vi, beforeEach } from "vitest";
import { installPackage } from "@/modules/processInstall";
import { downloads, addDownload } from "@/global/downloadStatus";
describe("installPackage integration", () => {
beforeEach(() => {
downloads.value = [];
vi.clearAllMocks();
});
it("should add download and send IPC message", () => {
const pkgname = "test-app";
installPackage(pkgname);
expect(downloads.value).toHaveLength(1);
expect(downloads.value[0].pkgname).toBe(pkgname);
expect(window.ipcRenderer.send).toHaveBeenCalledWith(
"queue-install",
expect.any(String),
);
});
});
```
## 运行测试
### 单元测试
```bash
# 运行所有测试
npm run test
# 监听模式(开发时)
npm run test:watch
# 运行特定文件
npm run test src/__tests__/unit/downloadStatus.test.ts
# 运行匹配模式的测试
npm run test -- downloadStatus
```
### 覆盖率
```bash
# 生成覆盖率报告
npm run test:coverage
# 报告位置:
# - 控制台: 文本报告
# - coverage/ 目录: HTML 报告
```
### E2E 测试
```bash
# 运行所有 E2E 测试
npm run test:e2e
# UI 模式(推荐用于开发)
npm run test:e2e:ui
# 调试模式
npm run test:e2e:debug
# 运行特定测试
npm run test:e2e -- install.spec.ts
```
## 测试覆盖率
### 覆盖率目标
- **语句覆盖率:** ≥ 70%
- **分支覆盖率:** ≥ 70%
- **函数覆盖率:** ≥ 70%
- **行覆盖率:** ≥ 70%
### 查看报告
```bash
npm run test:coverage
# 在浏览器中打开
open coverage/index.html
```
### CI 中强制检查
`.github/workflows/test.yml` 中配置覆盖率阈值。
## Mock 数据
### Mock IPC
`src/__tests__/setup.ts` 中全局 mock
```typescript
global.window = Object.create(window);
Object.defineProperty(window, "ipcRenderer", {
value: {
send: vi.fn(),
on: vi.fn(),
off: vi.fn(),
invoke: vi.fn(),
removeListener: vi.fn(),
},
});
```
### Mock API 响应
```typescript
import { vi } from "vitest";
import axios from "axios";
vi.mock("axios");
describe("fetchApps", () => {
it("should fetch apps from API", async () => {
const mockApps = [{ name: "Test", pkgname: "test" }];
axios.get.mockResolvedValue({ data: mockApps });
const result = await fetchApps();
expect(result).toEqual(mockApps);
});
});
```
### Mock 文件系统
```typescript
import { vi } from "vitest";
import fs from "node:fs";
vi.mock("node:fs");
describe("readConfig", () => {
it("should read config file", () => {
const mockConfig = { theme: "dark" };
fs.readFileSync.mockReturnValue(JSON.stringify(mockConfig));
const config = readConfig();
expect(config).toEqual(mockConfig);
});
});
```
## E2E 测试
### 编写 E2E 测试
```typescript
import { test, expect } from "@playwright/test";
test.describe("App Installation", () => {
test.beforeEach(async ({ page }) => {
await page.goto("http://127.0.0.1:3344");
});
test("should install an app", async ({ page }) => {
// 搜索应用
await page.fill('input[placeholder="搜索应用"]', "Test App");
await page.press('input[placeholder="搜索应用"]', "Enter");
// 等待结果
await expect(page.locator(".app-card")).toBeVisible();
// 点击安装
await page.click('.app-card:has-text("Test App") .install-button');
// 验证下载队列
await expect(page.locator(".download-queue")).toBeVisible();
await expect(page.locator(".download-item")).toHaveText("Test App");
});
test("should show installation progress", async ({ page }) => {
// ... 测试进度显示
});
test("should handle installation failure", async ({ page }) => {
// ... 测试失败处理
});
});
```
### E2E 测试最佳实践
1. **使用选择器**
```typescript
// 推荐:语义化选择器
await page.click('[data-testid="install-button"]');
// 避免:脆弱的选择器
await page.click("button.btn-primary");
```
2. **等待元素**
```typescript
// 自动等待
await expect(page.locator(".modal")).toBeVisible();
// 手动等待(必要时)
await page.waitForSelector(".modal", { state: "visible" });
```
3. **截图和视频**
- 失败时自动截图
- 失败时自动录制视频
4. **网络拦截**
```typescript
await page.route("**/api/**", (route) => {
route.fulfill({
status: 200,
body: JSON.stringify(mockData),
});
});
```
## 常见问题
### 测试超时
```typescript
test(
"slow test",
async () => {
// 增加超时时间
},
{ timeout: 10000 },
);
```
### 异步测试
```typescript
it("should handle async operation", async () => {
await someAsyncOperation();
expect(result).toBe(expected);
});
```
### 清理副作用
```typescript
import { afterEach } from "vitest";
afterEach(() => {
// 清理 mock
vi.restoreAllMocks();
// 清理状态
downloads.value = [];
});
```
---
**© 2026 APM 应用商店项目**
+160
View File
@@ -0,0 +1,160 @@
# 问题排查指南
## 📋 目录
- [常见问题](#常见问题)
- [调试方法](#调试方法)
- [日志分析](#日志分析)
- [性能问题](#性能问题)
## 常见问题
### 应用无法启动
**症状:** 双击应用图标后无反应
**可能原因:**
1. 依赖包未安装
2. 配置文件损坏
3. 权限问题
**解决方法:**
```bash
# 检查日志
journalctl -u spark-store
# 重新安装
sudo dpkg -i spark-store_*.deb
# 检查依赖
sudo apt-get install -f
```
### 安装失败
**症状:** 点击安装按钮后无响应或报错
**可能原因:**
1. APM 未安装
2. 权限不足
3. 网络问题
**解决方法:**
```bash
# 检查 APM 是否安装
which apm
# 检查权限
pkexec --version
# 查看 APM 日志
sudo journalctl -u amber-pm
```
### 下载速度慢
**症状:** 下载进度缓慢
**解决方法:**
1. 检查网络连接
2. 更换下载源
3. 使用代理
### 主题切换无效
**症状:** 切换暗色/亮色主题后无变化
**解决方法:**
```bash
# 清除本地存储
rm -rf ~/.config/spark-store/
```
## 调试方法
### 主进程调试
```bash
# 使用命令行启动并查看日志
spark-store --enable-logging
```
### 渲染进程调试
1. 打开应用
2.`Ctrl+Shift+I` 打开 DevTools
3. 查看 Console 和 Network 标签
### IPC 通信调试
`electron/main/index.ts` 中添加日志:
```typescript
ipcMain.on("test-channel", (event, data) => {
logger.info("IPC received:", data);
});
```
## 日志分析
### 日志位置
- **主进程日志:** `~/.config/spark-store/logs/`
- **系统日志:** `journalctl -u spark-store`
### 日志级别
- `trace`: 最详细
- `debug`: 调试信息
- `info`: 一般信息
- `warn`: 警告
- `error`: 错误
- `fatal`: 致命错误
### 查看日志
```bash
# 查看最新日志
tail -f ~/.config/spark-store/logs/main.log
# 搜索错误
grep ERROR ~/.config/spark-store/logs/*.log
```
## 性能问题
### 内存占用高
**检查方法:**
1. 打开 DevTools → Performance 标签
2. 录制并分析内存使用
**优化建议:**
- 清理不必要的组件
- 使用虚拟滚动
- 避免内存泄漏
### 启动慢
**检查方法:**
1. 查看 DevTools → Network 标签
2. 检查加载时间
**优化建议:**
- 延迟加载非关键资源
- 优化 API 请求
- 减少 HTTP 请求数量
---
**© 2026 APM 应用商店项目**
+632
View File
@@ -0,0 +1,632 @@
# 标准开发流程
本文档描述在 APM 应用商店项目中完成代码开发后的标准提交流程。
## 📋 目录
- [开发前准备](#开发前准备)
- [代码完成后](#代码完成后)
- [提交流程](#提交流程)
- [典型场景](#典型场景)
- [提交流程检查清单](#提交流程检查清单)
- [常见问题](#常见问题)
---
## 开发前准备
在开始开发之前,确保你的开发环境已正确配置:
```bash
# 1. 切换到项目目录
cd apm-app-store
# 2. 拉取最新代码
git pull origin main
# 3. 创建功能分支
git checkout -b feature/your-feature-name
# 或修复分支
git checkout -b fix/your-bug-fix
# 4. 确保依赖已安装
npm install
```
---
## 代码完成后
### 1️⃣ 运行代码检查
首先确保代码符合项目规范:
```bash
# 运行 ESLint 检查
npm run lint
# 如果有错误,尝试自动修复
npm run lint:fix
# 手动修复无法自动处理的问题
```
**ESLint 错误类型:**
- `@typescript-eslint/no-explicit-any`: 避免使用 `any` 类型
- `@typescript-eslint/no-unused-vars`: 未使用的变量
- 其他代码风格问题
### 2️⃣ 格式化代码
使用 Prettier 格式化代码:
```bash
npm run format
```
### 3️⃣ 运行测试
确保所有测试通过:
```bash
# 运行单元测试
npm run test
# 生成测试覆盖率报告
npm run test:coverage
# 运行 E2E 测试(如果需要)
npm run test:e2e
# 运行所有测试
npm run test:all
```
**测试覆盖率要求:**
- 语句覆盖率: ≥ 70%
- 分支覆盖率: ≥ 70%
- 函数覆盖率: ≥ 70%
- 行覆盖率: ≥ 70%
### 4️⃣ 构建验证
验证代码可以成功构建:
```bash
# 仅构建前端代码(快速)
npm run build:vite
```
如果构建失败,检查 TypeScript 错误并修复。
---
## 提交流程
### 5️⃣ 提交代码
#### 查看变更
```bash
# 查看所有变更文件
git status
# 查看具体变更
git diff
```
#### 添加文件
```bash
# 添加所有变更文件
git add .
# 或添加特定文件
git add path/to/file.ts
```
#### 提交信息
遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
```
type(scope): subject
[可选的正文]
[可选的脚注]
```
**Type 类型:**
- `feat`: 新功能
- `fix`: Bug 修复
- `docs`: 文档更新
- `style`: 代码格式(不影响功能)
- `refactor`: 重构
- `perf`: 性能优化
- `test`: 测试相关
- `chore`: 构建/工具相关
**Scope 范围:**
- `app`: 应用核心
- `install`: 安装/卸载
- `ui`: UI 组件
- `ipc`: IPC 通信
- `api`: API 集成
- `theme`: 主题
- `build`: 构建
- `docs`: 文档
**Subject 主题:**
- 使用现在时态("add" 而非 "added"
- 首字母小写
- 不以句号结尾
**示例:**
```bash
# 新功能
git commit -m "feat(install): add retry mechanism for failed installations" -s
# Bug 修复
git commit -m "fix(ui): correct dark mode toggle persistence" -s
# 文档更新
git commit -m "docs(readme): update build instructions" -s
# 重构
git commit -m "refactor(ipc): simplify install manager event handling" -s
# 测试
git commit -m "test(download): add unit tests for download queue" -s
```
**添加签名:**
```bash
# 使用 -s 添加签名
git commit -m "feat(example): add new feature" -s
# 或在 ~/.gitconfig 中配置
# [commit]
# gpgsign = true
```
#### 执行提交
```bash
git commit -m "type(scope): description" -s
```
### 6️⃣ 推送到远程仓库
```bash
# 推送当前分支
git push origin feature/your-feature-name
# 或使用简写
git push -u origin feature/your-feature-name
```
### 7️⃣ 创建 Pull Request
#### 访问 GitHub
1. 访问仓库页面
2. 点击 "New Pull Request"
3. 选择你的分支 → main 分支
#### 填写 PR 模板
使用 PR 模板填写信息:
**变更类型:**
- [ ] `feat` - 新功能
- [ ] `fix` - Bug 修复
- [ ] `refactor` - 重构
- [ ] `docs` - 文档更新
- [ ] `test` - 测试相关
- [ ] `chore` - 构建/工具相关
**变更描述:**
清晰简洁地说明你做了什么,为什么这么做。
**相关 Issue**
引用相关的 Issue 编号,例如 `Fixes #123``Closes #123`
**测试说明:**
如何测试这些变更?包括:
- 测试步骤
- 预期结果
- 测试环境
**截图/录屏:**
如果涉及 UI 变更,添加截图或录屏。
**检查清单:**
- [ ] 代码通过 `npm run lint`
- [ ] 代码通过 `npm run format`
- [ ] 所有测试通过 (`npm run test`)
- [ ] 新功能包含测试
- [ ] 文档已更新(如需要)
#### 提交 PR
点击 "Create Pull Request"。
### 8️⃣ 代码审查
#### 等待审查
- 至少一位维护者会审查你的 PR
- CI 会自动运行测试和检查
- 确保所有 CI 检查通过(绿色 ✅)
#### 响应审查意见
- 阅审审查者提出的意见
- 进行必要的修改
- 提交更改到你的分支
- 在 PR 中评论说明修改内容
#### 更新 PR
```bash
# 修改代码后
git add .
git commit -m "address review feedback" -s
git push origin feature/your-feature-name
```
### 9️⃣ 合并 PR
#### 合并条件
- 至少一次审查批准
- 所有 CI 检查通过
- 无冲突
- 分支最新
#### 合并方式
- 使用 "Squash and merge" 将提交压缩为一个
- 或使用 "Merge commit" 保留提交历史
#### 删除分支
合并后删除你的功能分支:
```bash
# 删除本地分支
git branch -d feature/your-feature-name
# 删除远程分支
git push origin --delete feature/your-feature-name
```
---
## 典型场景
### 场景 1: 开发新功能
```bash
# 1. 创建功能分支
git checkout -b feature/add-search-filters
# 2. 开发代码...
# (编写代码)
# 3. 运行检查
npm run lint
npm run lint:fix
npm run format
npm run test
# 4. 构建验证
npm run build:vite
# 5. 提交代码
git add .
git commit -m "feat(search): add advanced search filters with category filtering" -s
# 6. 推送
git push -u origin feature/add-search-filters
# 7. 创建 PR
# (在 GitHub 上创建 PR
```
### 场景 2: 修复 Bug
```bash
# 1. 创建修复分支
git checkout -b fix/fix-download-timeout
# 2. 修复代码...
# 3. 运行检查
npm run lint
npm run format
npm run test
# 4. 提交代码
git add .
git commit -m "fix(download): resolve timeout issue with retry logic" -m "Fixes #123" -s
# 5. 推送
git push -u origin fix/fix-download-timeout
# 6. 创建 PR
```
### 场景 3: 更新文档
```bash
# 1. 创建文档分支
git checkout -b docs/update-api-docs
# 2. 更新文档...
# 3. 提交代码
git add .
git commit -m "docs(api): update installation API documentation" -s
# 4. 推送
git push -u origin docs/update-api-docs
# 5. 创建 PR
```
### 场景 4: 重构代码
```bash
# 1. 创建重构分支
git checkout -b refactor/simplify-download-manager
# 2. 重构代码...
# 3. 运行检查
npm run lint
npm run format
npm run test
# 4. 提交代码
git add .
git commit -m "refactor(download): simplify download manager event handling" -s
# 5. 推送
git push -u origin refactor/simplify-download-manager
# 6. 创建 PR
```
---
## 提交流程检查清单
在创建 PR 前,确保完成以下检查:
### 代码质量
- [ ] ESLint 检查通过 (`npm run lint`)
- [ ] 代码已格式化 (`npm run format`)
- [ ] 没有 `any` 类型(除非必要并添加注释)
- [ ] 遵循代码规范(见 [AGENTS.md](./AGENTS.md)
- [ ] TypeScript 严格模式通过
### 测试
- [ ] 单元测试通过 (`npm run test`)
- [ ] 新功能包含测试
- [ ] 测试覆盖率 ≥ 70%
- [ ] E2E 测试通过(如需要,`npm run test:e2e`
- [ ] 没有测试回归
### 文档
- [ ] 更新了相关文档(如需要)
- [ ] 更新了 CHANGELOG.md(如需要)
- [ ] API 文档更新(如需要)
- [ ] README.md 更新(如需要)
### 功能验证
- [ ] 本地测试通过
- [ ] 没有引入新 Bug
- [ ] 边界情况已处理
- [ ] 错误处理完善
- [ ] 性能未下降
### 提交信息
- [ ] 遵循 Conventional Commits 规范
- [ ] 添加了签名(`-s`
- [ ] 引用相关 Issue(如适用)
- [ ] 提交信息清晰明确
---
## 快速提交命令
如果你想快速提交所有检查,可以使用以下命令:
```bash
# 完整流程(一行命令)
npm run lint && npm run format && npm run test && git add . && git commit -m "type(scope): description" -s && git push -u origin $(git branch --show-current)
```
### 创建便捷脚本
`scripts/` 目录下创建 `commit.sh`:
```bash
#!/bin/bash
# 检查参数
if [ -z "$1" ]; then
echo "❌ 错误: 请提供提交信息"
echo "使用方法: ./scripts/commit.sh \"type(scope): description\""
exit 1
fi
echo "🔍 Running lint..."
npm run lint
if [ $? -ne 0 ]; then
echo "❌ ESLint 检查失败,请修复错误后重试"
exit 1
fi
echo "🎨 Formatting code..."
npm run format
echo "🧪 Running tests..."
npm run test
if [ $? -ne 0 ]; then
echo "❌ 测试失败,请修复测试后重试"
exit 1
fi
echo "📝 Committing changes..."
git add .
git commit -m "$1" -s
if [ $? -ne 0 ]; then
echo "❌ 提交失败"
exit 1
fi
echo "🚀 Pushing to remote..."
BRANCH_NAME=$(git branch --show-current)
git push -u origin $BRANCH_NAME
if [ $? -ne 0 ]; then
echo "❌ 推送失败"
exit 1
fi
echo ""
echo "✅ 提交成功!"
echo "📌 分支: $BRANCH_NAME"
echo "📝 提交信息: $1"
echo "🔗 请创建 Pull Request: https://github.com/elysia-best/apm-app-store/compare/main...$BRANCH_NAME"
```
使用方法:
```bash
# 给脚本添加执行权限
chmod +x scripts/commit.sh
# 使用脚本提交
./scripts/commit.sh "feat(search): add advanced search filters"
```
---
## 常见问题
### Q: ESLint 检查失败怎么办?
**A:**
1. 运行 `npm run lint:fix` 自动修复
2. 手动修复无法自动处理的问题
3. 如果确实需要使用 `any`,添加 `// eslint-disable-next-line @typescript-eslint/no-explicit-any`
### Q: 测试失败怎么办?
**A:**
1. 查看测试失败信息
2. 修复代码或测试
3. 确保测试覆盖所有情况
4. 运行 `npm run test` 重新验证
### Q: 构建失败怎么办?
**A:**
1. 查看 TypeScript 错误
2. 修复类型错误
3. 确保类型定义正确
4. 运行 `npm run build:vite` 重新验证
### Q: 如何修复合并冲突?
**A:**
```bash
# 1. 拉取最新代码
git fetch origin
# 2. 合并 main 分支到你的分支
git merge origin/main
# 3. 解决冲突
# (编辑冲突文件,选择正确的代码)
# 4. 标记冲突已解决
git add .
# 5. 提交合并
git commit -m "merge: resolve conflicts with main" -s
# 6. 推送
git push origin feature/your-feature-name
```
### Q: 如何修改已提交的代码?
**A:**
```bash
# 1. 修改代码...
# 2. 添加到暂存区
git add .
# 3. 提交到分支
git commit -m "address review feedback" -s
# 4. 推送
git push origin feature/your-feature-name
```
### Q: 如何撤回错误的提交?
**A:**
```bash
# 如果还未推送
git reset --soft HEAD~1
# 重新提交
git commit -m "correct message" -s
# 如果已推送(需要强制推送,谨慎使用)
git reset --soft HEAD~1
git commit -m "correct message" -s
git push origin feature/your-feature-name --force
```
**注意:** 避免在已公开的分支上使用强制推送。
---
## 📚 相关文档
- **开发指南:** [DEVELOPMENT.md](./DEVELOPMENT.md)
- **贡献指南:** [CONTRIBUTING.md](./CONTRIBUTING.md)
- **测试文档:** [TESTING.md](./TESTING.md)
- **AI 编码指南:** [AGENTS.md](./AGENTS.md)
- **部署文档:** [DEPLOYMENT.md](./DEPLOYMENT.md)
---
**© 2026 APM 应用商店项目**
Binary file not shown.
Binary file not shown.
-59
View File
@@ -1,59 +0,0 @@
<RCC>
<qresource prefix="/icons">
<file>icons/category_chat_dark.svg</file>
<file>icons/category_chat.svg</file>
<file>icons/category_develop_dark.svg</file>
<file>icons/category_develop.svg</file>
<file>icons/category_game_dark.svg</file>
<file>icons/category_game.svg</file>
<file>icons/category_graphic_dark.svg</file>
<file>icons/category_graphic.svg</file>
<file>icons/category_music_dark.svg</file>
<file>icons/category_music.svg</file>
<file>icons/category_network_dark.svg</file>
<file>icons/category_network.svg</file>
<file>icons/category_office_dark.svg</file>
<file>icons/category_office.svg</file>
<file>icons/category_others_dark.svg</file>
<file>icons/category_others.svg</file>
<file>icons/category_reading_dark.svg</file>
<file>icons/category_reading.svg</file>
<file>icons/category_system_dark.svg</file>
<file>icons/category_system.svg</file>
<file>icons/category_video_dark.svg</file>
<file>icons/category_video.svg</file>
<file>icons/downloads-symbolic_dark.svg</file>
<file>icons/downloads-symbolic.svg</file>
<file>icons/theme-symbolic_dark.svg</file>
<file>icons/theme-symbolic.svg</file>
<file>icons/homepage.svg</file>
<file>icons/homepage_dark.svg</file>
<file>icons/category_active_dark.svg</file>
<file>icons/category_active.svg</file>
<file>icons/refresh-page-dark.svg</file>
<file>icons/refresh-page.svg</file>
</qresource>
<qresource prefix="/">
<file>tags/a2d.png</file>
<file>tags/community.svg</file>
<file>tags/deepin.svg</file>
<file>tags/logo_icon.svg</file>
<file>tags/uos-authorize.svg</file>
<file>tags/a2d-small.png</file>
<file>tags/community-small.png</file>
<file>tags/deepin-small.png</file>
<file>tags/dtk-small.png</file>
<file>tags/uos-small.png</file>
<file>tags/community.png</file>
<file>tags/ubuntu-small.png</file>
<file>tags/ubuntu.png</file>
<file>tags/dwine5-small.png</file>
<file>tags/dwine5.svg</file>
<file>tags/dwine2-small.png</file>
<file>spark-store.png</file>
<file>spark-logo.svg</file>
</qresource>
<qresource prefix="/fonts">
<file>fonts/hksnzt.ttf</file>
</qresource>
</RCC>
-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="#536076" d="M10.138807,3.52000025 L10.138,12.5230002 L14.6066017,8.05523757 L15.3137085,8.76234435 L9.65685425,14.4191986 L4,8.76234435 L4.70710678,8.05523757 L9.138,12.4870002 L9.138807,3.52000025 L10.138807,3.52000025 Z" transform="rotate(90 9.657 11.518)"/>
</svg>

Before

Width:  |  Height:  |  Size: 366 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="#536076" d="M10.138807,3.52000025 L10.138,12.5230002 L14.6066017,8.05523757 L15.3137085,8.76234435 L9.65685425,14.4191986 L4,8.76234435 L4.70710678,8.05523757 L9.138,12.4870002 L9.138807,3.52000025 L10.138807,3.52000025 Z" transform="rotate(90 9.657 11.518)"/>
</svg>

Before

Width:  |  Height:  |  Size: 366 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M0.09791679,7.31479943 C0.09791679,3.53173257 3.65198565,0.5 8,0.5 C12.3485596,0.5 15.9020832,3.53150012 15.9020832,7.31479943 C15.9020832,11.0972813 12.3485704,14.127954 8,14.127954 C7.06316558,14.127954 6.1471898,13.9862478 5.28311727,13.7134084 L2.55321759,15.327403 C2.15529088,15.5626687 1.67860204,15.1782665 1.82419813,14.7395213 L2.62951677,12.3127412 C1.03368368,11.0385392 0.09791679,9.24513974 0.09791679,7.31479943 Z M4.7455,6.9148 C4.7455,6.2248 4.1855,5.6648 3.4955,5.6648 C2.8055,5.6648 2.2455,6.2248 2.2455,6.9148 C2.2455,7.6048 2.8055,8.1648 3.4955,8.1648 C4.1855,8.1648 4.7455,7.6048 4.7455,6.9148 Z M9.2504,6.9148 C9.2504,6.2248 8.6904,5.6648 8.0004,5.6648 C7.3104,5.6648 6.7504,6.2248 6.7504,6.9148 C6.7504,7.6048 7.3104,8.1648 8.0004,8.1648 C8.6904,8.1648 9.2504,7.6048 9.2504,6.9148 Z M13.766,6.9148 C13.766,6.2248 13.206,5.6648 12.516,5.6648 C11.826,5.6648 11.266,6.2248 11.266,6.9148 C11.266,7.6048 11.826,8.1648 12.516,8.1648 C13.206,8.1648 13.766,7.6048 13.766,6.9148 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M0.09791679,7.31479943 C0.09791679,3.53173257 3.65198565,0.5 8,0.5 C12.3485596,0.5 15.9020832,3.53150012 15.9020832,7.31479943 C15.9020832,11.0972813 12.3485704,14.127954 8,14.127954 C7.06316558,14.127954 6.1471898,13.9862478 5.28311727,13.7134084 L2.55321759,15.327403 C2.15529088,15.5626687 1.67860204,15.1782665 1.82419813,14.7395213 L2.62951677,12.3127412 C1.03368368,11.0385392 0.09791679,9.24513974 0.09791679,7.31479943 Z M4.7455,6.9148 C4.7455,6.2248 4.1855,5.6648 3.4955,5.6648 C2.8055,5.6648 2.2455,6.2248 2.2455,6.9148 C2.2455,7.6048 2.8055,8.1648 3.4955,8.1648 C4.1855,8.1648 4.7455,7.6048 4.7455,6.9148 Z M9.2504,6.9148 C9.2504,6.2248 8.6904,5.6648 8.0004,5.6648 C7.3104,5.6648 6.7504,6.2248 6.7504,6.9148 C6.7504,7.6048 7.3104,8.1648 8.0004,8.1648 C8.6904,8.1648 9.2504,7.6048 9.2504,6.9148 Z M13.766,6.9148 C13.766,6.2248 13.206,5.6648 12.516,5.6648 C11.826,5.6648 11.266,6.2248 11.266,6.9148 C11.266,7.6048 11.826,8.1648 12.516,8.1648 C13.206,8.1648 13.766,7.6048 13.766,6.9148 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 Z M3.76776695,5.35355339 L6.03553391,7.62132034 L3.76776695,9.8890873 L4.47487373,10.5961941 L7.44974747,7.62132034 L4.47487373,4.64644661 L3.76776695,5.35355339 Z M5.91666667,12 L11.0833333,12 L11.0833333,11 L5.91666667,11 L5.91666667,12 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 523 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 Z M3.76776695,5.35355339 L6.03553391,7.62132034 L3.76776695,9.8890873 L4.47487373,10.5961941 L7.44974747,7.62132034 L4.47487373,4.64644661 L3.76776695,5.35355339 Z M5.91666667,12 L11.0833333,12 L11.0833333,11 L5.91666667,11 L5.91666667,12 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 553 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M11.3114315,3 C13.357501,3 15.0067163,5.17017281 15.7133188,8.05794777 C16.4086522,10.8996678 15.9150863,13.3535714 14.0872428,13.3535714 C13.3629901,13.3535714 12.7141246,13.0969142 11.9239825,12.5819693 C11.7832522,12.4902536 11.638281,12.3909224 11.461347,12.2660165 C11.3686071,12.200547 11.0517692,11.9743261 11.0062924,11.9420563 C9.76649639,11.0623107 9.01108239,10.715 8.00430016,10.715 C6.77138366,10.715 5.99921712,11.0762729 4.96661589,11.9397238 C4.93060093,11.9698391 4.48571222,12.3483964 4.35343872,12.4563717 C3.49008067,13.1611339 2.80601727,13.4628505 1.87123269,13.3869162 C0.0836355556,13.241098 -0.391076934,10.7851693 0.309935396,7.98500253 C1.02394135,5.13293317 2.67988585,3 4.7263796,3 C5.07581055,3 5.40379038,3.09122326 5.76942208,3.26509058 C5.87841375,3.31691894 5.98930228,3.37514875 6.12219409,3.44909841 C6.19628024,3.49032478 6.44963239,3.6346061 6.45727206,3.63892075 C7.10277068,4.00347855 7.50182674,4.14857143 8.01851079,4.14857143 C8.51588602,4.14857143 8.90120605,4.00650828 9.55466919,3.63859493 C9.69986269,3.55637602 9.78224829,3.50972827 9.84835639,3.47295723 C9.96412339,3.40856473 10.0609743,3.35696675 10.1556729,3.31001061 C10.567507,3.10580322 10.9247171,3 11.3114315,3 Z M5.07357978,10.107 C6.56572905,10.107 7.78410609,8.9267355 7.78410609,7.46414286 C7.78410609,6.00155021 6.56572905,4.82128571 5.07357978,4.82128571 C3.57990894,4.82128571 2.36305346,6.00089051 2.36305346,7.46414286 C2.36305346,8.9273952 3.57990894,10.107 5.07357978,10.107 Z M5.07357978,9.107 C4.12535588,9.107 3.36305346,8.36803337 3.36305346,7.46414286 C3.36305346,6.56025235 4.12535588,5.82128571 5.07357978,5.82128571 C6.02043115,5.82128571 6.78410609,6.56107184 6.78410609,7.46414286 C6.78410609,8.36721388 6.02043115,9.107 5.07357978,9.107 Z M5.03983241,8.37864286 C5.54751662,8.37864286 5.9601482,7.97792857 5.9601482,7.48935714 C5.9601482,6.99292857 5.54751662,6.59364286 5.03983241,6.59364286 C4.53067452,6.59364286 4.11804294,6.99292857 4.11804294,7.48935714 C4.11804294,7.97792857 4.53067452,8.37864286 5.03983241,8.37864286 Z M9.65408509,8.38564286 C10.1617693,8.38564286 10.5744008,7.9835 10.5744008,7.49135714 C10.5744008,6.99135714 10.1617693,6.58992857 9.65408509,6.58992857 C9.14492719,6.58992857 8.73229557,6.99135714 8.73229557,7.49135714 C8.73229557,7.9835 9.14492719,8.38564286 9.65408509,8.38564286 Z M11.3288535,9.99071429 C11.8365377,9.99071429 12.2491693,9.58928571 12.2491693,9.09214286 C12.2491693,8.59571429 11.8365377,8.19357143 11.3288535,8.19357143 C10.8196956,8.19357143 10.407064,8.59571429 10.407064,9.09214286 C10.407064,9.58928571 10.8196956,9.99071429 11.3288535,9.99071429 Z M11.3281166,6.77357143 C11.8372745,6.77357143 12.2491693,6.37142857 12.2491693,5.87357143 C12.2491693,5.37714286 11.8372745,4.97428571 11.3281166,4.97428571 C10.8174851,4.97428571 10.407064,5.37714286 10.407064,5.87357143 C10.407064,6.37142857 10.8174851,6.77357143 11.3281166,6.77357143 Z M12.9731166,8.38421429 C13.4852219,8.38421429 13.8971166,7.98135714 13.8971166,7.48921429 C13.8971166,6.98992857 13.4852219,6.5885 12.9731166,6.5885 C12.4676429,6.5885 12.0550114,6.98992857 12.0550114,7.48921429 C12.0550114,7.98135714 12.4676429,8.38421429 12.9731166,8.38421429 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M11.3114315,3 C13.357501,3 15.0067163,5.17017281 15.7133188,8.05794777 C16.4086522,10.8996678 15.9150863,13.3535714 14.0872428,13.3535714 C13.3629901,13.3535714 12.7141246,13.0969142 11.9239825,12.5819693 C11.7832522,12.4902536 11.638281,12.3909224 11.461347,12.2660165 C11.3686071,12.200547 11.0517692,11.9743261 11.0062924,11.9420563 C9.76649639,11.0623107 9.01108239,10.715 8.00430016,10.715 C6.77138366,10.715 5.99921712,11.0762729 4.96661589,11.9397238 C4.93060093,11.9698391 4.48571222,12.3483964 4.35343872,12.4563717 C3.49008067,13.1611339 2.80601727,13.4628505 1.87123269,13.3869162 C0.0836355556,13.241098 -0.391076934,10.7851693 0.309935396,7.98500253 C1.02394135,5.13293317 2.67988585,3 4.7263796,3 C5.07581055,3 5.40379038,3.09122326 5.76942208,3.26509058 C5.87841375,3.31691894 5.98930228,3.37514875 6.12219409,3.44909841 C6.19628024,3.49032478 6.44963239,3.6346061 6.45727206,3.63892075 C7.10277068,4.00347855 7.50182674,4.14857143 8.01851079,4.14857143 C8.51588602,4.14857143 8.90120605,4.00650828 9.55466919,3.63859493 C9.69986269,3.55637602 9.78224829,3.50972827 9.84835639,3.47295723 C9.96412339,3.40856473 10.0609743,3.35696675 10.1556729,3.31001061 C10.567507,3.10580322 10.9247171,3 11.3114315,3 Z M5.07357978,10.107 C6.56572905,10.107 7.78410609,8.9267355 7.78410609,7.46414286 C7.78410609,6.00155021 6.56572905,4.82128571 5.07357978,4.82128571 C3.57990894,4.82128571 2.36305346,6.00089051 2.36305346,7.46414286 C2.36305346,8.9273952 3.57990894,10.107 5.07357978,10.107 Z M5.07357978,9.107 C4.12535588,9.107 3.36305346,8.36803337 3.36305346,7.46414286 C3.36305346,6.56025235 4.12535588,5.82128571 5.07357978,5.82128571 C6.02043115,5.82128571 6.78410609,6.56107184 6.78410609,7.46414286 C6.78410609,8.36721388 6.02043115,9.107 5.07357978,9.107 Z M5.03983241,8.37864286 C5.54751662,8.37864286 5.9601482,7.97792857 5.9601482,7.48935714 C5.9601482,6.99292857 5.54751662,6.59364286 5.03983241,6.59364286 C4.53067452,6.59364286 4.11804294,6.99292857 4.11804294,7.48935714 C4.11804294,7.97792857 4.53067452,8.37864286 5.03983241,8.37864286 Z M9.65408509,8.38564286 C10.1617693,8.38564286 10.5744008,7.9835 10.5744008,7.49135714 C10.5744008,6.99135714 10.1617693,6.58992857 9.65408509,6.58992857 C9.14492719,6.58992857 8.73229557,6.99135714 8.73229557,7.49135714 C8.73229557,7.9835 9.14492719,8.38564286 9.65408509,8.38564286 Z M11.3288535,9.99071429 C11.8365377,9.99071429 12.2491693,9.58928571 12.2491693,9.09214286 C12.2491693,8.59571429 11.8365377,8.19357143 11.3288535,8.19357143 C10.8196956,8.19357143 10.407064,8.59571429 10.407064,9.09214286 C10.407064,9.58928571 10.8196956,9.99071429 11.3288535,9.99071429 Z M11.3281166,6.77357143 C11.8372745,6.77357143 12.2491693,6.37142857 12.2491693,5.87357143 C12.2491693,5.37714286 11.8372745,4.97428571 11.3281166,4.97428571 C10.8174851,4.97428571 10.407064,5.37714286 10.407064,5.87357143 C10.407064,6.37142857 10.8174851,6.77357143 11.3281166,6.77357143 Z M12.9731166,8.38421429 C13.4852219,8.38421429 13.8971166,7.98135714 13.8971166,7.48921429 C13.8971166,6.98992857 13.4852219,6.5885 12.9731166,6.5885 C12.4676429,6.5885 12.0550114,6.98992857 12.0550114,7.48921429 C12.0550114,7.98135714 12.4676429,8.38421429 12.9731166,8.38421429 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z M9.38816736,7.22265239 L7.95626236,10.0443009 C7.82854357,10.2959779 7.59618367,10.3016397 7.44581474,10.0701011 L6.5212474,8.6464491 C6.2918509,8.42797452 5.91137533,8.45796439 5.72281255,8.70938339 L3.09783322,12.2093834 C2.84963451,12.5403176 3.0980227,13 3.52503993,13 L12.9749655,13 C13.3830419,13 13.6350993,12.5760169 13.4251458,12.2427546 L10.2751706,7.24275461 C10.0768804,6.92800582 9.60195261,6.91724249 9.38816736,7.22265239 Z M4.5,4 C3.67157288,4 3,4.67157288 3,5.5 C3,6.32842712 3.67157288,7 4.5,7 C5.32842712,7 6,6.32842712 6,5.5 C6,4.67157288 5.32842712,4 4.5,4 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 865 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.1045695 14.1045695,14 13,14 L3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z M9.38816736,7.22265239 L7.95626236,10.0443009 C7.82854357,10.2959779 7.59618367,10.3016397 7.44581474,10.0701011 L6.5212474,8.6464491 C6.2918509,8.42797452 5.91137533,8.45796439 5.72281255,8.70938339 L3.09783322,12.2093834 C2.84963451,12.5403176 3.0980227,13 3.52503993,13 L12.9749655,13 C13.3830419,13 13.6350993,12.5760169 13.4251458,12.2427546 L10.2751706,7.24275461 C10.0768804,6.92800582 9.60195261,6.91724249 9.38816736,7.22265239 Z M4.5,4 C3.67157288,4 3,4.67157288 3,5.5 C3,6.32842712 3.67157288,7 4.5,7 C5.32842712,7 6,6.32842712 6,5.5 C6,4.67157288 5.32842712,4 4.5,4 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 895 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M13.9529472,2.53458892 C13.9842218,2.67532449 14,2.81906015 14,2.9632288 L14,11.5 C14,12.6045695 13.1045695,13.5 12,13.5 C10.8954305,13.5 10,12.6045695 10,11.5 C10,10.3954305 10.8954305,9.5 12,9.5 C12.364732,9.5 12.7066608,9.5976323 13.0010775,9.76818814 L13,3.81473429 C13,3.45097522 12.705115,3.15609023 12.3413559,3.15609023 C12.2949677,3.15609023 12.2487093,3.16099086 12.2033508,3.17071053 L6.52063898,4.38843451 C6.21695744,4.45350912 6,4.7218827 6,5.03245826 L6,13.5 C6,14.6045695 5.1045695,15.5 4,15.5 C2.8954305,15.5 2,14.6045695 2,13.5 C2,12.3954305 2.8954305,11.5 4,11.5 C4.364732,11.5 4.70666076,11.5976323 5.0010775,11.7681881 L5,4.08503671 C5,3.15891996 5.64322914,2.35706019 6.54729233,2.15615726 L11.5954279,1.03434935 C12.6607186,0.797618084 13.716216,1.46929822 13.9529472,2.53458892 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 929 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M13.9529472,2.53458892 C13.9842218,2.67532449 14,2.81906015 14,2.9632288 L14,11.5 C14,12.6045695 13.1045695,13.5 12,13.5 C10.8954305,13.5 10,12.6045695 10,11.5 C10,10.3954305 10.8954305,9.5 12,9.5 C12.364732,9.5 12.7066608,9.5976323 13.0010775,9.76818814 L13,3.81473429 C13,3.45097522 12.705115,3.15609023 12.3413559,3.15609023 C12.2949677,3.15609023 12.2487093,3.16099086 12.2033508,3.17071053 L6.52063898,4.38843451 C6.21695744,4.45350912 6,4.7218827 6,5.03245826 L6,13.5 C6,14.6045695 5.1045695,15.5 4,15.5 C2.8954305,15.5 2,14.6045695 2,13.5 C2,12.3954305 2.8954305,11.5 4,11.5 C4.364732,11.5 4.70666076,11.5976323 5.0010775,11.7681881 L5,4.08503671 C5,3.15891996 5.64322914,2.35706019 6.54729233,2.15615726 L11.5954279,1.03434935 C12.6607186,0.797618084 13.716216,1.46929822 13.9529472,2.53458892 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 959 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M7.99960993,0.9998 C11.8598496,0.9998 15,4.13995046 15,7.99940993 C15,11.8596496 11.8598496,14.9998 7.99960993,14.9998 C4.14015046,14.9998 1,11.8596496 1,7.99940993 C1,4.13995046 4.14015046,0.9998 7.99960993,0.9998 Z M8.86971986,11.9145 C8.56971986,12.747 8.22071986,13.122 7.99971986,13.122 C7.78521986,13.122 7.44971986,12.768 7.15571986,11.9845 C6.86571986,12.132 6.61521986,12.2485 6.36971986,12.354 C6.75321986,13.3495 7.29871986,14 7.99971986,14 C8.71921986,14 9.27521986,13.314 9.66021986,12.274 C9.41771986,12.1735 9.16171986,12.0585 8.86971986,11.9145 Z M12.0962199,3.61 C10.8027199,3.61 9.05121986,4.5085 7.94421986,5.19 C6.85371986,4.547 5.16021986,3.717 3.90321986,3.717 C3.19571986,3.717 2.85321986,4 2.69121986,4.238 C2.46021986,4.576 2.34571986,5.1655 2.90071986,6.1455 C2.82221986,6.286 2.77771986,6.448 2.77771986,6.6205 C2.77771986,7.154 3.20271986,7.5865 3.72621986,7.5865 C4.24971986,7.5865 4.67471986,7.154 4.67471986,6.6205 C4.67471986,6.087 4.25021986,5.6545 3.72621986,5.6545 L3.72621986,5.6545 L3.62121986,5.6605 C3.32971986,5.131 3.33321986,4.8355 3.39871986,4.7395 C3.46021986,4.6485 3.64921986,4.595 3.90321986,4.595 C4.30121986,4.595 4.82071986,4.7155 5.41071986,4.9325 C5.98671986,5.145 6.57721986,5.43 7.11871986,5.728 C5.99421986,6.502 5.13171986,7.25 4.36621986,8.027 C4.02471986,8.379 3.68871986,8.7615 3.39771986,9.1515 C2.30221986,10.6215 2.40671986,11.433 2.68771986,11.8555 C3.25671986,12.71 4.68721986,12.3665 5.64571986,12.014 C7.99371986,11.151 11.0597199,8.9165 12.6017199,6.848 C13.6972199,5.3785 13.5927199,4.567 13.3117199,4.1445 C13.1492199,3.9005 12.8067199,3.61 12.0962199,3.61 Z M12.2647199,8.445 C11.7407199,8.445 11.3162199,8.8775 11.3162199,9.411 C11.3162199,9.9445 11.7407199,10.377 12.2647199,10.377 L12.3937199,10.368 C12.6702199,10.88 12.6657199,11.167 12.6012199,11.2615 C12.5392199,11.352 12.3507199,11.4055 12.0967199,11.4055 C11.2957199,11.4055 10.1802199,10.933 9.46171986,10.5765 C9.22171986,10.7475 8.92321986,10.9505 8.63221986,11.136 C9.59521986,11.6545 11.0112199,12.2835 12.0967199,12.2835 C12.8042199,12.2835 13.1467199,12.0005 13.3087199,11.7625 C13.5392199,11.4255 13.6537199,10.8375 13.1032199,9.8625 C13.1737199,9.7275 13.2132199,9.574 13.2132199,9.411 C13.2132199,8.8775 12.7887199,8.445 12.2647199,8.445 Z M12.0962199,4.4875 C12.3517199,4.4875 12.5347199,4.542 12.5977199,4.6365 C12.6907199,4.776 12.6677199,5.3075 11.9147199,6.317 C10.9462199,7.6165 9.40121986,8.8925 8.04671986,9.7805 C6.94321986,10.504 5.07821986,11.5125 3.90321986,11.5125 C3.64771986,11.5125 3.46471986,11.458 3.40171986,11.3635 C3.21521986,11.083 3.61221986,10.04 5.02121986,8.601 C5.54371986,9.0665 6.10721986,9.5115 6.67921986,9.917 L6.67921986,9.917 C6.98671986,9.7555 7.25071986,9.597 7.51171986,9.4315 C6.82921986,8.9695 6.18871986,8.4705 5.65121986,7.995 C6.36621986,7.3465 7.16221986,6.738 7.95271986,6.2195 C8.64121986,6.6515 9.30521986,7.133 9.90271986,7.625 C10.1212199,7.429 10.3347199,7.226 10.5382199,7.0195 C9.99971986,6.5705 9.40971986,6.1295 8.77721986,5.711 C9.63321986,5.217 11.1197199,4.4875 12.0962199,4.4875 Z M7.99971986,2 C7.28021986,2 6.72421986,2.686 6.33921986,3.726 C6.58321986,3.827 6.83971986,3.9425 7.12971986,4.0855 C7.42971986,3.253 7.77871986,2.878 7.99971986,2.878 C8.21471986,2.878 8.54971986,3.232 8.84371986,4.0155 C9.13071986,3.8695 9.38371986,3.7515 9.62971986,3.646 C9.24671986,2.6505 8.70071986,2 7.99971986,2 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M7.99960993,0.9998 C11.8598496,0.9998 15,4.13995046 15,7.99940993 C15,11.8596496 11.8598496,14.9998 7.99960993,14.9998 C4.14015046,14.9998 1,11.8596496 1,7.99940993 C1,4.13995046 4.14015046,0.9998 7.99960993,0.9998 Z M8.86971986,11.9145 C8.56971986,12.747 8.22071986,13.122 7.99971986,13.122 C7.78521986,13.122 7.44971986,12.768 7.15571986,11.9845 C6.86571986,12.132 6.61521986,12.2485 6.36971986,12.354 C6.75321986,13.3495 7.29871986,14 7.99971986,14 C8.71921986,14 9.27521986,13.314 9.66021986,12.274 C9.41771986,12.1735 9.16171986,12.0585 8.86971986,11.9145 Z M12.0962199,3.61 C10.8027199,3.61 9.05121986,4.5085 7.94421986,5.19 C6.85371986,4.547 5.16021986,3.717 3.90321986,3.717 C3.19571986,3.717 2.85321986,4 2.69121986,4.238 C2.46021986,4.576 2.34571986,5.1655 2.90071986,6.1455 C2.82221986,6.286 2.77771986,6.448 2.77771986,6.6205 C2.77771986,7.154 3.20271986,7.5865 3.72621986,7.5865 C4.24971986,7.5865 4.67471986,7.154 4.67471986,6.6205 C4.67471986,6.087 4.25021986,5.6545 3.72621986,5.6545 L3.72621986,5.6545 L3.62121986,5.6605 C3.32971986,5.131 3.33321986,4.8355 3.39871986,4.7395 C3.46021986,4.6485 3.64921986,4.595 3.90321986,4.595 C4.30121986,4.595 4.82071986,4.7155 5.41071986,4.9325 C5.98671986,5.145 6.57721986,5.43 7.11871986,5.728 C5.99421986,6.502 5.13171986,7.25 4.36621986,8.027 C4.02471986,8.379 3.68871986,8.7615 3.39771986,9.1515 C2.30221986,10.6215 2.40671986,11.433 2.68771986,11.8555 C3.25671986,12.71 4.68721986,12.3665 5.64571986,12.014 C7.99371986,11.151 11.0597199,8.9165 12.6017199,6.848 C13.6972199,5.3785 13.5927199,4.567 13.3117199,4.1445 C13.1492199,3.9005 12.8067199,3.61 12.0962199,3.61 Z M12.2647199,8.445 C11.7407199,8.445 11.3162199,8.8775 11.3162199,9.411 C11.3162199,9.9445 11.7407199,10.377 12.2647199,10.377 L12.3937199,10.368 C12.6702199,10.88 12.6657199,11.167 12.6012199,11.2615 C12.5392199,11.352 12.3507199,11.4055 12.0967199,11.4055 C11.2957199,11.4055 10.1802199,10.933 9.46171986,10.5765 C9.22171986,10.7475 8.92321986,10.9505 8.63221986,11.136 C9.59521986,11.6545 11.0112199,12.2835 12.0967199,12.2835 C12.8042199,12.2835 13.1467199,12.0005 13.3087199,11.7625 C13.5392199,11.4255 13.6537199,10.8375 13.1032199,9.8625 C13.1737199,9.7275 13.2132199,9.574 13.2132199,9.411 C13.2132199,8.8775 12.7887199,8.445 12.2647199,8.445 Z M12.0962199,4.4875 C12.3517199,4.4875 12.5347199,4.542 12.5977199,4.6365 C12.6907199,4.776 12.6677199,5.3075 11.9147199,6.317 C10.9462199,7.6165 9.40121986,8.8925 8.04671986,9.7805 C6.94321986,10.504 5.07821986,11.5125 3.90321986,11.5125 C3.64771986,11.5125 3.46471986,11.458 3.40171986,11.3635 C3.21521986,11.083 3.61221986,10.04 5.02121986,8.601 C5.54371986,9.0665 6.10721986,9.5115 6.67921986,9.917 L6.67921986,9.917 C6.98671986,9.7555 7.25071986,9.597 7.51171986,9.4315 C6.82921986,8.9695 6.18871986,8.4705 5.65121986,7.995 C6.36621986,7.3465 7.16221986,6.738 7.95271986,6.2195 C8.64121986,6.6515 9.30521986,7.133 9.90271986,7.625 C10.1212199,7.429 10.3347199,7.226 10.5382199,7.0195 C9.99971986,6.5705 9.40971986,6.1295 8.77721986,5.711 C9.63321986,5.217 11.1197199,4.4875 12.0962199,4.4875 Z M7.99971986,2 C7.28021986,2 6.72421986,2.686 6.33921986,3.726 C6.58321986,3.827 6.83971986,3.9425 7.12971986,4.0855 C7.42971986,3.253 7.77871986,2.878 7.99971986,2.878 C8.21471986,2.878 8.54971986,3.232 8.84371986,4.0155 C9.13071986,3.8695 9.38371986,3.7515 9.62971986,3.646 C9.24671986,2.6505 8.70071986,2 7.99971986,2 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M14.6796875,1 C15.1667188,1 15.5,1.316 15.5,1.66666667 L15.5,2.33333333 C15.5,2.684 15.1667188,3 14.6796875,3 L14,3 L14,9.0952381 C14,10.147209 13.1045695,11 12,11 L10.223,11 L12.2674534,13.0443466 C12.4627155,13.2396088 12.4627155,13.5561912 12.2674534,13.7514534 C12.0721912,13.9467155 11.7556088,13.9467155 11.5603466,13.7514534 L8.9995,11.1905 L9,14.5 C9,14.7761424 8.77614237,15 8.5,15 C8.24358208,15 8.03224642,14.8069799 8.00336387,14.5583106 L8,14.5 L7.9995,11.191 L5.43965339,13.7514534 C5.25941141,13.9316954 4.97579588,13.9455601 4.77965028,13.7930477 L4.73254661,13.7514534 C4.55230463,13.5712114 4.53843986,13.2875959 4.69095231,13.0914503 L4.73254661,13.0443466 L6.776,11 L4,11 C2.8954305,11 2,10.147209 2,9.0952381 L2,3 L1.3203125,3 C0.83328125,3 0.5,2.684 0.5,2.33333333 L0.5,1.66666667 C0.5,1.316 0.83328125,1 1.3203125,1 L14.6796875,1 Z M13,3 L3,3 L3,9.05882353 C3,9.57862094 3.44771525,10 4,10 L12,10 C12.5522847,10 13,9.57862094 13,9.05882353 L13,3 Z M8,4.5 L8,6.5 L10,6.5 C10,7.6045695 9.1045695,8.5 8,8.5 C6.8954305,8.5 6,7.6045695 6,6.5 C6,5.3954305 6.8954305,4.5 8,4.5 Z M9,3.5 C10.1045695,3.5 11,4.3954305 11,5.5 L9,5.5 L9,3.5 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M14.6796875,1 C15.1667188,1 15.5,1.316 15.5,1.66666667 L15.5,2.33333333 C15.5,2.684 15.1667188,3 14.6796875,3 L14,3 L14,9.0952381 C14,10.147209 13.1045695,11 12,11 L10.223,11 L12.2674534,13.0443466 C12.4627155,13.2396088 12.4627155,13.5561912 12.2674534,13.7514534 C12.0721912,13.9467155 11.7556088,13.9467155 11.5603466,13.7514534 L8.9995,11.1905 L9,14.5 C9,14.7761424 8.77614237,15 8.5,15 C8.24358208,15 8.03224642,14.8069799 8.00336387,14.5583106 L8,14.5 L7.9995,11.191 L5.43965339,13.7514534 C5.25941141,13.9316954 4.97579588,13.9455601 4.77965028,13.7930477 L4.73254661,13.7514534 C4.55230463,13.5712114 4.53843986,13.2875959 4.69095231,13.0914503 L4.73254661,13.0443466 L6.776,11 L4,11 C2.8954305,11 2,10.147209 2,9.0952381 L2,3 L1.3203125,3 C0.83328125,3 0.5,2.684 0.5,2.33333333 L0.5,1.66666667 C0.5,1.316 0.83328125,1 1.3203125,1 L14.6796875,1 Z M13,3 L3,3 L3,9.05882353 C3,9.57862094 3.44771525,10 4,10 L12,10 C12.5522847,10 13,9.57862094 13,9.05882353 L13,3 Z M8,4.5 L8,6.5 L10,6.5 C10,7.6045695 9.1045695,8.5 8,8.5 C6.8954305,8.5 6,7.6045695 6,6.5 C6,5.3954305 6.8954305,4.5 8,4.5 Z M9,3.5 C10.1045695,3.5 11,4.3954305 11,5.5 L9,5.5 L9,3.5 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8.00031808,0.99950155 C11.8603458,0.99950155 14.9999738,4.1390565 14.9999738,7.99950155 C14.9999738,11.8599466 11.8603458,14.9995015 8.00031808,14.9995015 C4.13971544,14.9995015 0.999973754,11.8600603 0.999973754,7.99950155 C0.999973754,4.13894278 4.13971544,0.99950155 8.00031808,0.99950155 Z M11.4999738,8.99950155 C12.0526404,8.99950155 12.4999738,8.55150155 12.4999738,7.99950155 C12.4999738,7.44683488 12.0526404,6.99950155 11.4999738,6.99950155 C10.9473071,6.99950155 10.4999738,7.44683488 10.4999738,7.99950155 C10.4999738,8.55150155 10.9473071,8.99950155 11.4999738,8.99950155 Z M7.99997375,8.99950155 C8.55264042,8.99950155 8.99997375,8.55150155 8.99997375,7.99950155 C8.99997375,7.44683488 8.55264042,6.99950155 7.99997375,6.99950155 C7.44797375,6.99950155 6.99997375,7.44683488 6.99997375,7.99950155 C6.99997375,8.55150155 7.44797375,8.99950155 7.99997375,8.99950155 Z M4.49997375,8.99950155 C5.05264042,8.99950155 5.49997375,8.55150155 5.49997375,7.99950155 C5.49997375,7.44683488 5.05264042,6.99950155 4.49997375,6.99950155 C3.94797375,6.99950155 3.49997375,7.44683488 3.49997375,7.99950155 C3.49997375,8.55150155 3.94797375,8.99950155 4.49997375,8.99950155 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M8.00031808,0.99950155 C11.8603458,0.99950155 14.9999738,4.1390565 14.9999738,7.99950155 C14.9999738,11.8599466 11.8603458,14.9995015 8.00031808,14.9995015 C4.13971544,14.9995015 0.999973754,11.8600603 0.999973754,7.99950155 C0.999973754,4.13894278 4.13971544,0.99950155 8.00031808,0.99950155 Z M11.4999738,8.99950155 C12.0526404,8.99950155 12.4999738,8.55150155 12.4999738,7.99950155 C12.4999738,7.44683488 12.0526404,6.99950155 11.4999738,6.99950155 C10.9473071,6.99950155 10.4999738,7.44683488 10.4999738,7.99950155 C10.4999738,8.55150155 10.9473071,8.99950155 11.4999738,8.99950155 Z M7.99997375,8.99950155 C8.55264042,8.99950155 8.99997375,8.55150155 8.99997375,7.99950155 C8.99997375,7.44683488 8.55264042,6.99950155 7.99997375,6.99950155 C7.44797375,6.99950155 6.99997375,7.44683488 6.99997375,7.99950155 C6.99997375,8.55150155 7.44797375,8.99950155 7.99997375,8.99950155 Z M4.49997375,8.99950155 C5.05264042,8.99950155 5.49997375,8.55150155 5.49997375,7.99950155 C5.49997375,7.44683488 5.05264042,6.99950155 4.49997375,6.99950155 C3.94797375,6.99950155 3.49997375,7.44683488 3.49997375,7.99950155 C3.49997375,8.55150155 3.94797375,8.99950155 4.49997375,8.99950155 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

-6
View File
@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-rule="evenodd">
<path fill="#000" d="M1.85789238,2.64258737 C4.86313703,2.21112969 6.5771729,2.75883866 7,4.28571429 L7,13.7857143 C6.27058294,12.8374721 4.43450345,12.3388115 1.49176152,12.2897326 C1.2188519,12.2852804 1,12.062748 1,11.7898021 L1,3.63241367 C1.00002467,3.13504017 1.36556687,2.71326968 1.85789238,2.64258737 Z"/>
<path fill="#000" d="M9.85789238,2.64258737 C12.863137,2.21112969 14.5771729,2.75883866 15,4.28571429 L15,13.7857143 C14.2705829,12.8374721 12.4345034,12.3388115 9.49176152,12.2897326 C9.2188519,12.2852804 9,12.062748 9,11.7898021 L9,3.63241367 C9.00002467,3.13504017 9.36556687,2.71326968 9.85789238,2.64258737 Z" transform="matrix(-1 0 0 1 24 0)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 810 B

-6
View File
@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-opacity=".6" fill-rule="evenodd">
<path fill="#FFF" d="M1.85789238,2.64258737 C4.86313703,2.21112969 6.5771729,2.75883866 7,4.28571429 L7,13.7857143 C6.27058294,12.8374721 4.43450345,12.3388115 1.49176152,12.2897326 C1.2188519,12.2852804 1,12.062748 1,11.7898021 L1,3.63241367 C1.00002467,3.13504017 1.36556687,2.71326968 1.85789238,2.64258737 Z"/>
<path fill="#FFF" d="M9.85789238,2.64258737 C12.863137,2.21112969 14.5771729,2.75883866 15,4.28571429 L15,13.7857143 C14.2705829,12.8374721 12.4345034,12.3388115 9.49176152,12.2897326 C9.2188519,12.2852804 9,12.062748 9,11.7898021 L9,3.63241367 C9.00002467,3.13504017 9.36556687,2.71326968 9.85789238,2.64258737 Z" transform="matrix(-1 0 0 1 24 0)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 828 B

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.0543618 14.1841222,13.9181651 13.1492623,13.9945143 L13,14 L13,14 L3,14 Z M14,5 L2,5 L2,12 C2,12.5522847 2.44771525,13 3,13 L8.01233301,13.0001639 C8.01943442,12.9772458 8.02824971,12.9546419 8.0388094,12.9325301 L8.30383017,12.3775926 C8.34459502,12.2912196 8.34695846,12.1917404 8.30983658,12.1028011 C8.27399122,12.0159757 8.20318605,11.9486684 8.11444707,11.9170901 L7.53244707,11.7100901 C7.33313205,11.6391997 7.19999981,11.4505463 7.19999981,11.2389998 L7.19999981,10.1609998 C7.19999981,9.9491733 7.33347927,9.7603339 7.53316619,9.6896543 L8.11249002,9.4846101 C8.20258302,9.4521442 8.27390085,9.3842428 8.31058669,9.2953916 C8.34695846,9.2082592 8.34459502,9.10878 8.3048094,9.0244696 L8.0388094,8.46746956 C7.94749917,8.2762673 7.98662009,8.04827275 8.13644642,7.89844642 L8.89844642,7.13644642 C9.04827275,6.98662009 9.2762673,6.94749917 9.46746956,7.0388094 L10.022407,7.30383017 C10.10878,7.34459502 10.2082592,7.34695846 10.2971985,7.30983658 C10.3842159,7.27391194 10.4518724,7.202745 10.4837447,7.11391109 L10.6897447,6.53291109 C10.7604992,6.33335606 10.9492726,6.19999981 11.1609998,6.19999981 L12.2389998,6.19999981 C12.450727,6.19999981 12.6395004,6.33335606 12.7102549,6.53291109 L12.9156316,7.11216331 C12.9481272,7.202745 13.0157837,7.27391194 13.104608,7.31058669 C13.1917404,7.34695846 13.2912196,7.34459502 13.3755301,7.3048094 L13.9325301,7.0388094 L14,7.013 L14,5 Z M11.6999998,9.1999998 C10.8729998,9.1999998 10.1999998,9.8729998 10.1999998,10.6999998 C10.1999998,11.5269998 10.8729998,12.1999998 11.6999998,12.1999998 C12.5269998,12.1999998 13.1999998,11.5269998 13.1999998,10.6999998 C13.1999998,9.8729998 12.5269998,9.1999998 11.6999998,9.1999998 Z M13,3 L12,3 L12,4 L13,4 L13,3 Z M9,3 L8,3 L8,4 L9,4 L9,3 Z M11,3 L10,3 L10,4 L11,4 L11,3 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M3,14 C1.8954305,14 1,13.1045695 1,12 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 C14.1045695,2 15,2.8954305 15,4 L15,12 C15,13.0543618 14.1841222,13.9181651 13.1492623,13.9945143 L13,14 L13,14 L3,14 Z M14,5 L2,5 L2,12 C2,12.5522847 2.44771525,13 3,13 L8.01233301,13.0001639 C8.01943442,12.9772458 8.02824971,12.9546419 8.0388094,12.9325301 L8.30383017,12.3775926 C8.34459502,12.2912196 8.34695846,12.1917404 8.30983658,12.1028011 C8.27399122,12.0159757 8.20318605,11.9486684 8.11444707,11.9170901 L7.53244707,11.7100901 C7.33313205,11.6391997 7.19999981,11.4505463 7.19999981,11.2389998 L7.19999981,10.1609998 C7.19999981,9.9491733 7.33347927,9.7603339 7.53316619,9.6896543 L8.11249002,9.4846101 C8.20258302,9.4521442 8.27390085,9.3842428 8.31058669,9.2953916 C8.34695846,9.2082592 8.34459502,9.10878 8.3048094,9.0244696 L8.0388094,8.46746956 C7.94749917,8.2762673 7.98662009,8.04827275 8.13644642,7.89844642 L8.89844642,7.13644642 C9.04827275,6.98662009 9.2762673,6.94749917 9.46746956,7.0388094 L10.022407,7.30383017 C10.10878,7.34459502 10.2082592,7.34695846 10.2971985,7.30983658 C10.3842159,7.27391194 10.4518724,7.202745 10.4837447,7.11391109 L10.6897447,6.53291109 C10.7604992,6.33335606 10.9492726,6.19999981 11.1609998,6.19999981 L12.2389998,6.19999981 C12.450727,6.19999981 12.6395004,6.33335606 12.7102549,6.53291109 L12.9156316,7.11216331 C12.9481272,7.202745 13.0157837,7.27391194 13.104608,7.31058669 C13.1917404,7.34695846 13.2912196,7.34459502 13.3755301,7.3048094 L13.9325301,7.0388094 L14,7.013 L14,5 Z M11.6999998,9.1999998 C10.8729998,9.1999998 10.1999998,9.8729998 10.1999998,10.6999998 C10.1999998,11.5269998 10.8729998,12.1999998 11.6999998,12.1999998 C12.5269998,12.1999998 13.1999998,11.5269998 13.1999998,10.6999998 C13.1999998,9.8729998 12.5269998,9.1999998 11.6999998,9.1999998 Z M13,3 L12,3 L12,4 L13,4 L13,3 Z M9,3 L8,3 L8,4 L9,4 L9,3 Z M11,3 L10,3 L10,4 L11,4 L11,3 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M12,2 C13.1045695,2 14,2.8954305 14,4 L14,13 C14,14.1045695 13.1045695,15 12,15 L4,15 C2.8954305,15 2,14.1045695 2,13 L2,4 C2,2.8954305 2.8954305,2 4,2 L12,2 Z M4.5,12 L3.5,12 C3.22385763,12 3,12.2238576 3,12.5 L3,12.5 L3,13 C3,13.5522847 3.44771525,14 4,14 L4,14 L4.5,14 C4.77614237,14 5,13.7761424 5,13.5 L5,13.5 L5,12.5 C5,12.2238576 4.77614237,12 4.5,12 L4.5,12 Z M12.5,12 L11.5,12 C11.2238576,12 11,12.2238576 11,12.5 L11,12.5 L11,13.5 C11,13.7761424 11.2238576,14 11.5,14 L11.5,14 L12,14 C12.5522847,14 13,13.5522847 13,13 L13,13 L13,12.5 C13,12.2238576 12.7761424,12 12.5,12 L12.5,12 Z M4.5,9 L3.5,9 C3.22385763,9 3,9.22385763 3,9.5 L3,9.5 L3,10.5 C3,10.7761424 3.22385763,11 3.5,11 L3.5,11 L4.5,11 C4.77614237,11 5,10.7761424 5,10.5 L5,10.5 L5,9.5 C5,9.22385763 4.77614237,9 4.5,9 L4.5,9 Z M12.5,9 L11.5,9 C11.2238576,9 11,9.22385763 11,9.5 L11,9.5 L11,10.5 C11,10.7761424 11.2238576,11 11.5,11 L11.5,11 L12.5,11 C12.7761424,11 13,10.7761424 13,10.5 L13,10.5 L13,9.5 C13,9.22385763 12.7761424,9 12.5,9 L12.5,9 Z M4.5,6 L3.5,6 C3.22385763,6 3,6.22385763 3,6.5 L3,6.5 L3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L3.5,8 L4.5,8 C4.77614237,8 5,7.77614237 5,7.5 L5,7.5 L5,6.5 C5,6.22385763 4.77614237,6 4.5,6 L4.5,6 Z M12.5,6 L11.5,6 C11.2238576,6 11,6.22385763 11,6.5 L11,6.5 L11,7.5 C11,7.77614237 11.2238576,8 11.5,8 L11.5,8 L12.5,8 C12.7761424,8 13,7.77614237 13,7.5 L13,7.5 L13,6.5 C13,6.22385763 12.7761424,6 12.5,6 L12.5,6 Z M4.5,3 L4,3 C3.44771525,3 3,3.44771525 3,4 L3,4 L3,4.5 C3,4.77614237 3.22385763,5 3.5,5 L3.5,5 L4.5,5 C4.77614237,5 5,4.77614237 5,4.5 L5,4.5 L5,3.5 C5,3.22385763 4.77614237,3 4.5,3 L4.5,3 Z M12,3 L11.5,3 C11.2238576,3 11,3.22385763 11,3.5 L11,3.5 L11,4.5 C11,4.77614237 11.2238576,5 11.5,5 L11.5,5 L12.5,5 C12.7761424,5 13,4.77614237 13,4.5 L13,4.5 L13,4 C13,3.44771525 12.5522847,3 12,3 L12,3 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="#FFF" fill-opacity=".6" fill-rule="evenodd" d="M12,2 C13.1045695,2 14,2.8954305 14,4 L14,13 C14,14.1045695 13.1045695,15 12,15 L4,15 C2.8954305,15 2,14.1045695 2,13 L2,4 C2,2.8954305 2.8954305,2 4,2 L12,2 Z M4.5,12 L3.5,12 C3.22385763,12 3,12.2238576 3,12.5 L3,12.5 L3,13 C3,13.5522847 3.44771525,14 4,14 L4,14 L4.5,14 C4.77614237,14 5,13.7761424 5,13.5 L5,13.5 L5,12.5 C5,12.2238576 4.77614237,12 4.5,12 L4.5,12 Z M12.5,12 L11.5,12 C11.2238576,12 11,12.2238576 11,12.5 L11,12.5 L11,13.5 C11,13.7761424 11.2238576,14 11.5,14 L11.5,14 L12,14 C12.5522847,14 13,13.5522847 13,13 L13,13 L13,12.5 C13,12.2238576 12.7761424,12 12.5,12 L12.5,12 Z M4.5,9 L3.5,9 C3.22385763,9 3,9.22385763 3,9.5 L3,9.5 L3,10.5 C3,10.7761424 3.22385763,11 3.5,11 L3.5,11 L4.5,11 C4.77614237,11 5,10.7761424 5,10.5 L5,10.5 L5,9.5 C5,9.22385763 4.77614237,9 4.5,9 L4.5,9 Z M12.5,9 L11.5,9 C11.2238576,9 11,9.22385763 11,9.5 L11,9.5 L11,10.5 C11,10.7761424 11.2238576,11 11.5,11 L11.5,11 L12.5,11 C12.7761424,11 13,10.7761424 13,10.5 L13,10.5 L13,9.5 C13,9.22385763 12.7761424,9 12.5,9 L12.5,9 Z M4.5,6 L3.5,6 C3.22385763,6 3,6.22385763 3,6.5 L3,6.5 L3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L3.5,8 L4.5,8 C4.77614237,8 5,7.77614237 5,7.5 L5,7.5 L5,6.5 C5,6.22385763 4.77614237,6 4.5,6 L4.5,6 Z M12.5,6 L11.5,6 C11.2238576,6 11,6.22385763 11,6.5 L11,6.5 L11,7.5 C11,7.77614237 11.2238576,8 11.5,8 L11.5,8 L12.5,8 C12.7761424,8 13,7.77614237 13,7.5 L13,7.5 L13,6.5 C13,6.22385763 12.7761424,6 12.5,6 L12.5,6 Z M4.5,3 L4,3 C3.44771525,3 3,3.44771525 3,4 L3,4 L3,4.5 C3,4.77614237 3.22385763,5 3.5,5 L3.5,5 L4.5,5 C4.77614237,5 5,4.77614237 5,4.5 L5,4.5 L5,3.5 C5,3.22385763 4.77614237,3 4.5,3 L4.5,3 Z M12,3 L11.5,3 C11.2238576,3 11,3.22385763 11,3.5 L11,3.5 L11,4.5 C11,4.77614237 11.2238576,5 11.5,5 L11.5,5 L12.5,5 C12.7761424,5 13,4.77614237 13,4.5 L13,4.5 L13,4 C13,3.44771525 12.5522847,3 12,3 L12,3 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8,1 C11.8659932,1 15,4.13400675 15,8 C15,11.8659932 11.8659932,15 8,15 C4.13400675,15 1,11.8659932 1,8 C1,4.13400675 4.13400675,1 8,1 Z M9.5,8 L6.5,8 C6.22385763,8 6,8.22385763 6,8.5 C6,8.77614237 5.77614237,9 5.5,9 L5.5,9 L5,9 C4.89014373,9 4.78478689,9.04364023 4.70710678,9.12132034 C4.54534632,9.2830808 4.54534632,9.54534632 4.70710678,9.70710678 L4.70710678,9.70710678 L7.64644661,12.6464466 C7.84170876,12.8417088 8.15829124,12.8417088 8.35355339,12.6464466 L8.35355339,12.6464466 L11.2928932,9.70710678 C11.3705733,9.62942667 11.4142136,9.52406983 11.4142136,9.41421356 C11.4142136,9.18544973 11.2287638,9 11,9 L11,9 L10.5,9 C10.2238576,9 10,8.77614237 10,8.5 C10,8.22385763 9.77614237,8 9.5,8 L9.5,8 Z M9.5,6 L6.5,6 C6.22385763,6 6,6.22385763 6,6.5 C6,6.77614237 6.22385763,7 6.5,7 L6.5,7 L9.5,7 C9.77614237,7 10,6.77614237 10,6.5 C10,6.22385763 9.77614237,6 9.5,6 L9.5,6 Z M9.5,4 L6.5,4 C6.22385763,4 6,4.22385763 6,4.5 C6,4.77614237 6.22385763,5 6.5,5 L6.5,5 L9.5,5 C9.77614237,5 10,4.77614237 10,4.5 C10,4.22385763 9.77614237,4 9.5,4 L9.5,4 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

-57
View File
@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg4"
sodipodi:docname="downloads-symbolic_dark.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="982"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
fill="#FFF"
fill-opacity=".8"
fill-rule="evenodd"
d="M8,1 C11.8659932,1 15,4.13400675 15,8 C15,11.8659932 11.8659932,15 8,15 C4.13400675,15 1,11.8659932 1,8 C1,4.13400675 4.13400675,1 8,1 Z M9.5,8 L6.5,8 C6.22385763,8 6,8.22385763 6,8.5 C6,8.77614237 5.77614237,9 5.5,9 L5.5,9 L5,9 C4.89014373,9 4.78478689,9.04364023 4.70710678,9.12132034 C4.54534632,9.2830808 4.54534632,9.54534632 4.70710678,9.70710678 L4.70710678,9.70710678 L7.64644661,12.6464466 C7.84170876,12.8417088 8.15829124,12.8417088 8.35355339,12.6464466 L8.35355339,12.6464466 L11.2928932,9.70710678 C11.3705733,9.62942667 11.4142136,9.52406983 11.4142136,9.41421356 C11.4142136,9.18544973 11.2287638,9 11,9 L11,9 L10.5,9 C10.2238576,9 10,8.77614237 10,8.5 C10,8.22385763 9.77614237,8 9.5,8 L9.5,8 Z M9.5,6 L6.5,6 C6.22385763,6 6,6.22385763 6,6.5 C6,6.77614237 6.22385763,7 6.5,7 L6.5,7 L9.5,7 C9.77614237,7 10,6.77614237 10,6.5 C10,6.22385763 9.77614237,6 9.5,6 L9.5,6 Z M9.5,4 L6.5,4 C6.22385763,4 6,4.22385763 6,4.5 C6,4.77614237 6.22385763,5 6.5,5 L6.5,5 L9.5,5 C9.77614237,5 10,4.77614237 10,4.5 C10,4.22385763 9.77614237,4 9.5,4 L9.5,4 Z"
id="path2"
style="fill:#ffffff;fill-opacity:0.60000002" />
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

-68
View File
@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="svg8"
sodipodi:docname="homepage.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="982"
id="namedview10"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<!-- Generator: Sketch 56.3 (81716) - https://sketch.com -->
<title
id="title2">category_recommend</title>
<desc
id="desc4">Created with Sketch.</desc>
<g
id="category_recommend"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
style="fill:#000000;fill-opacity:0.86666667">
<path
d="M8,12.6085145 L4.54924088,14.5160472 C4.06572729,14.783327 3.74708518,14.5504931 3.83503048,14.0113448 L4.5,9.93475242 L1.69148737,7.05624503 C1.30958944,6.6648293 1.44637232,6.27932454 1.97881505,6.19797453 L5.83688104,5.60851449 L7.5726373,1.91049416 C7.8086632,1.40764212 8.19196238,1.40897492 8.4273627,1.91049416 L10.163119,5.60851449 L14.0211849,6.19797453 C14.5617696,6.28056851 14.6893983,6.66586674 14.3085126,7.05624503 L11.5,9.93475242 L12.1649695,14.0113448 C12.2540356,14.557364 11.9269904,14.7793014 11.4507591,14.5160472 L8,12.6085145 Z"
id="Star"
fill="#536076"
style="fill:#000000;fill-opacity:0.86666667" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

-68
View File
@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="svg8"
sodipodi:docname="homepage_dark.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="982"
id="namedview10"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-15.932203"
inkscape:cy="2.5762712"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<!-- Generator: Sketch 56.3 (81716) - https://sketch.com -->
<title
id="title2">category_recommend</title>
<desc
id="desc4">Created with Sketch.</desc>
<g
id="category_recommend"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
style="fill:#ffffff;fill-opacity:0.60000002">
<path
d="M8,12.6085145 L4.54924088,14.5160472 C4.06572729,14.783327 3.74708518,14.5504931 3.83503048,14.0113448 L4.5,9.93475242 L1.69148737,7.05624503 C1.30958944,6.6648293 1.44637232,6.27932454 1.97881505,6.19797453 L5.83688104,5.60851449 L7.5726373,1.91049416 C7.8086632,1.40764212 8.19196238,1.40897492 8.4273627,1.91049416 L10.163119,5.60851449 L14.0211849,6.19797453 C14.5617696,6.28056851 14.6893983,6.66586674 14.3085126,7.05624503 L11.5,9.93475242 L12.1649695,14.0113448 C12.2540356,14.557364 11.9269904,14.7793014 11.4507591,14.5160472 L8,12.6085145 Z"
id="Star"
fill="#C5CFE0"
style="fill:#ffffff;fill-opacity:0.60000002" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

-54
View File
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
height="16"
width="16"
sodipodi:docname="refresh-page-dark.svg"
xml:space="preserve"
viewBox="0 0 16 16"
y="0px"
x="0px"
id="Layer_1"
version="1.1"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
inkscape:current-layer="Layer_1"
inkscape:window-maximized="1"
inkscape:window-y="0"
inkscape:window-x="0"
inkscape:cy="8.8351119"
inkscape:cx="12.452215"
inkscape:zoom="34.711876"
showgrid="true"
id="namedview5"
inkscape:window-height="958"
inkscape:window-width="1920"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff"><inkscape:grid
id="grid834"
type="xygrid" /></sodipodi:namedview>
<g
style="fill:#ffffff;fill-opacity:0.60000002"
transform="scale(0.03125,0.0312082)"
id="XMLID_2_">
<path
style="fill:#ffffff;fill-opacity:0.60000002"
d="M 436.6,75.4 C 390.1,28.9 326.7,0 256,0 114.5,0 0,114.5 0,256 0,397.5 114.5,512 256,512 375.2,512 474.8,430.1 503.6,320.2 h -67 C 410.5,394.7 339.8,447.7 256,447.7 149.9,447.7 64.2,362.1 64.2,255.9 64.2,149.7 149.9,64.2 256,64.2 c 53.1,0 100.5,22.3 135,56.8 L 287.7,224.3 H 512 V 0 Z"
id="XMLID_4_" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

-52
View File
@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
height="16"
width="16"
sodipodi:docname="refresh-page.svg"
xml:space="preserve"
viewBox="0 0 16 16"
y="0px"
x="0px"
id="Layer_1"
version="1.1"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
inkscape:current-layer="Layer_1"
inkscape:window-maximized="1"
inkscape:window-y="0"
inkscape:window-x="0"
inkscape:cy="8.8351119"
inkscape:cx="12.452215"
inkscape:zoom="34.711876"
showgrid="true"
id="namedview5"
inkscape:window-height="958"
inkscape:window-width="1920"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff"><inkscape:grid
id="grid834"
type="xygrid" /></sodipodi:namedview>
<g
transform="scale(0.03125,0.0312082)"
id="XMLID_2_">
<path
d="M 436.6,75.4 C 390.1,28.9 326.7,0 256,0 114.5,0 0,114.5 0,256 0,397.5 114.5,512 256,512 375.2,512 474.8,430.1 503.6,320.2 h -67 C 410.5,394.7 339.8,447.7 256,447.7 149.9,447.7 64.2,362.1 64.2,255.9 64.2,149.7 149.9,64.2 256,64.2 c 53.1,0 100.5,22.3 135,56.8 L 287.7,224.3 H 512 V 0 Z"
id="XMLID_4_" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M3.5,14 C3.22385763,14 3,13.7761424 3,13.5 C3,13.2238576 3.22385763,13 3.5,13 L7,13 L7,12 L2,12 C1.44771525,12 1,11.5522847 1,11 L15,11 C15,11.5522847 14.5522847,12 14,12 L9,12 L9,13 L12.5,13 C12.7761424,13 13,13.2238576 13,13.5 C13,13.7761424 12.7761424,14 12.5,14 L3.5,14 Z M13,2 C14.1045695,2 15,2.8954305 15,4 L15,10 L1,10 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 494 B

-57
View File
@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg4"
sodipodi:docname="theme-symbolic_dark.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="982"
id="namedview6"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
fill="#FFF"
fill-opacity=".8"
fill-rule="evenodd"
d="M3.5,14 C3.22385763,14 3,13.7761424 3,13.5 C3,13.2238576 3.22385763,13 3.5,13 L7,13 L7,12 L2,12 C1.44771525,12 1,11.5522847 1,11 L15,11 C15,11.5522847 14.5522847,12 14,12 L9,12 L9,13 L12.5,13 C12.7761424,13 13,13.2238576 13,13.5 C13,13.7761424 12.7761424,14 12.5,14 L3.5,14 Z M13,2 C14.1045695,2 15,2.8954305 15,4 L15,10 L1,10 L1,4 C1,2.8954305 1.8954305,2 3,2 L13,2 Z"
id="path2"
style="opacity:1;fill:#ffffff;fill-opacity:0.60000002" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

-253
View File
@@ -1,253 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
sodipodi:docname="spark-logo.svg"
inkscape:version="1.1 (c4e8f9e, 2021-05-24)"
id="svg8"
version="1.1"
viewBox="0 0 180.00012 48.251057"
height="48.251057mm"
width="180.00012mm"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2">
<linearGradient
id="linearGradient1200"
inkscape:collect="always">
<stop
id="stop1196"
offset="0"
style="stop-color:#000000;stop-opacity:0.1299435" />
<stop
id="stop1198"
offset="1"
style="stop-color:#dadada;stop-opacity:0.81960785" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient1138">
<stop
style="stop-color:#99e7ea;stop-opacity:1"
offset="0"
id="stop1134" />
<stop
style="stop-color:#007ffc;stop-opacity:1"
offset="1"
id="stop1136" />
</linearGradient>
<linearGradient
id="linearGradient1128"
inkscape:collect="always">
<stop
id="stop1124"
offset="0"
style="stop-color:#99e7ea;stop-opacity:1" />
<stop
id="stop1126"
offset="1"
style="stop-color:#007ffc;stop-opacity:1" />
</linearGradient>
<inkscape:path-effect
only_selected="false"
apply_with_weight="true"
apply_no_weight="true"
helper_size="0"
steps="2"
weight="33.333333"
is_visible="true"
id="path-effect960"
effect="bspline"
lpeversion="0" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.98112945,0,3.7714702)"
r="90.135414"
fy="199.86011"
fx="100.35268"
cy="199.86011"
cx="100.35268"
id="radialGradient1130"
xlink:href="#linearGradient1128"
inkscape:collect="always" />
<radialGradient
r="90.135414"
fy="199.86011"
fx="100.35268"
cy="199.86011"
cx="100.35268"
gradientTransform="matrix(1,0,0,0.98112945,0,3.7714702)"
gradientUnits="userSpaceOnUse"
id="radialGradient1132"
xlink:href="#linearGradient1138"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.98112945,0,3.7714702)"
r="90.135414"
fy="199.86011"
fx="100.35268"
cy="199.86011"
cx="100.35268"
id="radialGradient1202"
xlink:href="#linearGradient1200"
inkscape:collect="always" />
<filter
id="filter1448"
inkscape:label="Drop Shadow"
style="color-interpolation-filters:sRGB">
<feFlood
id="feFlood1438"
result="flood"
flood-color="rgb(145,145,145)"
flood-opacity="0.372549" />
<feComposite
id="feComposite1440"
result="composite1"
operator="in"
in2="SourceGraphic"
in="flood" />
<feGaussianBlur
id="feGaussianBlur1442"
result="blur"
stdDeviation="5.2918"
in="composite1" />
<feOffset
id="feOffset1444"
result="offset"
dy="0"
dx="0" />
<feComposite
id="feComposite1446"
result="composite2"
operator="over"
in2="offset"
in="SourceGraphic" />
</filter>
<filter
id="filter2201"
inkscape:label="Drop Shadow"
style="color-interpolation-filters:sRGB">
<feFlood
id="feFlood2191"
result="flood"
flood-color="rgb(145,145,145)"
flood-opacity="0.372549" />
<feComposite
id="feComposite2193"
result="composite1"
operator="in"
in2="SourceGraphic"
in="flood" />
<feGaussianBlur
id="feGaussianBlur2195"
result="blur"
stdDeviation="3.76995"
in="composite1" />
<feOffset
id="feOffset2197"
result="offset"
dy="0"
dx="0" />
<feComposite
id="feComposite2199"
result="composite2"
operator="over"
in2="offset"
in="SourceGraphic" />
</filter>
</defs>
<sodipodi:namedview
inkscape:document-rotation="0"
inkscape:window-maximized="1"
inkscape:window-y="0"
inkscape:window-x="0"
inkscape:window-height="946"
inkscape:window-width="1920"
showgrid="false"
inkscape:current-layer="layer2"
inkscape:document-units="mm"
inkscape:cy="332.14286"
inkscape:cx="520.71429"
inkscape:zoom="0.7"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
inkscape:pagecheckerboard="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-34.291348,-63.035531)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1" />
<g
inkscape:label="Layer 2"
id="layer2"
inkscape:groupmode="layer"
transform="translate(-34.291348,33.964469)">
<path
inkscape:connector-curvature="0"
id="path1002"
d="m 50.895965,-25.80076 c 0,0 3.210258,-0.04536 6.509677,1.995776 3.299426,2.041135 5.216663,3.991553 5.840878,5.261592 0.624212,1.270041 2.67521,3.492613 2.630628,7.574884 -0.04461,4.0822665 -0.98091,6.8037874 -2.586039,9.0717077 -1.605128,2.26792732 -4.503272,3.9915518 -7.981044,4.0822737 -3.477778,0.090717 -5.707121,-2.17720666 -6.465096,-3.4472534 -0.757975,-1.270036 -1.070084,-3.9915518 -0.133761,-5.9419619 0.936325,-1.9504282 2.40769,-1.9504282 2.898147,-1.7689877 0.490455,0.181438 0.624213,0.4535811 0.891735,0.9525256 0.26752,0.4989447 0.44587,0.4082311 0.847161,0.1360795 0.401275,-0.2721541 0.535033,-0.5896654 0.445866,-0.9978916 -0.08917,-0.408231 -0.62422,-0.9071732 -1.070092,-1.0432502 -0.445865,-0.1360747 -1.070085,-0.5443017 -1.961822,-0.4082167 -0.891736,0.136065 -2.630623,0.5896548 -4.101988,2.585427 -1.471365,1.9957744 -1.29302,5.0801606 -0.401281,6.5316309 0.891737,1.45147531 2.586035,4.1729873 6.331332,5.1255217 3.745301,0.9525364 9.809105,-1.8597006 11.904684,-6.2141209 2.095577,-4.3544229 2.140168,-6.3955562 2.051001,-9.9788777 -0.08917,-3.583335 -3.254842,-8.935643 -6.777199,-10.886061 -3.522357,-1.950419 -6.152982,-3.084383 -8.872787,-2.630797 z"
style="fill:#ffc344;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1012"
d="m 52.759546,-7.6807986 c 0,0 -0.882776,-0.833911 -1.670967,0.6414663 -0.788192,1.4753675 -1.166523,2.790373 -0.378332,4.3940472 0.78819,1.6036647 2.427624,2.56586017 4.949854,2.53379165 2.522203,-0.0321084 4.382334,-0.64146726 5.485801,-2.46964635 1.103472,-1.8281836 1.954712,-3.1752577 2.049297,-3.8487984 0.09459,-0.6735444 0.599029,0.096216 0.441394,0.6735407 -0.15764,0.5773125 -0.126112,1.6998816 0.315273,1.4753653 0.441388,-0.2245063 0.788195,-0.5773163 0.851243,-0.4169509 0.06306,0.1603616 -0.50444,1.154644 -0.772422,1.6517766 -0.267993,0.4971326 -1.103472,1.699893 -1.592156,2.16494892 -0.488669,0.46506666 -1.166517,1.1225704 -1.970475,1.6036691 C 59.664103,1.2035109 58.418766,1.7647989 57.725156,1.893092 57.031546,2.0213857 55.644328,2.2940039 54.856131,2.2619316 54.067946,2.2298548 53.059055,2.0855246 51.939826,1.5242442 50.820592,0.96296626 49.606778,0.0969782 49.133864,-0.76900099 48.66095,-1.6349808 47.935815,-2.4207789 48.093452,-4.6017617 c 0.15764,-2.1809854 0.86701,-3.3035574 1.40298,-3.8167243 0.53597,-0.5131766 1.32416,-0.7376922 1.844369,-0.6254295 0.520205,0.1122529 0.851246,0.4169555 0.977357,0.6414613 0.126107,0.224512 0.331042,0.6414675 0.441388,0.7216556 z"
style="fill:#f06767;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1014"
d="m 60.767575,3.8655962 c 0,0 3.783317,-2.2130621 5.548864,-5.7090499 1.765551,-3.4959942 2.522214,-5.7411261 2.30152,-9.1729813 -0.220695,-3.431843 -0.756663,-1.731959 -0.157641,-3.207334 0.599026,-1.475377 -0.378328,-4.394049 0.03152,-4.586488 0.409861,-0.19244 1.292637,1.282934 1.544859,2.469649 0.252214,1.186712 1.355684,4.843067 0.472911,9.4937107 -0.882773,4.6506303 -2.963589,6.51088559 -4.350812,7.76175223 C 64.77157,2.1657114 61.618812,4.3467019 61.145898,4.314627 60.67298,4.2825186 60.609928,4.2825186 60.76756,3.8655962 Z"
style="fill:#3f62eb;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1016"
d="m 53.957602,-2.8698091 c 0,0 2.017773,0.4490302 3.562621,-0.5131634 1.544859,-0.9622063 2.742913,-2.5337986 2.932073,-3.1431917 0.189165,-0.6093954 0.220697,0.5452465 0.441386,-0.032045 0.220692,-0.5773293 1.10347,-1.7319649 0.662081,-4.4261318 -0.441389,-2.694157 -0.472916,-2.822457 -1.292627,-4.265758 -0.819727,-1.443301 -2.774446,-3.431845 -3.972493,-4.073313 -1.198047,-0.641466 -2.86901,-1.603666 -5.170538,-1.53952 -2.301517,0.06415 -1.544853,-0.09622 -3.751788,0.288661 -2.206938,0.384879 -4.193179,1.4433 -4.855258,2.02062 -0.66208,0.577321 -2.427629,2.148917 -3.058183,3.014896 -0.630554,0.865981 -2.364573,2.822454 -3.278875,5.5486918 -0.914302,2.7262327 -1.292635,3.0148925 -1.35569,4.8109998 -0.06306,1.7961094 0.157637,2.2772018 -0.220692,2.4375779 -0.378332,0.1603616 -0.315277,-1.3470823 -0.283751,-2.4055093 0.03153,-1.0584128 0.03153,-3.8167249 1.418745,-6.8957642 1.387216,-3.079043 3.846373,-5.644912 5.23359,-6.575039 1.387216,-0.930126 2.995127,-2.180987 5.485811,-2.790382 2.490685,-0.609392 4.981368,-0.513172 6.526228,-0.224513 1.544859,0.288661 3.94096,1.282935 5.23359,2.277208 1.292636,0.994275 2.711385,2.213062 3.78332,4.20161 1.07194,1.988545 1.355684,4.522341 1.324159,5.5807587 -0.03152,1.0584266 -0.567498,3.4960027 -1.387216,4.6827127 -0.819721,1.186715 -1.923185,2.597942 -3.05818,3.1111149 -1.135,0.5131697 -2.522222,0.6735396 -3.657204,0.1603641 C 54.08371,-2.132102 54.146768,-2.3245385 53.957602,-2.869785 Z"
style="fill:#fce102;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1018"
d="m 53.957602,-2.8698091 c 0,0 1.597697,0.4513829 2.946439,-0.1609516 1.348754,-0.6123403 1.850358,-1.2020043 2.173613,-1.5535277 0.323251,-0.3515343 0.936324,-1.0092338 1.103526,-1.3154017 0.167198,-0.3061663 0.345542,-0.4876031 0.345542,-0.6009978 0,-0.1133983 -0.312104,-0.3855536 -0.01112,-1.043249 0.300955,-0.6576966 0.568485,-2.1658733 0.434721,-2.8462471 -0.133762,-0.680377 -0.445868,-4.456482 -3.121079,-6.973885 -2.675203,-2.517401 -5.328127,-2.81223 -5.328127,-2.81223 0,0 4.235756,1.338077 6.219869,5.397669 1.984117,4.059596 1.337601,6.66771 0.06688,8.2552586 -1.270724,1.5875487 -3.076491,1.7689868 -3.566953,1.3607558 -0.490444,-0.4082292 -1.501077,1.8641068 -1.26328,2.2928065 z"
style="fill:#5ed938;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1020"
d="m 48.800383,-17.432105 c 0,0 -2.853557,-0.02267 -5.01602,1.406112 -2.16246,1.428797 -3.210252,2.585441 -3.812175,3.492612 -0.601919,0.907174 -1.293016,2.154531 -1.203842,2.131854 0.08917,-0.0227 2.60833,-3.53797 4.57015,-4.445139 1.961822,-0.907173 3.923641,-2.177213 6.621146,-1.247366 2.697505,0.929857 3.968232,2.222571 4.547859,1.905065 0.579629,-0.31751 0.691101,-0.70306 0.356697,-1.133966 -0.334399,-0.430906 -2.697508,-2.540081 -6.063815,-2.109172 z"
style="fill:#8fdbe9;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1022"
d="m 44.530829,0.69033794 c 0.189165,0.0962163 1.607908,2.56586906 2.742905,2.98282056 1.134994,0.4169541 1.891657,0.4490201 2.017767,0.6414685 0.126111,0.192439 0.09459,1.1546409 1.103469,1.5716019 1.008886,0.4169522 5.738036,1.7319552 7.09372,1.8602476 1.355695,0.1282956 0.2207,0.9301201 1.040416,1.2187811 0.819723,0.2886654 4.319291,0.4490282 5.170539,0.096218 0.851247,-0.3528 0.851247,0.3207371 -0.630553,0.8980604 -1.481799,0.577316 -5.391228,1.956476 -7.944967,1.635743 C 52.570379,11.274546 49.543723,10.729296 47.84123,9.5105098 46.138737,8.2917237 45.413601,7.7464765 46.044154,7.6502577 c 0.630553,-0.096225 2.30152,1.6998841 3.026654,1.8923257 0.725137,0.1924358 1.324162,0.1924358 0.882773,-0.2565932 C 49.512197,8.8369677 46.64318,6.8484212 46.359433,6.9446376 46.075682,7.0408596 45.476656,7.1050004 44.972214,6.4314646 44.467772,5.7579276 41.819449,2.0374171 41.977086,0.04887194 42.134727,-1.9396732 42.63917,-1.4265066 43.238195,-0.6888129 c 0.599024,0.73768484 1.292634,1.37915084 1.292634,1.37915084 z"
style="fill:#fd7aff;fill-opacity:1;stroke:none;stroke-width:0.0890379px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:1.28957px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.0322394"
x="80.617455"
y="4.5832744"
id="text24207"><tspan
sodipodi:role="line"
id="tspan24205"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:49.4338px;font-family:Yukarimobile;-inkscape-font-specification:'Yukarimobile, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#1d2129;fill-opacity:1;stroke-width:0.0322394"
x="80.617455"
y="4.5832744">spark</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

-240
View File
@@ -1,240 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="deepin-community-store.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
id="svg8"
version="1.1"
viewBox="0 0 200 200"
height="200mm"
width="200mm">
<defs
id="defs2">
<linearGradient
id="linearGradient1200"
inkscape:collect="always">
<stop
id="stop1196"
offset="0"
style="stop-color:#000000;stop-opacity:0.1299435" />
<stop
id="stop1198"
offset="1"
style="stop-color:#dadada;stop-opacity:0.81960785" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient1138">
<stop
style="stop-color:#99e7ea;stop-opacity:1"
offset="0"
id="stop1134" />
<stop
style="stop-color:#007ffc;stop-opacity:1"
offset="1"
id="stop1136" />
</linearGradient>
<linearGradient
id="linearGradient1128"
inkscape:collect="always">
<stop
id="stop1124"
offset="0"
style="stop-color:#99e7ea;stop-opacity:1" />
<stop
id="stop1126"
offset="1"
style="stop-color:#007ffc;stop-opacity:1" />
</linearGradient>
<inkscape:path-effect
only_selected="false"
apply_with_weight="true"
apply_no_weight="true"
helper_size="0"
steps="2"
weight="33.333333"
is_visible="true"
id="path-effect960"
effect="bspline" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.98112945,0,3.7714702)"
r="90.135414"
fy="199.86011"
fx="100.35268"
cy="199.86011"
cx="100.35268"
id="radialGradient1130"
xlink:href="#linearGradient1128"
inkscape:collect="always" />
<radialGradient
r="90.135414"
fy="199.86011"
fx="100.35268"
cy="199.86011"
cx="100.35268"
gradientTransform="matrix(1,0,0,0.98112945,0,3.7714702)"
gradientUnits="userSpaceOnUse"
id="radialGradient1132"
xlink:href="#linearGradient1138"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.98112945,0,3.7714702)"
r="90.135414"
fy="199.86011"
fx="100.35268"
cy="199.86011"
cx="100.35268"
id="radialGradient1202"
xlink:href="#linearGradient1200"
inkscape:collect="always" />
<filter
id="filter1448"
inkscape:label="Drop Shadow"
style="color-interpolation-filters:sRGB;">
<feFlood
id="feFlood1438"
result="flood"
flood-color="rgb(145,145,145)"
flood-opacity="0.372549" />
<feComposite
id="feComposite1440"
result="composite1"
operator="in"
in2="SourceGraphic"
in="flood" />
<feGaussianBlur
id="feGaussianBlur1442"
result="blur"
stdDeviation="5.2918"
in="composite1" />
<feOffset
id="feOffset1444"
result="offset"
dy="0"
dx="0" />
<feComposite
id="feComposite1446"
result="composite2"
operator="over"
in2="offset"
in="SourceGraphic" />
</filter>
<filter
id="filter2201"
inkscape:label="Drop Shadow"
style="color-interpolation-filters:sRGB;">
<feFlood
id="feFlood2191"
result="flood"
flood-color="rgb(145,145,145)"
flood-opacity="0.372549" />
<feComposite
id="feComposite2193"
result="composite1"
operator="in"
in2="SourceGraphic"
in="flood" />
<feGaussianBlur
id="feGaussianBlur2195"
result="blur"
stdDeviation="3.76995"
in="composite1" />
<feOffset
id="feOffset2197"
result="offset"
dy="0"
dx="0" />
<feComposite
id="feComposite2199"
result="composite2"
operator="over"
in2="offset"
in="SourceGraphic" />
</filter>
</defs>
<sodipodi:namedview
inkscape:document-rotation="0"
inkscape:window-maximized="1"
inkscape:window-y="-8"
inkscape:window-x="-8"
inkscape:window-height="705"
inkscape:window-width="1366"
showgrid="false"
inkscape:current-layer="layer2"
inkscape:document-units="mm"
inkscape:cy="507.94585"
inkscape:cx="120.33119"
inkscape:zoom="0.35"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-97)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1" />
<g
inkscape:label="Layer 2"
id="layer2"
inkscape:groupmode="layer">
<path
inkscape:connector-curvature="0"
id="path1002"
d="m 91.937746,32.561862 c 0,0 11.145084,-0.157476 22.599704,6.928753 11.45465,7.086223 18.11074,13.857508 20.27783,18.266716 2.16708,4.409213 9.28755,12.125333 9.13277,26.297793 -0.15488,14.17244 -3.40543,23.620766 -8.97797,31.494326 -5.57254,7.87359 -15.63405,13.85751 -27.70786,14.17247 -12.073834,0.31494 -19.813464,-7.55863 -22.444934,-11.96786 -2.63147,-4.4092 -3.71502,-13.85751 -0.46438,-20.628766 3.25065,-6.77132 8.3588,-6.77132 10.06152,-6.14141 1.70272,0.6299 2.16709,1.5747 3.09585,3.30689 0.92875,1.73219 1.54793,1.41726 2.941094,0.47243 1.39311,-0.94484 1.85748,-2.04715 1.54792,-3.46439 -0.30958,-1.41726 -2.167114,-3.14944 -3.715054,-3.62186 -1.54791,-0.47241 -3.71502,-1.88966 -6.81087,-1.41721 -3.09585,0.47238 -9.13276,2.04711 -14.24091,8.97585 -5.10815,6.928746 -4.48899,17.636836 -1.39313,22.675926 3.09585,5.0391 8.97796,14.48739 21.98054,17.79431 13.002594,3.30693 34.054354,-6.45633 41.329594,-21.57361 7.27524,-15.117296 7.43004,-22.203516 7.12048,-34.643766 C 145.96036,67.048164 134.97008,48.466503 122.74148,41.69522 110.51288,34.923934 101.38012,30.987141 91.937746,32.561862 Z"
style="fill:#ffc344;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1012"
d="m 98.407556,95.469094 c 0,0 -3.06474,-2.8951 -5.80111,2.22698 -2.73637,5.122046 -4.04983,9.687366 -1.31346,15.254856 2.73637,5.56745 8.42801,8.90792 17.184454,8.79659 8.75636,-0.11148 15.21419,-2.22699 19.0451,-8.5739 3.83094,-6.34692 6.7862,-11.02357 7.11457,-13.361906 0.32839,-2.33835 2.07965,0.334036 1.53239,2.338336 -0.54728,2.00426 -0.43783,5.9015 1.09454,5.12204 1.53237,-0.77942 2.73637,-2.00427 2.95526,-1.44753 0.21893,0.55673 -1.75127,4.00859 -2.68162,5.73449 -0.93039,1.7259 -3.83094,5.90153 -5.5275,7.51607 -1.69652,1.61458 -4.04981,3.89724 -6.84092,5.56747 -2.79109,1.67024 -7.11454,3.61887 -9.52255,4.06427 -2.40801,0.44539 -7.22403,1.39184 -9.96042,1.2805 -2.73635,-0.11137 -6.238924,-0.61243 -10.124564,-2.56104 -3.88565,-1.94859 -8.09966,-4.95505 -9.74148,-7.96148 -1.64182,-3.00643 -4.15928,-5.73449 -3.61201,-13.30623 0.54728,-7.571746 3.01001,-11.468986 4.87074,-13.250556 1.86073,-1.7816 4.5971,-2.56105 6.40311,-2.17131 1.806,0.38971 2.95528,1.44755 3.3931,2.22697 0.43781,0.77944 1.14928,2.22699 1.53237,2.50538 z"
style="fill:#f06767;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1014"
d="m 126.2091,135.55481 c 0,0 13.13457,-7.6831 19.26404,-19.82016 6.12948,-12.13707 8.7564,-19.931516 7.99021,-31.845916 -0.76619,-11.91436 -2.62692,-6.01286 -0.54728,-11.13493 2.07964,-5.12208 -1.31345,-15.25486 0.10943,-15.922952 1.42292,-0.668097 4.48765,4.453972 5.3633,8.573902 0.87562,4.11992 4.70654,16.81372 1.64181,32.9594 -3.06472,16.145636 -10.28872,22.603906 -15.10475,26.946546 -4.81603,4.34261 -15.7615,11.91437 -17.40332,11.80302 -1.64183,-0.11148 -1.86073,-0.11148 -1.31348,-1.55891 z"
style="fill:#3f62eb;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1016"
d="m 102.56686,112.17145 c 0,0 7.00512,1.5589 12.36838,-1.78156 5.3633,-3.3405 9.5226,-8.79661 10.17931,-10.912246 0.65672,-2.11564 0.76619,1.892936 1.53236,-0.11125 0.76618,-2.00432 3.83093,-6.01288 2.29855,-15.36624 -1.53237,-9.35333 -1.64182,-9.79875 -4.48762,-14.80947 -2.84586,-5.01072 -9.63207,-11.914367 -13.79134,-14.141356 -4.15927,-2.226986 -9.96037,-5.567464 -17.950604,-5.344766 -7.9902,0.222699 -5.36328,-0.334048 -13.02512,1.002146 -7.66184,1.336187 -14.55749,5.010717 -16.85604,7.015006 -2.29855,2.004286 -8.42802,7.46041 -10.61712,10.46684 -2.1891,3.00643 -8.20911,9.79874 -11.3833,19.26344 -3.17419,9.46469 -4.48765,10.46683 -4.70656,16.702396 -0.21891,6.23557 0.54727,7.90578 -0.76618,8.46256 -1.31346,0.55673 -1.09455,-4.67668 -0.9851,-8.35123 0.10946,-3.6745 0.10946,-13.250556 4.92547,-23.940086 4.81601,-10.68954 13.35349,-19.59749 18.1695,-22.826621 4.81601,-3.229128 10.39821,-7.571752 19.04514,-9.687392 8.64693,-2.115635 17.29386,-1.781586 22.65716,-0.779443 5.363304,1.002145 13.681874,4.453974 18.169504,7.905802 4.48766,3.45183 9.41314,7.683104 13.13459,14.586764 3.72146,6.90365 4.70654,15.70025 4.59709,19.37477 -0.10943,3.67455 -1.97019,12.137106 -4.81601,16.257016 -2.84583,4.11993 -6.67674,9.0193 -10.61711,10.80089 -3.94039,1.78157 -8.75642,2.33833 -12.69675,0.55674 -3.94039,-1.78161 -3.72147,-2.44969 -4.3782,-4.34263 z"
style="fill:#fce102;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1018"
d="m 102.56686,112.17145 c 0,0 5.54674,1.56707 10.22918,-0.55878 4.68248,-2.12587 6.4239,-4.17301 7.54615,-5.3934 1.12223,-1.22042 3.25064,-3.50376 3.83112,-4.56669 0.58046,-1.06292 1.19962,-1.692816 1.19962,-2.086486 0,-0.39369 -1.08353,-1.33853 -0.0386,-3.62186 1.04482,-2.28333 1.97361,-7.51928 1.50922,-9.88134 -0.46438,-2.36207 -1.54792,-15.47161 -10.83547,-24.2113 -9.28753,-8.739679 -18.497714,-9.763243 -18.497714,-9.763243 0,0 14.705314,4.645415 21.593574,18.739133 6.88828,14.09374 4.64376,23.14835 0.23218,28.65986 -4.41158,5.511506 -10.68068,6.141406 -12.38342,4.724146 -1.70268,-1.41725 -5.2113,6.47164 -4.38574,7.95996 z"
style="fill:#5ed938;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1020"
d="m 84.662496,61.615394 c 0,0 -9.90672,-0.0787 -17.41416,4.88161 -7.50743,4.96037 -11.14506,8.9759 -13.23476,12.12533 -2.08969,3.14945 -4.48898,7.47991 -4.17939,7.40118 0.30958,-0.0788 9.05536,-12.2828 15.86623,-15.43223 6.81087,-3.14944 13.62174,-7.55865 22.98669,-4.33049 9.36495,3.22819 13.776544,7.71612 15.788844,6.61383 2.0123,-1.1023 2.3993,-2.44082 1.23835,-3.9368 -1.16094,-1.49598 -9.364964,-8.81842 -21.051804,-7.32243 z"
style="fill:#8fdbe9;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path1022"
d="m 69.839846,124.53124 c 0.65673,0.33404 5.58219,8.90795 9.52257,10.35548 3.94037,1.44755 6.56728,1.55888 7.0051,2.227 0.43782,0.66809 0.32837,4.00858 3.83092,5.45614 3.50256,1.44753 19.920794,6.01284 24.627334,6.45824 4.70658,0.4454 0.76621,3.22911 3.61202,4.23125 2.84584,1.00217 14.99532,1.5589 17.95061,0.33405 2.95527,-1.22483 2.95527,1.1135 -2.1891,3.1178 -5.14437,2.00427 -18.71677,6.79231 -27.58261,5.67882 -8.865864,-1.1135 -19.373534,-3.00644 -25.284094,-7.23772 -5.91056,-4.23126 -8.42802,-6.1242 -6.23892,-6.45824 2.18909,-0.33407 7.9902,5.9015 10.50766,6.56959 2.51746,0.66809 4.5971,0.66809 3.06473,-0.8908 -1.53236,-1.55888 -11.49275,-8.46253 -12.47784,-8.1285 -0.9851,0.33405 -3.06474,0.55674 -4.81602,-1.78159 -1.75127,-2.33832 -10.94548,-15.25485 -10.39821,-22.1585 0.54728,-6.90365 2.29856,-5.12208 4.3782,-2.56103 2.07964,2.56103 4.48765,4.78801 4.48765,4.78801 z"
style="fill:#fd7aff;fill-opacity:1;stroke:none;stroke-width:0.309114px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

-35
View File
@@ -1,35 +0,0 @@
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path d="m17,129c0,-61.30371 49.69629,-111 111,-111c61.30371,0 111,49.69629 111,111c0,61.30371 -49.69629,111 -111,111c-61.30371,0 -111,-49.69629 -111,-111z" id="deepin-launcher-b"/>
<filter filterUnits="objectBoundingBox" y="-6.3%" x="-8.1%" height="116.2%" width="116.2%" id="deepin-launcher-a">
<feGaussianBlur stdDeviation="5"/>
</filter>
<path d="m172.29023,47.20405c-13.1683,-7.14564 -28.25541,-11.20405 -44.29023,-11.20405c-3.85759,0 -7.66034,0.23489 -11.39471,0.69114c-13.8375,19.06416 -21.01047,50.16415 -20.43985,69.1948c0,0 -0.90954,28.19993 18.37748,38.20231c0,0 17.33291,7.61701 29.14502,-17.01295c0,0 8.11834,-13.89983 4.81381,-45.31395c0,0 3.16155,0.55793 3.51901,1.05927c0.35746,0.49728 6.98241,24.18523 2.32747,44.13339c0,0 -4.28556,23.44132 -25.35592,28.80234c-21.06242,5.36102 -37.47784,-7.60893 -48.62269,-19.82688c-8.29983,-9.09853 -20.62176,-33.53254 -26.69028,-62.84231c-11.72709,15.56323 -18.67934,34.92741 -18.67934,55.91495c0,14.49236 3.31502,28.21045 9.22816,40.43737c20.53097,6.06549 72.70224,17.88328 105.89216,-6.44123c21.96964,-16.10443 19.13893,-41.89451 19.13893,-41.89451c-0.36372,-19.61754 -12.30727,-39.10374 -12.30727,-39.10374c46.44186,42.01354 18.99265,88.68931 18.99265,88.68931c-12.77926,26.10154 -39.04908,42.79526 -62.02961,50.25104c4.59324,0.69782 9.29685,1.05965 14.08498,1.05965c51.36266,0 93,-41.63639 93,-92.99789c0,-21.72407 -7.44877,-41.70884 -19.93152,-57.53933c-4.54487,0.31322 -9.825,0.49664 -15.30337,0.31684c0,0 -24.70889,1.15387 -38.56418,8.0646c0,0 -10.33212,4.60716 -20.65999,12.41858c0,0 -2.19192,1.09575 -2.08593,5.12183c0.09327,4.01362 -2.10288,14.71385 -9.42058,20.98539c0,0 -5.22329,2.68544 -2.61165,6.52889c0,0 3.52742,5.12183 8.49633,-0.25734c0,0 12.81233,-13.18228 13.59668,-34.42501c0,0 4.05314,-3.4616 10.45506,-4.48264c0,0 1.17863,31.86824 -14.63539,47.86878c0,0 -15.04241,16.38239 -19.87565,-7.93593c0,0 -5.88469,-23.16861 24.45027,-50.68289c0,0 20.448,-20.42091 32.46751,-29.98388c1.66104,0.69233 3.29908,1.42749 4.91265,2.20406l-0.00001,-0.00001zm-44.29023,183.79595c-56.33322,0 -102,-45.66583 -102,-101.99789c0,-56.33281 45.66752,-102.00211 102,-102.00211c56.33248,0 102,45.6693 102,102.00211c0,56.33206 -45.66678,101.99789 -102,101.99789z" id="deepin-launcher-f"/>
<filter filterUnits="objectBoundingBox" y="-.5%" x="-.5%" height="102%" width="101%" id="deepin-launcher-e"/>
<filter filterUnits="objectBoundingBox" y="-.5%" x="-.5%" height="102%" width="101%" id="deepin-launcher-g"/>
<linearGradient y2="97.178%" y1="4.64%" x2="50%" x1="50%" id="deepin-launcher-c">
<stop stop-color="#00ABFF" offset="0%"/>
<stop stop-color="#0163FA" offset="100%"/>
</linearGradient>
<linearGradient y2="100%" y1="0%" x2="50%" x1="50%" id="deepin-launcher-d">
<stop stop-color="#32BBFF" offset="0%"/>
<stop stop-color="#004FC5" offset="100%"/>
</linearGradient>
</defs>
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="514" width="514" y="-1" x="-1"/>
</g>
<g>
<title>Layer 1</title>
<g stroke="null" id="svg_1" fill-rule="evenodd" fill="none">
<use x="0" y="0" transform="matrix(2.15315318107605,0,0,2.15315318107605,-19.603604078292847,-20.756757259368896) " stroke="null" id="svg_2" xlink:href="#deepin-launcher-b" filter="url(#deepin-launcher-a)" fill="#000"/>
<use x="0" y="0" transform="matrix(2.15315318107605,0,0,2.15315318107605,-19.603604078292847,-20.756757259368896) " stroke="url(#deepin-launcher-d)" id="svg_3" xlink:href="#deepin-launcher-b" stroke-width="2" fill="url(#deepin-launcher-c)"/>
<g stroke="null" id="svg_4" fill-rule="nonzero">
<use x="0" y="0" transform="matrix(2.15315318107605,0,0,2.15315318107605,-19.603604078292847,-20.756757259368896) " stroke="null" id="svg_5" xlink:href="#deepin-launcher-f" filter="url(#deepin-launcher-e)" fill="#000"/>
<use x="0" y="0" transform="matrix(2.15315318107605,0,0,2.15315318107605,-19.603604078292847,-20.756757259368896) " stroke="null" id="svg_6" xlink:href="#deepin-launcher-f" fill="#F0F9FF"/>
<use x="0" y="0" transform="matrix(2.15315318107605,0,0,2.15315318107605,-19.603604078292847,-20.756757259368896) " stroke="null" id="svg_7" xlink:href="#deepin-launcher-f" filter="url(#deepin-launcher-g)" fill="#000"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

-1
View File
@@ -1 +0,0 @@
<svg width="305" height="304" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="hidden"><defs><clipPath id="clip0"><path d="M688 378 993 378 993 682 688 682Z" fill-rule="evenodd" clip-rule="evenodd"/></clipPath><clipPath id="clip1"><path d="M751.382 385.273 984.326 440.078 929.522 673.022 696.578 618.218Z" fill-rule="evenodd" clip-rule="evenodd"/></clipPath><clipPath id="clip2"><path d="M751.382 385.273 984.326 440.078 929.522 673.022 696.578 618.218Z" fill-rule="evenodd" clip-rule="evenodd"/></clipPath><clipPath id="clip3"><path d="M751.382 385.273 984.326 440.078 929.522 673.022 696.578 618.218Z" fill-rule="evenodd" clip-rule="evenodd"/></clipPath></defs><g clip-path="url(#clip0)" transform="translate(-688 -378)"><path d="M689 529.5C689 445.829 756.829 378 840.5 378 924.171 378 992 445.829 992 529.5 992 613.171 924.171 681 840.5 681 756.829 681 689 613.171 689 529.5Z" fill="#A20000" fill-rule="evenodd"/><g clip-path="url(#clip1)"><g clip-path="url(#clip2)"><g clip-path="url(#clip3)"><path d="M812.478 604.512 826.339 545.597C790.456 531.483 772.809 490.952 786.924 455.069 792.525 440.83 802.648 428.825 815.737 420.901L910.837 443.275C931.459 475.856 921.763 518.985 889.182 539.607 876.253 547.79 860.994 551.499 845.751 550.164L831.89 609.079 851.302 613.646C856.662 614.908 859.986 620.276 858.724 625.636 857.463 630.996 852.095 634.32 846.735 633.058L788.499 619.357C783.138 618.096 779.815 612.728 781.076 607.368 782.338 602.007 787.705 598.684 793.066 599.945L812.478 604.512ZM803.34 469.2 900.4 492.035C901.355 477.612 900.407 467.146 897.544 460.634L819.896 442.366C814.431 446.918 808.915 455.864 803.34 469.2Z" fill="#FFFFFF"/></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

-23
View File
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>logo icon</title>
<defs>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
<stop stop-color="#00F1FF" offset="0%"></stop>
<stop stop-color="#008AFF" offset="100%"></stop>
</linearGradient>
</defs>
<g id="light" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1" transform="translate(-460.000000, -159.000000)">
<g id="tittlebar" transform="translate(450.000000, 150.000000)">
<g id="logo-icon" transform="translate(10.000000, 9.000000)">
<g>
<rect id="矩形" fill="url(#linearGradient-1)" x="0" y="0" width="32" height="32" rx="8"></rect>
<path d="M23,25 L23,24.0002278 C21.6666667,24.0002278 21,24.0002278 21,24.0002278 L21,20 L22,20 L22,19 L21,19 L21,17 L20,17.5 L20,19 L19,19 L19,20 L20,20 L20,24.0002278 C20,24.0002278 20,24.0002278 20,24.0002278 C20,24.5523868 20.4476132,25 20.9997722,25 C20.9998481,25 20.9999241,25 21,25 L23,25 Z M24.0210414,23.9789586 L24.0210414,22.2215556 L24.0210414,22.2215556 L24.6565969,21.6226667 L27.2207674,25 L29.0052118,25 L25.6099302,20.7304444 L28.4678057,18.0074755 L26.6711391,18.0074755 L24.0210414,20.6204444 L24,15.5 L23,15 L23,25 C23.5639056,25 24.0210414,24.5428642 24.0210414,23.9789586 Z" id="tk" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M10.275,24 C13.175,24 15.35,23.2 16.85,21.6 C18.275,20.075 19,17.825 19,15 C19,12.15 18.275,10.05 16.85,8.55 C15.35,6.95 13.175,6 10.275,6 L4,6 L4,24 L10.275,24 Z M9.725,21 L7,21 L7,9 L9.725,9 C11.95,9 13.575,9.15 14.6,10.175 C15.6,11.175 16,12.75 16,15 C16,17.2 15.6,18.9 14.6,19.95 C13.575,20.975 11.95,21 9.725,21 Z" id="D" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Some files were not shown because too many files have changed in this diff Show More