fix bug
This commit is contained in:
@@ -10,7 +10,25 @@
|
|||||||
"Bash(timeout:*)",
|
"Bash(timeout:*)",
|
||||||
"Bash(nul)",
|
"Bash(nul)",
|
||||||
"Bash(start \"\" \"f:\\cursor-auto\\focusBuddy\\icon-preview.html\")",
|
"Bash(start \"\" \"f:\\cursor-auto\\focusBuddy\\icon-preview.html\")",
|
||||||
"Bash(dir:*)"
|
"Bash(dir:*)",
|
||||||
|
"Bash(echo:*)",
|
||||||
|
"Bash(cat:*)",
|
||||||
|
"Bash(code --locate-extension:*)",
|
||||||
|
"Bash(~/sdk/flutter/bin/flutter --version)",
|
||||||
|
"Bash(ruby:*)",
|
||||||
|
"Bash(pod --version:*)",
|
||||||
|
"Bash(gem environment:*)",
|
||||||
|
"Bash(brew:*)",
|
||||||
|
"Bash(sudo gem uninstall:*)",
|
||||||
|
"Bash(rbenv --version:*)",
|
||||||
|
"Bash(rbenv install:*)",
|
||||||
|
"Bash(/opt/homebrew/bin/rbenv install:*)",
|
||||||
|
"Bash(/opt/homebrew/bin/rbenv global:*)",
|
||||||
|
"Bash(/opt/homebrew/bin/rbenv version:*)",
|
||||||
|
"Bash(gem install:*)",
|
||||||
|
"Bash(export PATH=\"$PATH:$HOME/sdk/flutter/bin\")",
|
||||||
|
"Bash(flutter doctor:*)",
|
||||||
|
"Bash(flutter analyze:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
# 🔧 Android 构建修复 - Core Library Desugaring
|
|
||||||
|
|
||||||
**日期**: 2025-11-22
|
|
||||||
**问题**: flutter_local_notifications 需要 core library desugaring
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❌ 错误信息
|
|
||||||
|
|
||||||
```
|
|
||||||
FAILURE: Build failed with an exception.
|
|
||||||
|
|
||||||
* What went wrong:
|
|
||||||
Execution failed for task ':app:checkDebugAarMetadata'.
|
|
||||||
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
|
|
||||||
> An issue was found when checking AAR metadata:
|
|
||||||
|
|
||||||
1. Dependency ':flutter_local_notifications' requires core library desugaring to be enabled
|
|
||||||
for :app.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 问题原因
|
|
||||||
|
|
||||||
`flutter_local_notifications` 包使用了 Java 8+ 的新 API(例如 `java.time` 包),这些 API 在较旧的 Android 版本上不可用。
|
|
||||||
|
|
||||||
Core library desugaring 允许应用使用这些新 API,同时保持对旧版 Android 的兼容性。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 解决方案
|
|
||||||
|
|
||||||
修改 `android/app/build.gradle.kts` 文件:
|
|
||||||
|
|
||||||
### 1. 启用 desugaring
|
|
||||||
|
|
||||||
在 `compileOptions` 中添加:
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
isCoreLibraryDesugaringEnabled = true // ✨ 新增
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 添加 desugaring 库依赖
|
|
||||||
|
|
||||||
在文件末尾添加:
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
dependencies {
|
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 完整修改
|
|
||||||
|
|
||||||
### 修改前
|
|
||||||
```kotlin
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
flutter {
|
|
||||||
source = "../.."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 修改后
|
|
||||||
```kotlin
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
isCoreLibraryDesugaringEnabled = true // ✨ 新增
|
|
||||||
}
|
|
||||||
|
|
||||||
flutter {
|
|
||||||
source = "../.."
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies { // ✨ 新增
|
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 验证修复
|
|
||||||
|
|
||||||
运行以下命令测试:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flutter clean
|
|
||||||
flutter build apk --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
或直接运行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flutter run -d <android-device>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 相关信息
|
|
||||||
|
|
||||||
### 什么是 Core Library Desugaring?
|
|
||||||
|
|
||||||
Desugaring 是一个过程,它将使用较新 Java API 的代码转换为在旧版 Android 上可运行的等效代码。
|
|
||||||
|
|
||||||
### 支持的 API
|
|
||||||
|
|
||||||
启用 desugaring 后,可以使用:
|
|
||||||
- `java.time.*` (日期和时间 API)
|
|
||||||
- `java.util.stream.*` (Stream API)
|
|
||||||
- `java.util.function.*` (函数式接口)
|
|
||||||
- 以及其他 Java 8+ 的核心库 API
|
|
||||||
|
|
||||||
### 版本说明
|
|
||||||
|
|
||||||
- `desugar_jdk_libs:2.0.4` 是当前稳定版本
|
|
||||||
- 最低支持 Android API 21 (Android 5.0)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 参考链接
|
|
||||||
|
|
||||||
- [Android Developer - Java 8+ Support](https://developer.android.com/studio/write/java8-support.html)
|
|
||||||
- [Core Library Desugaring Guide](https://developer.android.com/studio/write/java8-support#library-desugaring)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**状态**: ✅ 已修复
|
|
||||||
**文件**: `android/app/build.gradle.kts`
|
|
||||||
**影响**: Android 构建现在应该可以正常工作
|
|
||||||
137
BUG_FIX_001.md
137
BUG_FIX_001.md
@@ -1,137 +0,0 @@
|
|||||||
# 🐛 Bug 修复报告
|
|
||||||
|
|
||||||
## Bug #1: "View Full Report" 按钮无功能
|
|
||||||
|
|
||||||
**日期**: 2025-11-22
|
|
||||||
**发现者**: 用户测试
|
|
||||||
**优先级**: 中等
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 问题描述
|
|
||||||
|
|
||||||
在 Complete Screen(完成页面)点击 "View Full Report" 按钮时,显示 "History screen coming soon!" 的占位提示,而不是导航到 History 页面。
|
|
||||||
|
|
||||||
**重现步骤**:
|
|
||||||
1. 完成一次 focus session
|
|
||||||
2. 到达 Complete Screen
|
|
||||||
3. 点击 "View Full Report" 按钮
|
|
||||||
4. 看到 SnackBar 提示 "History screen coming soon!"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 根本原因
|
|
||||||
|
|
||||||
在 `complete_screen.dart` 中,"View Full Report" 按钮的 `onPressed` 处理函数只是显示一个占位的 SnackBar,而没有实际导航到 HistoryScreen。
|
|
||||||
|
|
||||||
```dart
|
|
||||||
// 问题代码
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('History screen coming soon!'),
|
|
||||||
duration: Duration(seconds: 1),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const Text('View Full Report'),
|
|
||||||
),
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 修复方案
|
|
||||||
|
|
||||||
1. **添加导入**: 在文件顶部添加 `import 'history_screen.dart';`
|
|
||||||
2. **修改按钮行为**: 使用 `Navigator.pushAndRemoveUntil` 导航到 HistoryScreen
|
|
||||||
3. **更新按钮文本**: 将 "View Full Report" 改为更准确的 "View History"
|
|
||||||
|
|
||||||
```dart
|
|
||||||
// 修复后的代码
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pushAndRemoveUntil(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const HistoryScreen(),
|
|
||||||
),
|
|
||||||
(route) => route.isFirst, // Keep only the home screen in stack
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const Text('View History'),
|
|
||||||
),
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 修复详情
|
|
||||||
|
|
||||||
**修改的文件**:
|
|
||||||
- `lib/screens/complete_screen.dart`
|
|
||||||
|
|
||||||
**修改内容**:
|
|
||||||
1. 第 7 行:添加 `import 'history_screen.dart';`
|
|
||||||
2. 第 110-122 行:重写 TextButton 的 onPressed 处理函数
|
|
||||||
|
|
||||||
**导航逻辑**:
|
|
||||||
- 使用 `pushAndRemoveUntil` 而不是简单的 `push`
|
|
||||||
- 保留 Home screen 在导航栈底部
|
|
||||||
- 这样从 History 点击返回会回到 Home,而不是 Complete screen
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 测试验证
|
|
||||||
|
|
||||||
**测试步骤**:
|
|
||||||
1. 完成一次 focus session
|
|
||||||
2. 在 Complete Screen 点击 "View History" 按钮
|
|
||||||
3. 验证:成功导航到 History Screen
|
|
||||||
4. 验证:可以看到刚刚完成的 session
|
|
||||||
5. 点击返回按钮
|
|
||||||
6. 验证:返回到 Home Screen(不是 Complete Screen)
|
|
||||||
|
|
||||||
**预期结果**: ✅ 所有步骤通过
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 影响范围
|
|
||||||
|
|
||||||
**影响的功能**:
|
|
||||||
- Complete Screen 到 History Screen 的导航流程
|
|
||||||
|
|
||||||
**不影响的功能**:
|
|
||||||
- 其他页面的导航
|
|
||||||
- 数据保存
|
|
||||||
- History Screen 自身的显示逻辑
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 部署方式
|
|
||||||
|
|
||||||
**Hot Reload**: ✅ 支持
|
|
||||||
**需要重启**: ❌ 不需要
|
|
||||||
|
|
||||||
用户在浏览器中应该会自动看到更新(Flutter 会自动热重载)。如果没有自动更新,按 `R` 进行热重启。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 后续改进建议
|
|
||||||
|
|
||||||
可选的 UI 优化:
|
|
||||||
1. 将 "View History" 改为图标按钮(更简洁)
|
|
||||||
2. 添加一个简短的过渡动画
|
|
||||||
3. 在 History Screen 顶部突出显示刚刚完成的 session
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 状态
|
|
||||||
|
|
||||||
- [x] Bug 已识别
|
|
||||||
- [x] 代码已修复
|
|
||||||
- [x] 已触发热重载
|
|
||||||
- [ ] 等待用户验证
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**修复完成!请在浏览器中测试 "View History" 按钮现在是否正常工作。** 🎉
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
# FocusBuddy - 开发进度报告
|
|
||||||
|
|
||||||
**日期**: 2025年11月22日
|
|
||||||
**状态**: ✅ MVP 核心功能已完成
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 已完成的工作
|
|
||||||
|
|
||||||
### 1. 项目初始化 ✅
|
|
||||||
- ✅ Flutter 项目创建
|
|
||||||
- ✅ 依赖包配置(Hive, Flutter Local Notifications, Path Provider, Shared Preferences)
|
|
||||||
- ✅ 项目文件夹结构搭建
|
|
||||||
|
|
||||||
### 2. 数据模型 ✅
|
|
||||||
- ✅ `FocusSession` 模型(包含开始时间、时长、分心次数等)
|
|
||||||
- ✅ `DistractionType` 类型定义(4种分心类型)
|
|
||||||
- ✅ Hive 适配器自动生成
|
|
||||||
|
|
||||||
### 3. 主题系统 ✅
|
|
||||||
- ✅ `AppColors` - 莫兰迪色系配色
|
|
||||||
- ✅ `AppTextStyles` - Nunito 字体样式系统
|
|
||||||
- ✅ `AppTheme` - Material 3 主题配置
|
|
||||||
|
|
||||||
### 4. 核心服务 ✅
|
|
||||||
- ✅ `StorageService` - Hive 本地数据存储
|
|
||||||
- ✅ `EncouragementService` - 鼓励文案管理
|
|
||||||
|
|
||||||
### 5. 核心页面 ✅
|
|
||||||
- ✅ **HomeScreen** - 启动页(固定25分钟)
|
|
||||||
- ✅ **FocusScreen** - 计时器页面
|
|
||||||
- 倒计时功能
|
|
||||||
- "I got distracted" 按钮
|
|
||||||
- 暂停/恢复功能
|
|
||||||
- 提前停止确认
|
|
||||||
- 分心类型选择(Bottom Sheet)
|
|
||||||
- ✅ **CompleteScreen** - 完成页面
|
|
||||||
- 显示本次专注时长
|
|
||||||
- 显示今日总计
|
|
||||||
- 随机鼓励文案
|
|
||||||
|
|
||||||
### 6. 核心功能 ✅
|
|
||||||
- ✅ 25分钟固定计时器
|
|
||||||
- ✅ 分心追踪(不中断计时)
|
|
||||||
- ✅ 4种分心类型分类
|
|
||||||
- ✅ 本地数据持久化
|
|
||||||
- ✅ 今日统计(总时长、分心次数)
|
|
||||||
- ✅ 随机鼓励文案
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 可以运行了!
|
|
||||||
|
|
||||||
### 当前可用设备:
|
|
||||||
- ✅ Windows (desktop)
|
|
||||||
- ✅ Edge (web)
|
|
||||||
|
|
||||||
### 运行命令:
|
|
||||||
```bash
|
|
||||||
# Windows 桌面版
|
|
||||||
flutter run -d windows
|
|
||||||
|
|
||||||
# Web 版(用于快速测试)
|
|
||||||
flutter run -d edge
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 待完成事项
|
|
||||||
|
|
||||||
### 高优先级(影响使用):
|
|
||||||
1. **字体** ⚠️
|
|
||||||
- 当前使用系统默认字体
|
|
||||||
- 需要下载 Nunito 字体或使用 google_fonts 包
|
|
||||||
- 参见 `FONT_SETUP.md`
|
|
||||||
|
|
||||||
### 中优先级(MVP 后续):
|
|
||||||
2. **History Screen** - 历史记录页面
|
|
||||||
3. **Settings Screen** - 设置页面(时长选择)
|
|
||||||
4. **Onboarding** - 首次启动引导
|
|
||||||
5. **本地通知** - 计时完成提醒
|
|
||||||
|
|
||||||
### 低优先级(V1.1+):
|
|
||||||
6. 白噪音播放
|
|
||||||
7. PDF 报告导出
|
|
||||||
8. 成就系统优化
|
|
||||||
9. 主题皮肤
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 已知问题
|
|
||||||
|
|
||||||
### 1. 字体缺失
|
|
||||||
**问题**: Nunito 字体文件未下载
|
|
||||||
**影响**: 使用系统默认字体,视觉效果不符合设计
|
|
||||||
**解决方案**:
|
|
||||||
- 方案A: 下载字体文件到 `assets/fonts/`
|
|
||||||
- 方案B: 使用 `google_fonts` 包
|
|
||||||
|
|
||||||
### 2. TODO 占位符
|
|
||||||
**影响**: History 和 Settings 按钮点击显示 "coming soon"
|
|
||||||
**解决**: 后续实现这些页面
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 代码统计
|
|
||||||
|
|
||||||
| 类型 | 数量 | 文件 |
|
|
||||||
|------|------|------|
|
|
||||||
| 模型 | 2 | focus_session.dart, distraction_type.dart |
|
|
||||||
| 服务 | 2 | storage_service.dart, encouragement_service.dart |
|
|
||||||
| 主题 | 3 | app_colors.dart, app_text_styles.dart, app_theme.dart |
|
|
||||||
| 页面 | 3 | home_screen.dart, focus_screen.dart, complete_screen.dart |
|
|
||||||
| 总代码行数 | ~600+ | (不含生成代码) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 下一步行动
|
|
||||||
|
|
||||||
### 立即可做:
|
|
||||||
1. **运行测试**:
|
|
||||||
```bash
|
|
||||||
cd f:\cursor-auto\focusBuddy
|
|
||||||
flutter run -d windows
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **体验核心流程**:
|
|
||||||
- 点击 "Start Focusing"
|
|
||||||
- 等待或点击 "I got distracted"
|
|
||||||
- 选择分心类型
|
|
||||||
- 查看完成页面
|
|
||||||
|
|
||||||
3. **验证数据持久化**:
|
|
||||||
- 完成一次专注
|
|
||||||
- 重启 app
|
|
||||||
- 开始新一次专注
|
|
||||||
- 在完成页查看"Total Today"是否累加
|
|
||||||
|
|
||||||
### 本周任务(按 MVP 清单):
|
|
||||||
- [ ] 下载并配置 Nunito 字体
|
|
||||||
- [ ] 实现 History Screen(简单列表)
|
|
||||||
- [ ] 实现 Settings Screen(3个时长选项)
|
|
||||||
- [ ] 添加本地通知(计时完成提醒)
|
|
||||||
- [ ] 真机测试(Android/iOS)
|
|
||||||
|
|
||||||
### 下周任务:
|
|
||||||
- [ ] 上架准备(图标、截图、描述文案)
|
|
||||||
- [ ] 注册开发者账号
|
|
||||||
- [ ] 准备隐私政策和服务条款托管
|
|
||||||
- [ ] Beta 测试
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 设计亮点
|
|
||||||
|
|
||||||
### 1. 无惩罚机制 ✅
|
|
||||||
- "I got distracted" 不中断计时
|
|
||||||
- 提前停止有友好提示
|
|
||||||
- 鼓励文案代替批评
|
|
||||||
|
|
||||||
### 2. 数据结构简洁 ✅
|
|
||||||
- FocusSession 包含所有核心信息
|
|
||||||
- 分心类型用字符串列表存储
|
|
||||||
- 易于扩展
|
|
||||||
|
|
||||||
### 3. 用户体验友好 ✅
|
|
||||||
- 大按钮,易点击
|
|
||||||
- 柔和配色(莫兰迪色系)
|
|
||||||
- 鼓励性文案随机展示
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 技术亮点
|
|
||||||
|
|
||||||
### 1. 架构清晰
|
|
||||||
```
|
|
||||||
lib/
|
|
||||||
├── models/ # 数据模型
|
|
||||||
├── services/ # 业务逻辑
|
|
||||||
├── theme/ # UI 主题
|
|
||||||
├── screens/ # 页面
|
|
||||||
└── main.dart # 入口
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 状态管理简单
|
|
||||||
- 使用 StatefulWidget 管理计时器状态
|
|
||||||
- 服务单例模式(StorageService)
|
|
||||||
- 依赖注入(EncouragementService)
|
|
||||||
|
|
||||||
### 3. 数据持久化
|
|
||||||
- Hive 本地数据库
|
|
||||||
- 自动生成适配器
|
|
||||||
- 快速读写
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 代码质量
|
|
||||||
|
|
||||||
### 优点:
|
|
||||||
- ✅ 代码结构清晰
|
|
||||||
- ✅ 注释完整
|
|
||||||
- ✅ 遵循 Flutter 最佳实践
|
|
||||||
- ✅ Material 3 设计
|
|
||||||
|
|
||||||
### 可改进:
|
|
||||||
- ⚠️ 缺少单元测试
|
|
||||||
- ⚠️ 错误处理可以更健壮
|
|
||||||
- ⚠️ 可以添加更多边界情况处理
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 MVP 完成度
|
|
||||||
|
|
||||||
| 功能 | 状态 | 备注 |
|
|
||||||
|------|------|------|
|
|
||||||
| 25分钟固定计时器 | ✅ 100% | |
|
|
||||||
| "I got distracted" 按钮 | ✅ 100% | |
|
|
||||||
| 4种分心分类 | ✅ 100% | |
|
|
||||||
| 鼓励文案反馈 | ✅ 100% | |
|
|
||||||
| 本地数据存储 | ✅ 100% | |
|
|
||||||
| 今日统计 | ✅ 100% | |
|
|
||||||
| 完成页面 | ✅ 100% | |
|
|
||||||
| History 页面 | ⏳ 0% | 下一步 |
|
|
||||||
| Settings 页面 | ⏳ 0% | 下一步 |
|
|
||||||
| 本地通知 | ⏳ 0% | 下一步 |
|
|
||||||
|
|
||||||
**总体完成度**: **70%** (7/10 核心功能)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 总结
|
|
||||||
|
|
||||||
✅ **核心价值已实现**: "无惩罚的专注追踪"功能完整可用
|
|
||||||
|
|
||||||
✅ **可以开始测试**: 主流程已打通,可以体验完整专注循环
|
|
||||||
|
|
||||||
⚠️ **仍需完善**: History、Settings 和通知功能需要补充
|
|
||||||
|
|
||||||
📅 **预计完成 MVP**: 本周末(还需 2-3 天开发时间)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**下一步**: 运行 `flutter run -d windows` 查看效果!
|
|
||||||
506
FIGMA设计教程.md
506
FIGMA设计教程.md
@@ -1,506 +0,0 @@
|
|||||||
# 🎨 FocusBuddy 图标设计教程(Figma 中文版)
|
|
||||||
|
|
||||||
**日期**: 2025年11月22日
|
|
||||||
**工具**: Figma(免费)
|
|
||||||
**所需时间**: 20-30分钟
|
|
||||||
**难度**: ⭐⭐☆☆☆ 简单
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 准备工作
|
|
||||||
|
|
||||||
### 1. 注册 Figma 账号
|
|
||||||
1. 打开浏览器,访问 **https://www.figma.com**
|
|
||||||
2. 点击右上角 **"Sign up"**(注册)
|
|
||||||
3. 使用 Google 账号或邮箱注册(完全免费)
|
|
||||||
4. 验证邮箱后登录
|
|
||||||
|
|
||||||
### 2. 准备颜色代码
|
|
||||||
把这些颜色复制到记事本,待会要用:
|
|
||||||
```
|
|
||||||
主色调(平静的绿色): #A7C4BC
|
|
||||||
成功色(明亮的绿色): #88C9A1
|
|
||||||
背景色(温暖的米白): #F8F6F2
|
|
||||||
文字色(柔和的灰色): #5B6D6D
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 推荐设计方案:温柔专注圈
|
|
||||||
|
|
||||||
这个设计最符合 FocusBuddy 的理念:
|
|
||||||
- 同心圆代表专注的力量
|
|
||||||
- 可选的笑脸让图标更友善
|
|
||||||
- 柔和的配色传达温暖支持
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📐 第一步:创建画布(2分钟)
|
|
||||||
|
|
||||||
### 1.1 新建文件
|
|
||||||
1. 登录 Figma 后,点击左上角 **"New design file"**(新建设计文件)
|
|
||||||
2. 会自动打开一个空白画布
|
|
||||||
|
|
||||||
### 1.2 创建正方形画框
|
|
||||||
1. 按键盘 **F** 键(Frame 工具)
|
|
||||||
2. 在右侧属性面板找到 **"Frame"** 区域
|
|
||||||
3. 在宽度(W)输入:**1024**
|
|
||||||
4. 在高度(H)输入:**1024**
|
|
||||||
5. 按 **Enter** 确认
|
|
||||||
|
|
||||||
**✅ 检查点**:你应该看到一个白色的正方形
|
|
||||||
|
|
||||||
### 1.3 命名画框
|
|
||||||
1. 双击画框名称(左侧图层面板)
|
|
||||||
2. 改名为:**FocusBuddy 图标**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 第二步:创建背景渐变(3分钟)
|
|
||||||
|
|
||||||
### 2.1 绘制背景矩形
|
|
||||||
1. 按键盘 **R** 键(矩形工具)
|
|
||||||
2. 在画框内拖拽,绘制一个矩形
|
|
||||||
3. 在右侧属性面板输入:
|
|
||||||
- **W**(宽度):1024
|
|
||||||
- **H**(高度):1024
|
|
||||||
- **X**:0
|
|
||||||
- **Y**:0
|
|
||||||
|
|
||||||
### 2.2 添加渐变色
|
|
||||||
1. 右侧找到 **"Fill"**(填充)
|
|
||||||
2. 点击颜色方块,打开颜色选择器
|
|
||||||
3. 在颜色选择器顶部,找到填充类型图标区域
|
|
||||||
4. 点击渐变图标(通常是第二个图标,有渐变效果的图标)
|
|
||||||
5. 或者直接在颜色方块上看到一个方形图标,点击它切换到 **Linear gradient**(线性渐变)
|
|
||||||
|
|
||||||
### 2.3 设置渐变颜色
|
|
||||||
**第一个色块(顶部)**:
|
|
||||||
1. 点击渐变条上的第一个圆点
|
|
||||||
2. 删除原来的代码,输入:**A7C4BC**
|
|
||||||
3. 按 Enter
|
|
||||||
|
|
||||||
**第二个色块(底部)**:
|
|
||||||
1. 点击渐变条上的第二个圆点
|
|
||||||
2. 删除原来的代码,输入:**88C9A1**
|
|
||||||
3. 按 Enter
|
|
||||||
|
|
||||||
### 2.4 调整渐变方向
|
|
||||||
1. 将渐变条旋转为竖直方向(从上到下)
|
|
||||||
2. 确保顶部是 #A7C4BC(浅绿色)
|
|
||||||
3. 底部是 #88C9A1(明绿色)
|
|
||||||
|
|
||||||
**✅ 检查点**:背景应该是从上到下的绿色渐变
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔵 第三步:绘制外圆环(5分钟)
|
|
||||||
|
|
||||||
### 3.1 创建圆环
|
|
||||||
1. 按键盘 **O** 键(椭圆工具)
|
|
||||||
2. **按住 Shift 键**,在画布中心拖拽出一个正圆
|
|
||||||
3. 在右侧输入尺寸:
|
|
||||||
- **W**:800
|
|
||||||
- **H**:800
|
|
||||||
|
|
||||||
### 3.2 居中对齐
|
|
||||||
1. 选中这个圆(点击它)
|
|
||||||
2. 同时按住 **Ctrl**(Windows)或 **Cmd**(Mac),点击背景画框
|
|
||||||
3. 顶部工具栏会出现对齐按钮
|
|
||||||
4. 点击 **居中对齐** 和 **垂直居中**
|
|
||||||
|
|
||||||
### 3.3 设置圆环样式
|
|
||||||
**填充(Fill)**:
|
|
||||||
1. 点击 Fill 右边的减号 **-**,删除填充
|
|
||||||
|
|
||||||
**描边(Stroke)**:
|
|
||||||
1. 点击 **"Stroke"** 旁边的 **+** 号
|
|
||||||
2. 点击颜色方块,输入:**F8F6F2**(米白色)
|
|
||||||
3. 找到 **"Stroke weight"**(描边粗细)
|
|
||||||
4. 输入:**60**
|
|
||||||
|
|
||||||
**透明度**:
|
|
||||||
1. 找到右上角的 **"Pass through"** 下拉菜单
|
|
||||||
2. 拖动下方的透明度滑块到 **90%**
|
|
||||||
|
|
||||||
**✅ 检查点**:应该看到一个粗粗的白色圆环
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 💾 随时保存你的工作
|
|
||||||
|
|
||||||
**Figma 会自动保存**,但你也可以手动保存:
|
|
||||||
|
|
||||||
1. **快捷键保存**:
|
|
||||||
- Windows: 按 **Ctrl + S**
|
|
||||||
- Mac: 按 **Cmd + S**
|
|
||||||
|
|
||||||
2. **查看保存状态**:
|
|
||||||
- 文件名旁边会显示 **"Saved"**(已保存)
|
|
||||||
- 如果显示 **"Saving..."**(保存中),等几秒即可
|
|
||||||
|
|
||||||
3. **重命名文件**:
|
|
||||||
- 点击顶部的文件名("Untitled")
|
|
||||||
- 输入新名字,如:**"FocusBuddy 图标"**
|
|
||||||
- 按 Enter
|
|
||||||
|
|
||||||
4. **下次继续**:
|
|
||||||
- 关闭浏览器后,你的设计会保存在云端
|
|
||||||
- 下次登录 Figma,在首页找到你的文件
|
|
||||||
- 点击即可继续编辑
|
|
||||||
|
|
||||||
**💡 提示**:可以随时暂停,Figma 会自动保存你的进度!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔵 第四步:绘制内圆(4分钟)
|
|
||||||
|
|
||||||
### 4.1 创建内圆
|
|
||||||
1. 按 **O** 键
|
|
||||||
2. **按住 Shift** 拖拽出一个圆
|
|
||||||
3. 设置尺寸:
|
|
||||||
- **W**:560
|
|
||||||
- **H**:560
|
|
||||||
|
|
||||||
### 4.2 居中对齐
|
|
||||||
1. 选中内圆
|
|
||||||
2. 按住 **Ctrl/Cmd**,点击画框
|
|
||||||
3. 点击居中对齐按钮
|
|
||||||
|
|
||||||
### 4.3 设置内圆颜色
|
|
||||||
1. **Fill**(填充):**F8F6F2**(米白色)
|
|
||||||
2. **Opacity**(不透明度):**95%**
|
|
||||||
|
|
||||||
**✅ 检查点**:中间有一个大大的白色圆
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 😊 第五步:添加笑脸(可选,8分钟)
|
|
||||||
|
|
||||||
### 5.1 绘制左眼
|
|
||||||
1. 按 **O** 键
|
|
||||||
2. 按住 Shift 画一个小圆
|
|
||||||
3. 尺寸:**W: 48, H: 48**
|
|
||||||
4. 位置:**X: 445, Y: 465**
|
|
||||||
5. 填充颜色:**5B6D6D**(灰色)
|
|
||||||
6. 不透明度:**70%**
|
|
||||||
|
|
||||||
### 5.2 绘制右眼
|
|
||||||
1. 按 **Ctrl/Cmd + D** 复制左眼
|
|
||||||
2. 拖动到右边对称位置
|
|
||||||
3. 或直接设置 **X: 530**
|
|
||||||
|
|
||||||
### 5.3 绘制微笑
|
|
||||||
1. 按 **P** 键(钢笔工具)
|
|
||||||
2. 在左眼下方点一下(起点)
|
|
||||||
3. 在中间点一下,**向下拖动** 形成弧度
|
|
||||||
4. 在右眼下方点一下(终点)
|
|
||||||
5. 按 **Esc** 退出钢笔工具
|
|
||||||
|
|
||||||
### 5.4 调整微笑样式
|
|
||||||
1. 选中刚画的曲线
|
|
||||||
2. 删除 **Fill**(填充)
|
|
||||||
3. 添加 **Stroke**(描边):
|
|
||||||
- 颜色:**5B6D6D**
|
|
||||||
- 粗细:**24**
|
|
||||||
- 不透明度:**70%**
|
|
||||||
4. 找到 **Cap** 选项,选择 **Round**(圆角)
|
|
||||||
|
|
||||||
**💡 提示**:如果微笑弧度不满意,可以用 **A** 键(选择工具)拖动中间的点调整
|
|
||||||
|
|
||||||
**✅ 检查点**:应该看到一个温柔的笑脸
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 第六步:添加中心点(2分钟)
|
|
||||||
|
|
||||||
### 6.1 绘制中心圆点
|
|
||||||
1. 按 **O** 键
|
|
||||||
2. 按住 Shift 画圆
|
|
||||||
3. 尺寸:**W: 160, H: 160**
|
|
||||||
4. 居中对齐
|
|
||||||
5. 填充颜色:**A7C4BC**(主色)
|
|
||||||
6. 不透明度:**30%**
|
|
||||||
|
|
||||||
**✅ 检查点**:中心有一个淡淡的圆点
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 第七步:整体优化(3分钟)
|
|
||||||
|
|
||||||
### 7.1 添加阴影(可选)
|
|
||||||
1. 选中内圆(大白圆)
|
|
||||||
2. 右侧找到 **"Effects"**
|
|
||||||
3. 点击 **+** 号
|
|
||||||
4. 选择 **"Drop Shadow"**(投影)
|
|
||||||
5. 设置:
|
|
||||||
- **X**: 0
|
|
||||||
- **Y**: 4
|
|
||||||
- **Blur**: 20
|
|
||||||
- **Color**: 黑色,透明度 10%
|
|
||||||
|
|
||||||
### 7.2 检查整体效果
|
|
||||||
1. 按 **Ctrl/Cmd + 0**(数字零)缩放到适合大小
|
|
||||||
2. 查看整体是否和谐
|
|
||||||
3. 确保所有元素都居中对齐
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📤 第八步:导出图标(5分钟)
|
|
||||||
|
|
||||||
### 8.1 选择导出对象
|
|
||||||
1. 点击最外层的画框(FocusBuddy 图标)
|
|
||||||
2. 确保左侧图层面板中画框名称高亮
|
|
||||||
|
|
||||||
### 8.2 设置导出参数
|
|
||||||
1. 右侧滚动到最底部
|
|
||||||
2. 找到 **"Export"**(导出)区域
|
|
||||||
3. 点击 **+** 号
|
|
||||||
|
|
||||||
### 8.3 导出 PNG
|
|
||||||
1. 格式选择:**PNG**
|
|
||||||
2. 尺寸选择:**1x**(保持 1024×1024)
|
|
||||||
3. 点击 **"Export FocusBuddy 图标"** 按钮
|
|
||||||
4. 保存到电脑,文件名:**icon-1024.png**
|
|
||||||
|
|
||||||
**✅ 检查点**:你应该得到一个 1024×1024 的 PNG 文件
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 第九步:生成所有尺寸(5分钟)
|
|
||||||
|
|
||||||
### 9.1 使用在线工具
|
|
||||||
1. 打开浏览器,访问:**https://appicon.co**
|
|
||||||
2. 点击 **"Choose File"**
|
|
||||||
3. 上传刚才导出的 **icon-1024.png**
|
|
||||||
|
|
||||||
### 9.2 生成图标包
|
|
||||||
1. 等待上传完成(几秒钟)
|
|
||||||
2. 勾选 **iOS** 和 **Android**
|
|
||||||
3. 点击 **"Generate"**(生成)
|
|
||||||
|
|
||||||
### 9.3 下载
|
|
||||||
1. 点击 **"Download"** 按钮
|
|
||||||
2. 会下载一个 ZIP 文件
|
|
||||||
3. 解压到桌面
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 第十步:安装到项目(10分钟)
|
|
||||||
|
|
||||||
### 10.1 iOS 图标安装
|
|
||||||
1. 打开项目文件夹:
|
|
||||||
```
|
|
||||||
f:\cursor-auto\focusBuddy\ios\Runner\Assets.xcassets\AppIcon.appiconset
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 删除原有的图标文件
|
|
||||||
|
|
||||||
3. 从下载的 ZIP 中找到 **iOS** 文件夹
|
|
||||||
|
|
||||||
4. 复制所有图标文件到上面的文件夹
|
|
||||||
|
|
||||||
### 10.2 Android 图标安装
|
|
||||||
1. 打开项目文件夹:
|
|
||||||
```
|
|
||||||
f:\cursor-auto\focusBuddy\android\app\src\main\res
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 你会看到多个文件夹:
|
|
||||||
- mipmap-mdpi
|
|
||||||
- mipmap-hdpi
|
|
||||||
- mipmap-xhdpi
|
|
||||||
- mipmap-xxhdpi
|
|
||||||
- mipmap-xxxhdpi
|
|
||||||
|
|
||||||
3. 从 ZIP 中的 **Android** 文件夹,找到对应尺寸的图标
|
|
||||||
|
|
||||||
4. 复制到对应文件夹,全部命名为:**ic_launcher.png**
|
|
||||||
|
|
||||||
### 10.3 测试
|
|
||||||
```bash
|
|
||||||
# 打开终端,运行:
|
|
||||||
flutter clean
|
|
||||||
flutter run -d edge
|
|
||||||
```
|
|
||||||
|
|
||||||
**✅ 检查点**:浏览器标签页应该显示新图标
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 快速参考表
|
|
||||||
|
|
||||||
### 常用快捷键
|
|
||||||
| 快捷键 | 功能 |
|
|
||||||
|--------|------|
|
|
||||||
| F | 创建画框 |
|
|
||||||
| R | 矩形工具 |
|
|
||||||
| O | 椭圆/圆形工具 |
|
|
||||||
| P | 钢笔工具 |
|
|
||||||
| V 或 A | 选择工具 |
|
|
||||||
| Ctrl/Cmd + D | 复制 |
|
|
||||||
| Ctrl/Cmd + 0 | 缩放到适合大小 |
|
|
||||||
| Shift + 拖动 | 保持等比例 |
|
|
||||||
|
|
||||||
### 元素尺寸速查
|
|
||||||
| 元素 | 宽度 | 高度 | 位置 |
|
|
||||||
|------|------|------|------|
|
|
||||||
| 画框 | 1024 | 1024 | - |
|
|
||||||
| 背景 | 1024 | 1024 | 0, 0 |
|
|
||||||
| 外圆环 | 800 | 800 | 居中 |
|
|
||||||
| 内圆 | 560 | 560 | 居中 |
|
|
||||||
| 眼睛 | 48 | 48 | 左眼 X:445, 右眼 X:530 |
|
|
||||||
| 中心点 | 160 | 160 | 居中 |
|
|
||||||
|
|
||||||
### 颜色速查
|
|
||||||
| 用途 | 颜色代码 | 说明 |
|
|
||||||
|------|----------|------|
|
|
||||||
| 渐变顶部 | #A7C4BC | 主色调 |
|
|
||||||
| 渐变底部 | #88C9A1 | 成功色 |
|
|
||||||
| 圆环/内圆 | #F8F6F2 | 背景色 |
|
|
||||||
| 笑脸 | #5B6D6D | 文字色 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❓ 常见问题
|
|
||||||
|
|
||||||
### Q1: 渐变色看起来不对?
|
|
||||||
**A**: 确保渐变方向是竖直的,顶部浅色 (#A7C4BC),底部深色 (#88C9A1)
|
|
||||||
|
|
||||||
### Q2: 圆形不居中怎么办?
|
|
||||||
**A**:
|
|
||||||
1. 选中圆形
|
|
||||||
2. 按住 Ctrl/Cmd,点击背景画框
|
|
||||||
3. 点击顶部的居中对齐按钮(两个都要点)
|
|
||||||
|
|
||||||
### Q3: 笑脸的弧度不满意?
|
|
||||||
**A**:
|
|
||||||
1. 用 **A** 键选择钢笔工具画的线
|
|
||||||
2. 拖动中间的点上下移动
|
|
||||||
3. 或者删除重画
|
|
||||||
|
|
||||||
### Q4: 颜色输入在哪里?
|
|
||||||
**A**:
|
|
||||||
1. 选中对象
|
|
||||||
2. 右侧 Fill 或 Stroke 区域
|
|
||||||
3. 点击颜色方块
|
|
||||||
4. 在 **HEX** 输入框输入颜色代码
|
|
||||||
|
|
||||||
### Q5: 导出的图片太小?
|
|
||||||
**A**:
|
|
||||||
1. 确保选中的是最外层的画框
|
|
||||||
2. 导出尺寸选择 **1x**
|
|
||||||
3. 不要选择 0.5x 或其他缩放
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 设计技巧
|
|
||||||
|
|
||||||
### 技巧 1: 使用网格对齐
|
|
||||||
1. 按 **Ctrl/Cmd + '**(单引号)显示网格
|
|
||||||
2. 确保所有元素对齐到网格
|
|
||||||
|
|
||||||
### 技巧 2: 组合元素
|
|
||||||
1. 选中笑脸的所有元素(两个眼睛+嘴巴)
|
|
||||||
2. 按 **Ctrl/Cmd + G** 组合
|
|
||||||
3. 方便统一移动和调整
|
|
||||||
|
|
||||||
### 技巧 3: 保存备份
|
|
||||||
1. 按 **Ctrl/Cmd + S** 保存
|
|
||||||
2. Figma 会自动保存到云端
|
|
||||||
3. 下次可以直接打开继续编辑
|
|
||||||
|
|
||||||
### 技巧 4: 快速测试小尺寸
|
|
||||||
1. 选中画框
|
|
||||||
2. 按 **Ctrl/Cmd + D** 复制
|
|
||||||
3. 将复制的画框缩小到 48×48
|
|
||||||
4. 查看小尺寸效果
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 完成清单
|
|
||||||
|
|
||||||
制作过程:
|
|
||||||
- [ ] 创建 1024×1024 画框
|
|
||||||
- [ ] 添加绿色渐变背景
|
|
||||||
- [ ] 绘制外圆环(800×800)
|
|
||||||
- [ ] 绘制内圆(560×560)
|
|
||||||
- [ ] 添加笑脸(可选)
|
|
||||||
- [ ] 添加中心点
|
|
||||||
- [ ] 导出 PNG 文件
|
|
||||||
|
|
||||||
生成和安装:
|
|
||||||
- [ ] 上传到 appicon.co
|
|
||||||
- [ ] 下载生成的图标包
|
|
||||||
- [ ] 安装 iOS 图标
|
|
||||||
- [ ] 安装 Android 图标
|
|
||||||
- [ ] 运行测试
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 完成效果
|
|
||||||
|
|
||||||
完成后你应该得到:
|
|
||||||
1. ✅ 一个温柔友善的图标
|
|
||||||
2. ✅ 符合 FocusBuddy 品牌色
|
|
||||||
3. ✅ 在小尺寸下依然清晰
|
|
||||||
4. ✅ iOS 和 Android 所有尺寸
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 学习资源
|
|
||||||
|
|
||||||
如果遇到困难,可以看这些教程:
|
|
||||||
|
|
||||||
### 视频教程(搜索关键词)
|
|
||||||
- Bilibili: "Figma 入门教程"
|
|
||||||
- Bilibili: "如何用 Figma 设计 App 图标"
|
|
||||||
- YouTube: "Figma tutorial for beginners"
|
|
||||||
|
|
||||||
### 文字教程
|
|
||||||
- Figma 官方文档(有中文): https://help.figma.com
|
|
||||||
- 设计导航网站搜索 "Figma 教程"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⏱️ 时间估算
|
|
||||||
|
|
||||||
| 步骤 | 时间 |
|
|
||||||
|------|------|
|
|
||||||
| 注册登录 Figma | 3 分钟 |
|
|
||||||
| 创建画布和背景 | 5 分钟 |
|
|
||||||
| 绘制圆环和圆形 | 9 分钟 |
|
|
||||||
| 添加笑脸 | 8 分钟(可选) |
|
|
||||||
| 整体优化 | 3 分钟 |
|
|
||||||
| 导出和生成 | 10 分钟 |
|
|
||||||
| 安装测试 | 10 分钟 |
|
|
||||||
| **总计** | **30-40 分钟** |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 下一步
|
|
||||||
|
|
||||||
完成图标后:
|
|
||||||
1. 📸 准备应用商店截图(6张)
|
|
||||||
2. 🧪 在真机上测试
|
|
||||||
3. 📝 完善应用描述
|
|
||||||
4. 🚀 提交到应用商店
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💬 需要帮助?
|
|
||||||
|
|
||||||
如果在设计过程中遇到问题:
|
|
||||||
|
|
||||||
1. **重新查看本教程** - 确保每一步都按顺序完成
|
|
||||||
2. **查看预览文件** - 打开 `icon-preview.html` 对比效果
|
|
||||||
3. **简化设计** - 可以不加笑脸,只保留圆环
|
|
||||||
4. **使用模板** - 搜索 "Figma app icon template" 找现成模板
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**祝你设计顺利!** 🎨
|
|
||||||
|
|
||||||
你正在创作一个温暖、友善、支持性的图标,它完美代表了 FocusBuddy 的理念:一个温柔的专注伙伴,而不是严格的任务监工。
|
|
||||||
|
|
||||||
**加油!** 💪
|
|
||||||
88
MACOS_BUILD_GUIDE.md
Normal file
88
MACOS_BUILD_GUIDE.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# macOS 编译测试指南
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/yuantiancai/work/FocusBuddy
|
||||||
|
flutter pub get
|
||||||
|
flutter run -d macos
|
||||||
|
```
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
### Flutter
|
||||||
|
Flutter 已安装在 `/Users/yuantiancai/sdk/flutter`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 添加到 PATH
|
||||||
|
export PATH="$PATH:$HOME/sdk/flutter/bin"
|
||||||
|
source ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Xcode
|
||||||
|
从 Mac App Store 安装 Xcode,然后:
|
||||||
|
```bash
|
||||||
|
sudo xcodebuild -license accept
|
||||||
|
```
|
||||||
|
|
||||||
|
### CocoaPods
|
||||||
|
使用 rbenv 安装 Ruby 3.x 和 CocoaPods:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安装 rbenv
|
||||||
|
brew install rbenv ruby-build
|
||||||
|
echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc
|
||||||
|
source ~/.zshrc
|
||||||
|
|
||||||
|
# 安装 Ruby 3.3.8
|
||||||
|
rbenv install 3.3.8
|
||||||
|
rbenv global 3.3.8
|
||||||
|
|
||||||
|
# 安装 CocoaPods
|
||||||
|
gem install cocoapods
|
||||||
|
```
|
||||||
|
|
||||||
|
## 编译运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS 桌面
|
||||||
|
flutter run -d macos
|
||||||
|
|
||||||
|
# iOS 模拟器
|
||||||
|
open -a Simulator
|
||||||
|
flutter run -d ios
|
||||||
|
|
||||||
|
# Release 版本
|
||||||
|
flutter build macos --release
|
||||||
|
# 输出:build/macos/Build/Products/Release/focus_buddy.app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### CocoaPods 错误
|
||||||
|
```bash
|
||||||
|
cd ios && pod install && cd ..
|
||||||
|
flutter clean && flutter pub get
|
||||||
|
```
|
||||||
|
|
||||||
|
### 构建缓存问题
|
||||||
|
```bash
|
||||||
|
flutter clean
|
||||||
|
flutter pub get
|
||||||
|
```
|
||||||
|
|
||||||
|
### Xcode 签名
|
||||||
|
打开 `ios/Runner.xcworkspace`,在 "Signing & Capabilities" 配置开发团队
|
||||||
|
|
||||||
|
## 开发提示
|
||||||
|
|
||||||
|
运行时快捷键:
|
||||||
|
- `r` - 热重载
|
||||||
|
- `R` - 热重启
|
||||||
|
- `q` - 退出
|
||||||
|
|
||||||
|
代码检查:
|
||||||
|
```bash
|
||||||
|
flutter analyze
|
||||||
|
flutter test
|
||||||
|
```
|
||||||
@@ -1,530 +0,0 @@
|
|||||||
# 📱 本地通知功能 - 实现文档
|
|
||||||
|
|
||||||
**实现日期**: 2025-11-22
|
|
||||||
**状态**: ✅ 完成
|
|
||||||
**平台支持**: Android, iOS (Web不支持)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 功能概述
|
|
||||||
|
|
||||||
FocusBuddy 现在支持本地通知,在专注计时完成时自动提醒用户,即使应用在后台运行。
|
|
||||||
|
|
||||||
### 核心特性
|
|
||||||
- ✅ 计时完成时自动发送通知
|
|
||||||
- ✅ 显示专注时长和分心次数
|
|
||||||
- ✅ 支持震动和声音
|
|
||||||
- ✅ 自动请求权限
|
|
||||||
- ✅ Web 平台优雅降级(不报错)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ 架构设计
|
|
||||||
|
|
||||||
### 文件结构
|
|
||||||
```
|
|
||||||
lib/services/notification_service.dart # 通知服务(新增)
|
|
||||||
lib/main.dart # 初始化通知服务(已修改)
|
|
||||||
lib/screens/focus_screen.dart # 计时完成时调用通知(已修改)
|
|
||||||
android/app/src/main/AndroidManifest.xml # Android权限(已修改)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 服务设计
|
|
||||||
- **单例模式**: 全局只有一个 NotificationService 实例
|
|
||||||
- **延迟初始化**: 首次调用时才初始化
|
|
||||||
- **平台检测**: 自动识别 Web 平台并跳过
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 代码实现
|
|
||||||
|
|
||||||
### 1. NotificationService 类
|
|
||||||
|
|
||||||
**位置**: `lib/services/notification_service.dart`
|
|
||||||
|
|
||||||
**关键方法**:
|
|
||||||
|
|
||||||
#### `initialize()` - 初始化服务
|
|
||||||
```dart
|
|
||||||
Future<void> initialize() async {
|
|
||||||
if (_initialized) return;
|
|
||||||
|
|
||||||
// Web 平台跳过
|
|
||||||
if (kIsWeb) return;
|
|
||||||
|
|
||||||
// Android/iOS 配置
|
|
||||||
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
||||||
const iosSettings = DarwinInitializationSettings(...);
|
|
||||||
|
|
||||||
await _notifications.initialize(initSettings);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `requestPermissions()` - 请求权限(iOS)
|
|
||||||
```dart
|
|
||||||
Future<bool> requestPermissions() async {
|
|
||||||
// iOS 需要显式请求,Android 自动授予
|
|
||||||
final result = await _notifications
|
|
||||||
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
|
|
||||||
?.requestPermissions(...);
|
|
||||||
return result ?? true;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `showFocusCompletedNotification()` - 显示完成通知
|
|
||||||
```dart
|
|
||||||
Future<void> showFocusCompletedNotification({
|
|
||||||
required int minutes,
|
|
||||||
required int distractionCount,
|
|
||||||
}) async {
|
|
||||||
final title = '🎉 Focus session complete!';
|
|
||||||
final body = distractionCount == 0
|
|
||||||
? 'You focused for $minutes minutes without distractions!'
|
|
||||||
: 'You focused for $minutes minutes. Great effort!';
|
|
||||||
|
|
||||||
await _notifications.show(0, title, body, details);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. main.dart 初始化
|
|
||||||
|
|
||||||
**修改内容**:
|
|
||||||
```dart
|
|
||||||
void main() async {
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
|
||||||
|
|
||||||
await StorageService.init();
|
|
||||||
|
|
||||||
// 新增:初始化通知服务
|
|
||||||
final notificationService = NotificationService();
|
|
||||||
await notificationService.initialize();
|
|
||||||
await notificationService.requestPermissions();
|
|
||||||
|
|
||||||
runApp(MyApp(...));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**何时调用**:
|
|
||||||
- 应用启动时自动初始化
|
|
||||||
- 自动请求权限(iOS 会弹出权限对话框)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. FocusScreen 计时完成
|
|
||||||
|
|
||||||
**修改位置**: `lib/screens/focus_screen.dart` 第 56-79 行
|
|
||||||
|
|
||||||
**修改内容**:
|
|
||||||
```dart
|
|
||||||
void _onTimerComplete() async {
|
|
||||||
_timer.cancel();
|
|
||||||
_saveFocusSession(completed: true);
|
|
||||||
|
|
||||||
// 新增:发送通知
|
|
||||||
final notificationService = NotificationService();
|
|
||||||
await notificationService.showFocusCompletedNotification(
|
|
||||||
minutes: widget.durationMinutes,
|
|
||||||
distractionCount: _distractions.length,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!mounted) return;
|
|
||||||
Navigator.pushReplacement(...);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**触发时机**:
|
|
||||||
- 计时器倒数到 0 时
|
|
||||||
- 在导航到 Complete Screen 之前
|
|
||||||
- 保存数据之后
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 Android 配置
|
|
||||||
|
|
||||||
### AndroidManifest.xml
|
|
||||||
|
|
||||||
**文件位置**: `android/app/src/main/AndroidManifest.xml`
|
|
||||||
|
|
||||||
**添加的权限**:
|
|
||||||
```xml
|
|
||||||
<!-- Android 13+ 通知权限(必需)-->
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
|
||||||
|
|
||||||
<!-- 震动权限(可选,增强体验)-->
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
|
||||||
|
|
||||||
<!-- Wake Lock(可选,后台计时)-->
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 权限说明
|
|
||||||
|
|
||||||
| 权限 | 必需性 | 用途 | Android版本 |
|
|
||||||
|------|--------|------|------------|
|
|
||||||
| POST_NOTIFICATIONS | **必需** | 发送通知 | 13+ (API 33+) |
|
|
||||||
| VIBRATE | 可选 | 通知震动 | 所有版本 |
|
|
||||||
| WAKE_LOCK | 可选 | 后台计时 | 所有版本 |
|
|
||||||
|
|
||||||
### Android 权限流程
|
|
||||||
|
|
||||||
**Android 12 及以下**:
|
|
||||||
1. 自动授予通知权限
|
|
||||||
2. 无需用户确认
|
|
||||||
|
|
||||||
**Android 13+**:
|
|
||||||
1. 首次发送通知时,系统自动弹出权限对话框
|
|
||||||
2. 用户可以选择"允许"或"拒绝"
|
|
||||||
3. 拒绝后可在设置中手动开启
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🍎 iOS 配置
|
|
||||||
|
|
||||||
### Info.plist
|
|
||||||
|
|
||||||
**不需要修改** - iOS 通知权限在运行时请求,无需配置文件声明。
|
|
||||||
|
|
||||||
### iOS 权限流程
|
|
||||||
|
|
||||||
1. **首次启动**:
|
|
||||||
- App 启动时调用 `requestPermissions()`
|
|
||||||
- 系统弹出权限对话框:
|
|
||||||
```
|
|
||||||
"FocusBuddy" Would Like to Send You Notifications
|
|
||||||
Notifications may include alerts, sounds, and icon badges.
|
|
||||||
[Don't Allow] [Allow]
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **用户选择**:
|
|
||||||
- **允许**: 正常发送通知
|
|
||||||
- **拒绝**: 静默失败(不影响应用运行)
|
|
||||||
|
|
||||||
3. **后续修改**:
|
|
||||||
- 用户可在 设置 > FocusBuddy > 通知 中修改
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 Web 平台处理
|
|
||||||
|
|
||||||
### 策略:优雅降级
|
|
||||||
|
|
||||||
**为什么 Web 不支持**:
|
|
||||||
- `flutter_local_notifications` 不支持 Web
|
|
||||||
- Web 使用不同的通知 API(需要 Service Worker)
|
|
||||||
|
|
||||||
**如何处理**:
|
|
||||||
```dart
|
|
||||||
if (kIsWeb) {
|
|
||||||
print('Notifications not supported on web platform');
|
|
||||||
return; // 静默跳过,不报错
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**用户体验**:
|
|
||||||
- Web 版用户不会看到通知
|
|
||||||
- 不会报错或崩溃
|
|
||||||
- 计时完成后仍正常跳转到 Complete Screen
|
|
||||||
|
|
||||||
**未来改进** (可选):
|
|
||||||
- 使用 Web Notification API
|
|
||||||
- 或显示应用内弹窗提示
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 测试指南
|
|
||||||
|
|
||||||
### Android 测试
|
|
||||||
|
|
||||||
#### 准备工作
|
|
||||||
```bash
|
|
||||||
# 1. 连接 Android 设备或启动模拟器
|
|
||||||
flutter devices
|
|
||||||
|
|
||||||
# 2. 运行应用
|
|
||||||
flutter run -d <android-device-id>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 测试步骤
|
|
||||||
|
|
||||||
**测试 1: 首次权限请求(Android 13+)**
|
|
||||||
```
|
|
||||||
1. 卸载应用(清除权限状态)
|
|
||||||
2. 重新安装并启动
|
|
||||||
3. 开始一次专注(设置为 1 分钟测试)
|
|
||||||
4. 等待计时完成
|
|
||||||
5. 预期:系统弹出权限对话框
|
|
||||||
6. 点击"允许"
|
|
||||||
7. 预期:看到通知
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试 2: 前台通知**
|
|
||||||
```
|
|
||||||
1. 应用在前台
|
|
||||||
2. 开始专注(1分钟)
|
|
||||||
3. 等待完成
|
|
||||||
4. 预期:
|
|
||||||
- 顶部通知栏出现通知
|
|
||||||
- 有震动(如果手机未静音)
|
|
||||||
- 有声音(如果手机未静音)
|
|
||||||
- 自动跳转到 Complete Screen
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试 3: 后台通知**
|
|
||||||
```
|
|
||||||
1. 开始专注(1分钟)
|
|
||||||
2. 按 Home 键,应用进入后台
|
|
||||||
3. 等待计时完成
|
|
||||||
4. 预期:
|
|
||||||
- 收到通知
|
|
||||||
- 点击通知可回到应用
|
|
||||||
- 看到 Complete Screen
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试 4: 拒绝权限**
|
|
||||||
```
|
|
||||||
1. 在设置中禁用通知权限
|
|
||||||
2. 开始专注
|
|
||||||
3. 完成后不会有通知
|
|
||||||
4. 但应用正常跳转到 Complete Screen
|
|
||||||
5. 预期:无崩溃
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### iOS 测试
|
|
||||||
|
|
||||||
#### 准备工作
|
|
||||||
```bash
|
|
||||||
# 需要 macOS + Xcode
|
|
||||||
# 1. 连接 iPhone 或启动模拟器
|
|
||||||
flutter devices
|
|
||||||
|
|
||||||
# 2. 运行应用
|
|
||||||
flutter run -d <ios-device-id>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 测试步骤
|
|
||||||
|
|
||||||
**测试 1: 权限对话框**
|
|
||||||
```
|
|
||||||
1. 首次启动应用
|
|
||||||
2. 预期:立即看到权限对话框
|
|
||||||
"FocusBuddy Would Like to Send You Notifications"
|
|
||||||
3. 点击 "Allow"
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试 2: 通知内容**
|
|
||||||
```
|
|
||||||
1. 完成一次专注(0次分心)
|
|
||||||
2. 预期通知内容:
|
|
||||||
标题: 🎉 Focus session complete!
|
|
||||||
正文: You focused for 15 minutes without distractions!
|
|
||||||
|
|
||||||
3. 完成一次专注(3次分心)
|
|
||||||
4. 预期通知内容:
|
|
||||||
标题: 🎉 Focus session complete!
|
|
||||||
正文: You focused for 15 minutes. Great effort!
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试 3: 后台通知**
|
|
||||||
```
|
|
||||||
1. 开始专注
|
|
||||||
2. 滑回主屏幕
|
|
||||||
3. 等待完成
|
|
||||||
4. 预期:锁屏/顶部有通知
|
|
||||||
5. 点击通知打开应用
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Web 测试
|
|
||||||
|
|
||||||
#### 测试步骤
|
|
||||||
```
|
|
||||||
1. 运行 Web 版:flutter run -d edge
|
|
||||||
2. 开始专注
|
|
||||||
3. 等待完成
|
|
||||||
4. 预期:
|
|
||||||
- 控制台输出:Notifications not supported on web platform
|
|
||||||
- 无通知
|
|
||||||
- 正常跳转到 Complete Screen
|
|
||||||
- 无报错
|
|
||||||
```
|
|
||||||
|
|
||||||
✅ **通过标准**: 应用正常运行,无崩溃
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 通知内容逻辑
|
|
||||||
|
|
||||||
### 标题
|
|
||||||
固定内容:`🎉 Focus session complete!`
|
|
||||||
|
|
||||||
### 正文
|
|
||||||
动态内容,根据分心次数变化:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
if (distractionCount == 0) {
|
|
||||||
body = 'You focused for $minutes minutes without distractions!';
|
|
||||||
} else {
|
|
||||||
body = 'You focused for $minutes minutes. Great effort!';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
- 25分钟,0次分心: "You focused for 25 minutes without distractions!"
|
|
||||||
- 15分钟,3次分心: "You focused for 15 minutes. Great effort!"
|
|
||||||
|
|
||||||
### 设计理念
|
|
||||||
- **正向鼓励**: 即使有分心,也用"Great effort"
|
|
||||||
- **无惩罚**: 不会说"但你分心了3次"
|
|
||||||
- **符合产品价值观**: 温柔、支持、无评判
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 配置选项
|
|
||||||
|
|
||||||
### 当前实现
|
|
||||||
|
|
||||||
| 特性 | Android | iOS |
|
|
||||||
|------|---------|-----|
|
|
||||||
| 声音 | ✅ | ✅ |
|
|
||||||
| 震动 | ✅ | ✅ |
|
|
||||||
| Badge | ❌ | ✅ |
|
|
||||||
| 优先级 | High | Default |
|
|
||||||
| Channel | focus_completed | - |
|
|
||||||
|
|
||||||
### 可调整的参数
|
|
||||||
|
|
||||||
在 `notification_service.dart` 中:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
// Android 配置
|
|
||||||
const androidDetails = AndroidNotificationDetails(
|
|
||||||
'focus_completed', // Channel ID(不建议改)
|
|
||||||
'Focus Session Completed', // Channel Name(用户可见)
|
|
||||||
channelDescription: '...', // Channel描述
|
|
||||||
importance: Importance.high, // 重要性(改为 max 会横幅提示)
|
|
||||||
priority: Priority.high, // 优先级
|
|
||||||
enableVibration: true, // 震动开关
|
|
||||||
playSound: true, // 声音开关
|
|
||||||
);
|
|
||||||
|
|
||||||
// iOS 配置
|
|
||||||
const iosDetails = DarwinNotificationDetails(
|
|
||||||
presentAlert: true, // 显示提示
|
|
||||||
presentBadge: true, // 显示角标
|
|
||||||
presentSound: true, // 播放声音
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 未来改进建议
|
|
||||||
|
|
||||||
### 优先级低(可选)
|
|
||||||
|
|
||||||
1. **自定义通知声音**
|
|
||||||
- 添加温柔的提示音
|
|
||||||
- 替换系统默认声音
|
|
||||||
- 需要音频资源
|
|
||||||
|
|
||||||
2. **定时提醒**
|
|
||||||
- "你已经2小时没专注了,要来一次吗?"
|
|
||||||
- 使用 `showReminderNotification()`
|
|
||||||
- 需要后台任务(WorkManager)
|
|
||||||
|
|
||||||
3. **通知操作按钮**
|
|
||||||
- Android: 通知上添加 "再来一次" 按钮
|
|
||||||
- 点击直接开始新的专注
|
|
||||||
- 需要额外配置
|
|
||||||
|
|
||||||
4. **通知统计**
|
|
||||||
- "本周你已经专注了 12 小时!"
|
|
||||||
- 定期(如周日)发送总结
|
|
||||||
- 需要调度逻辑
|
|
||||||
|
|
||||||
5. **Web 通知支持**
|
|
||||||
- 使用 Web Notification API
|
|
||||||
- 需要 Service Worker
|
|
||||||
- 需要用户手动授权
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❗ 常见问题
|
|
||||||
|
|
||||||
### Q1: 为什么 Android 13 没有弹出权限对话框?
|
|
||||||
**A**: Android 13+ 权限会在**首次发送通知时**自动弹出,不是应用启动时。
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
- 完成一次完整的专注会话
|
|
||||||
- 或在设置中手动开启
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Q2: iOS 模拟器收不到通知?
|
|
||||||
**A**: iOS 模拟器通知功能有限制。
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
- 使用真机测试
|
|
||||||
- 或检查模拟器的通知设置
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Q3: Web 版为什么没有通知?
|
|
||||||
**A**: `flutter_local_notifications` 不支持 Web。
|
|
||||||
|
|
||||||
**当前方案**: 优雅降级,不报错
|
|
||||||
**未来方案**: 实现 Web Notification API
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Q4: 通知没有声音?
|
|
||||||
**A**: 检查以下设置:
|
|
||||||
1. 手机是否静音/勿扰模式
|
|
||||||
2. 应用通知权限是否开启
|
|
||||||
3. 通知重要性是否足够高
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Q5: 后台计时不准确?
|
|
||||||
**A**: Android 后台限制可能影响计时。
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
- 添加前台服务(Foreground Service)
|
|
||||||
- 或使用 WorkManager
|
|
||||||
- 当前 MVP 不实现,用户应在前台使用
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 总结
|
|
||||||
|
|
||||||
### ✅ 已实现
|
|
||||||
- [x] 通知服务架构
|
|
||||||
- [x] 计时完成通知
|
|
||||||
- [x] Android 权限配置
|
|
||||||
- [x] iOS 权限请求
|
|
||||||
- [x] Web 平台兼容
|
|
||||||
- [x] 完整文档
|
|
||||||
|
|
||||||
### 📊 影响
|
|
||||||
- **代码变更**: 3 个文件(新增1个,修改2个)
|
|
||||||
- **新增行数**: ~200 行
|
|
||||||
- **配置变更**: Android + iOS 权限
|
|
||||||
- **测试时间**: ~15 分钟(手动测试)
|
|
||||||
|
|
||||||
### 🎯 MVP 完成度
|
|
||||||
```
|
|
||||||
██████████████████▓░ 95% → 98%
|
|
||||||
```
|
|
||||||
|
|
||||||
**新增功能**: 本地通知 ✅
|
|
||||||
**待完成**: 应用图标、截图、上架准备
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**文档版本**: 1.0
|
|
||||||
**最后更新**: 2025-11-22
|
|
||||||
**维护者**: Claude
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
# 🎉 FocusBuddy 开发进度更新
|
|
||||||
|
|
||||||
**更新时间**: 2025年11月22日
|
|
||||||
**当前状态**: ✅ MVP 主要功能已完成!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 新增功能
|
|
||||||
|
|
||||||
### 1. History Screen ✅
|
|
||||||
完整的历史记录页面,包含:
|
|
||||||
- 📊 今日总结卡片(总时长、分心次数、完成会话数)
|
|
||||||
- 📅 按日期分组的会话列表
|
|
||||||
- ⏱️ 每个会话的详细信息(时间、时长、状态)
|
|
||||||
- ✨ 空状态提示(无记录时)
|
|
||||||
|
|
||||||
### 2. Settings Screen ✅
|
|
||||||
实用的设置页面,包含:
|
|
||||||
- ⏰ 默认专注时长选择(15/25/45分钟)
|
|
||||||
- 📱 使用 SharedPreferences 持久化设置
|
|
||||||
- 📋 隐私政策快速查看
|
|
||||||
- ℹ️ 关于 FocusBuddy 介绍
|
|
||||||
- 🔄 设置变更后自动更新首页
|
|
||||||
|
|
||||||
### 3. 动态时长支持 ✅
|
|
||||||
- 首页显示从设置中读取的默认时长
|
|
||||||
- 返回首页时自动刷新时长显示
|
|
||||||
- 所有页面互联互通
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 完整功能清单
|
|
||||||
|
|
||||||
### ✅ 已完成(90%)
|
|
||||||
|
|
||||||
| 功能模块 | 状态 | 备注 |
|
|
||||||
|---------|------|------|
|
|
||||||
| **核心计时** | ✅ | 完整倒计时 + 暂停/恢复 |
|
|
||||||
| **分心追踪** | ✅ | 4种类型 + 不中断计时 |
|
|
||||||
| **数据持久化** | ✅ | Hive 本地数据库 |
|
|
||||||
| **鼓励系统** | ✅ | 15条随机文案 |
|
|
||||||
| **完成页面** | ✅ | 统计 + 鼓励 |
|
|
||||||
| **History 页面** | ✅ | 完整历史记录 |
|
|
||||||
| **Settings 页面** | ✅ | 时长设置 + 关于 |
|
|
||||||
| **页面导航** | ✅ | 所有页面互联 |
|
|
||||||
| **主题系统** | ✅ | 莫兰迪配色 |
|
|
||||||
| **UI/UX** | ✅ | 符合设计规范 |
|
|
||||||
|
|
||||||
### ⏳ 待完成(10%)
|
|
||||||
|
|
||||||
| 功能 | 优先级 | 预计时间 |
|
|
||||||
|------|--------|---------|
|
|
||||||
| 本地通知 | 中 | 1小时 |
|
|
||||||
| Nunito 字体 | 低 | 30分钟 |
|
|
||||||
| App 图标 | 中 | 1小时 |
|
|
||||||
| 真机测试 | 高 | 2小时 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 MVP 完成度
|
|
||||||
|
|
||||||
```
|
|
||||||
███████████████████░ 95%
|
|
||||||
```
|
|
||||||
|
|
||||||
**距离可上线版本**: 仅差通知功能和真机测试!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 代码统计更新
|
|
||||||
|
|
||||||
| 文件类型 | 数量 | 代码行数 |
|
|
||||||
|---------|------|---------|
|
|
||||||
| Screens | 5 | ~900 行 |
|
|
||||||
| Models | 2 | ~80 行 |
|
|
||||||
| Services | 3 | ~150 行 |
|
|
||||||
| Theme | 4 | ~150 行 |
|
|
||||||
| **总计** | **14** | **~1,280 行** |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 新增的 UI 特性
|
|
||||||
|
|
||||||
### History Screen
|
|
||||||
- ✅ 今日总结卡片带徽章
|
|
||||||
- ✅ 按日期分组的时间线
|
|
||||||
- ✅ 完成/停止状态标识
|
|
||||||
- ✅ 空状态友好提示
|
|
||||||
|
|
||||||
### Settings Screen
|
|
||||||
- ✅ 自定义选择样式(单选按钮)
|
|
||||||
- ✅ 选中状态高亮
|
|
||||||
- ✅ "Default" 标签提示
|
|
||||||
- ✅ 弹窗式隐私政策和关于页面
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 测试建议
|
|
||||||
|
|
||||||
### 立即可测试的完整流程:
|
|
||||||
|
|
||||||
1. **首页 → 设置**
|
|
||||||
- 打开 Settings
|
|
||||||
- 更改默认时长为 15 分钟
|
|
||||||
- 返回首页
|
|
||||||
- ✅ 验证: 首页显示 "15 minutes"
|
|
||||||
|
|
||||||
2. **完整专注流程**
|
|
||||||
- 点击 Start Focusing
|
|
||||||
- 点击 2-3 次 "I got distracted"
|
|
||||||
- 选择不同分心类型
|
|
||||||
- 完成或提前停止
|
|
||||||
- 查看完成页统计
|
|
||||||
|
|
||||||
3. **历史记录查看**
|
|
||||||
- 点击 History
|
|
||||||
- 查看今日总结
|
|
||||||
- 查看会话列表
|
|
||||||
- ✅ 验证: 数据正确显示
|
|
||||||
|
|
||||||
4. **多次循环**
|
|
||||||
- 连续完成 2-3 次专注
|
|
||||||
- 查看 History 中的累计数据
|
|
||||||
- ✅ 验证: 今日总时长正确累加
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 运行测试
|
|
||||||
|
|
||||||
### Windows 桌面版
|
|
||||||
```bash
|
|
||||||
cd f:\cursor-auto\focusBuddy
|
|
||||||
flutter run -d windows
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web 版
|
|
||||||
```bash
|
|
||||||
flutter run -d edge
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 下一步行动
|
|
||||||
|
|
||||||
### 今天可以完成:
|
|
||||||
1. ✅ 运行并测试所有新功能
|
|
||||||
2. ✅ 验证页面导航流畅性
|
|
||||||
3. ✅ 检查数据持久化是否正常
|
|
||||||
|
|
||||||
### 明天任务:
|
|
||||||
1. ⏰ 添加本地通知(计时完成提醒)
|
|
||||||
2. 🎨 准备应用图标
|
|
||||||
3. 📱 准备真机测试环境
|
|
||||||
|
|
||||||
### 本周末前:
|
|
||||||
1. 🔍 真机测试(Android/iOS)
|
|
||||||
2. 🐛 修复发现的 bug
|
|
||||||
3. 📸 准备应用商店截图
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎊 重要里程碑
|
|
||||||
|
|
||||||
### 已达成:
|
|
||||||
- ✅ 核心差异化功能完整(无惩罚分心追踪)
|
|
||||||
- ✅ 三大核心页面全部完成
|
|
||||||
- ✅ 数据持久化稳定运行
|
|
||||||
- ✅ 用户体验流畅
|
|
||||||
|
|
||||||
### 即将达成:
|
|
||||||
- 🎯 完整 MVP 功能(95% → 100%)
|
|
||||||
- 🎯 准备提交 App Store/Play Store
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 亮点功能展示
|
|
||||||
|
|
||||||
### 1. 智能时长设置
|
|
||||||
```
|
|
||||||
Home → Settings → 选择 15/25/45 分钟
|
|
||||||
→ 自动保存 → 返回首页 → 时长已更新
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 完整历史追踪
|
|
||||||
```
|
|
||||||
今日总结: 47 mins, 2 sessions, 3 distractions
|
|
||||||
↓
|
|
||||||
按日期查看: Today, Yesterday, ...
|
|
||||||
↓
|
|
||||||
每个会话详情: 时间 + 状态 + 分心次数
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 无缝导航
|
|
||||||
```
|
|
||||||
Home ⇄ Focus ⇄ Complete
|
|
||||||
↓ ↓
|
|
||||||
History Settings
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 恭喜!
|
|
||||||
|
|
||||||
**FocusBuddy 的 MVP 已经 95% 完成!**
|
|
||||||
|
|
||||||
现在你有一个功能完整、可以实际使用的专注应用了。
|
|
||||||
|
|
||||||
接下来只需要:
|
|
||||||
1. 添加通知功能(可选但推荐)
|
|
||||||
2. 真机测试
|
|
||||||
3. 准备上架资料
|
|
||||||
|
|
||||||
**立即运行测试,体验完整功能吧!** 🚀
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**运行命令**:
|
|
||||||
```bash
|
|
||||||
flutter run -d windows
|
|
||||||
```
|
|
||||||
|
|
||||||
或查看 [QUICK_START.md](QUICK_START.md) 了解更多测试指南。
|
|
||||||
@@ -1,334 +0,0 @@
|
|||||||
# 📝 开发会话总结 - 2025年11月22日
|
|
||||||
|
|
||||||
## 🎯 今日目标
|
|
||||||
从 95% MVP 完成度 → 99% MVP 完成度
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 完成的任务
|
|
||||||
|
|
||||||
### 1. 🐛 Bug 修复:Complete Screen 导航问题
|
|
||||||
|
|
||||||
**问题**: 点击 "View Full Report" 按钮显示 "History screen coming soon" 提示
|
|
||||||
|
|
||||||
**修复内容**:
|
|
||||||
- 添加 `history_screen.dart` 导入
|
|
||||||
- 将按钮从 SnackBar 改为正确的导航
|
|
||||||
- 使用 `Navigator.pushAndRemoveUntil` 保持导航栈清晰
|
|
||||||
- 按钮文本改为 "View History"
|
|
||||||
|
|
||||||
**文件**: [complete_screen.dart:110-122](lib/screens/complete_screen.dart#L110-L122)
|
|
||||||
|
|
||||||
**文档**: [BUG_FIX_001.md](BUG_FIX_001.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 🔔 本地通知系统完整实现
|
|
||||||
|
|
||||||
**功能亮点**:
|
|
||||||
- ✅ 专注完成后自动发送通知
|
|
||||||
- ✅ 基于分心次数的智能文案
|
|
||||||
- 无分心:"You focused for X minutes without distractions!"
|
|
||||||
- 有分心:"You focused for X minutes. Great effort!"
|
|
||||||
- ✅ 跨平台支持
|
|
||||||
- Android: 支持 Android 13+ 的 POST_NOTIFICATIONS 权限
|
|
||||||
- iOS: 运行时权限请求
|
|
||||||
- Web: 优雅降级(不报错)
|
|
||||||
- ✅ 单例模式设计
|
|
||||||
|
|
||||||
**新增文件**:
|
|
||||||
- [lib/services/notification_service.dart](lib/services/notification_service.dart) - 200行完整实现
|
|
||||||
|
|
||||||
**修改文件**:
|
|
||||||
- [lib/main.dart](lib/main.dart) - 添加通知初始化
|
|
||||||
- [lib/screens/focus_screen.dart](lib/screens/focus_screen.dart) - 计时器完成时发送通知
|
|
||||||
- [android/app/src/main/AndroidManifest.xml](android/app/src/main/AndroidManifest.xml) - 添加3个权限
|
|
||||||
- [pubspec.yaml](pubspec.yaml) - 添加 `flutter_local_notifications: ^17.0.0`
|
|
||||||
|
|
||||||
**文档**:
|
|
||||||
- [NOTIFICATION_IMPLEMENTATION.md](NOTIFICATION_IMPLEMENTATION.md) - 200行技术文档
|
|
||||||
- [NOTIFICATION_COMPLETE.md](NOTIFICATION_COMPLETE.md) - 实现总结
|
|
||||||
|
|
||||||
**测试结果**:
|
|
||||||
```
|
|
||||||
✅ Web: "Notifications not supported on web platform" - 优雅降级成功
|
|
||||||
⏳ Android/iOS: 需要真机测试
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 🎨 Google Fonts (Nunito) 字体集成
|
|
||||||
|
|
||||||
**实现方式**:
|
|
||||||
- 使用 `google_fonts: ^6.1.0` 包
|
|
||||||
- 自动从 Google CDN 下载并缓存字体
|
|
||||||
- 无需手动管理 `assets/fonts/` 目录
|
|
||||||
|
|
||||||
**字体变体**:
|
|
||||||
| 字重 | 用途 | 代码位置 |
|
|
||||||
|------|------|----------|
|
|
||||||
| Light (300) | Helper text | `AppTextStyles.helperText` |
|
|
||||||
| Regular (400) | Body text, quotes | `AppTextStyles.bodyText` |
|
|
||||||
| SemiBold (600) | Headlines, buttons | `AppTextStyles.headline` |
|
|
||||||
| Bold (700) | App title | `AppTextStyles.appTitle` |
|
|
||||||
| ExtraBold (800) | Timer display | `AppTextStyles.timerDisplay` |
|
|
||||||
|
|
||||||
**修改文件**:
|
|
||||||
- [lib/theme/app_text_styles.dart](lib/theme/app_text_styles.dart) - 所有样式使用 `GoogleFonts.nunito()`
|
|
||||||
- [lib/theme/app_theme.dart](lib/theme/app_theme.dart) - 默认字体族设置
|
|
||||||
- [pubspec.yaml](pubspec.yaml) - 添加 `google_fonts: ^6.1.0`
|
|
||||||
|
|
||||||
**遇到的问题**:
|
|
||||||
- ❌ Google Fonts 返回的 TextStyle 不是 `const`
|
|
||||||
- ❌ 代码中有 10 处 `const Text(...style: AppTextStyles.*)` 导致编译错误
|
|
||||||
|
|
||||||
**解决方案**:
|
|
||||||
系统性删除了 10 处 `const` 关键字:
|
|
||||||
- [home_screen.dart](lib/screens/home_screen.dart) - 2处 (第 49, 115 行)
|
|
||||||
- [history_screen.dart](lib/screens/history_screen.dart) - 2处 (第 86, 92 行)
|
|
||||||
- [settings_screen.dart](lib/screens/settings_screen.dart) - 5处 (第 63, 84, 100, 251, 276 行)
|
|
||||||
- [complete_screen.dart](lib/screens/complete_screen.dart) - 1处 (第 46 行)
|
|
||||||
|
|
||||||
**测试结果**:
|
|
||||||
```bash
|
|
||||||
✅ flutter pub get && flutter run -d edge
|
|
||||||
✅ "Starting application from main method"
|
|
||||||
✅ 所有字体正确渲染
|
|
||||||
```
|
|
||||||
|
|
||||||
**文档**:
|
|
||||||
- [GOOGLE_FONTS_SETUP.md](GOOGLE_FONTS_SETUP.md) - 完整实现指南
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 今日统计
|
|
||||||
|
|
||||||
### 代码变更
|
|
||||||
- **新增代码**: ~250 行
|
|
||||||
- notification_service.dart: 200 行
|
|
||||||
- 其他修改: 50 行
|
|
||||||
- **修改文件**: 9 个
|
|
||||||
- **新增依赖**: 2 个 (flutter_local_notifications, google_fonts)
|
|
||||||
- **新增服务**: 1 个 (NotificationService)
|
|
||||||
|
|
||||||
### 文档更新
|
|
||||||
- **新增文档**: 4 个
|
|
||||||
- BUG_FIX_001.md
|
|
||||||
- NOTIFICATION_IMPLEMENTATION.md
|
|
||||||
- NOTIFICATION_COMPLETE.md
|
|
||||||
- GOOGLE_FONTS_SETUP.md
|
|
||||||
- **更新文档**: 1 个
|
|
||||||
- FINAL_SUMMARY.md (95% → 99%)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 MVP 完成度对比
|
|
||||||
|
|
||||||
### 开始 (95%)
|
|
||||||
```
|
|
||||||
███████████████████░ 95%
|
|
||||||
```
|
|
||||||
- ✅ 所有核心功能
|
|
||||||
- ✅ 所有核心页面
|
|
||||||
- ✅ 数据持久化
|
|
||||||
- ❌ 本地通知
|
|
||||||
- ❌ Nunito 字体
|
|
||||||
- ❌ 应用图标
|
|
||||||
|
|
||||||
### 结束 (99%)
|
|
||||||
```
|
|
||||||
███████████████████▓ 99%
|
|
||||||
```
|
|
||||||
- ✅ 所有核心功能
|
|
||||||
- ✅ 所有核心页面
|
|
||||||
- ✅ 数据持久化
|
|
||||||
- ✅ 本地通知系统 ✨
|
|
||||||
- ✅ Google Fonts (Nunito) ✨
|
|
||||||
- ✅ Bug 修复(Complete Screen 导航)✨
|
|
||||||
- ⏳ 应用图标(1%)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 技术亮点
|
|
||||||
|
|
||||||
### 1. 通知服务单例模式
|
|
||||||
```dart
|
|
||||||
class NotificationService {
|
|
||||||
static final NotificationService _instance = NotificationService._internal();
|
|
||||||
factory NotificationService() => _instance;
|
|
||||||
NotificationService._internal();
|
|
||||||
|
|
||||||
// 防止重复初始化
|
|
||||||
bool _initialized = false;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 平台检测与优雅降级
|
|
||||||
```dart
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
|
|
||||||
if (kIsWeb) {
|
|
||||||
print('Notifications not supported on web platform');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Google Fonts 集成
|
|
||||||
```dart
|
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
|
||||||
|
|
||||||
static final appTitle = GoogleFonts.nunito(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: AppColors.textPrimary,
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 智能通知文案
|
|
||||||
```dart
|
|
||||||
final body = distractionCount == 0
|
|
||||||
? 'You focused for $minutes minutes without distractions!'
|
|
||||||
: 'You focused for $minutes minutes. Great effort!';
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 测试状态
|
|
||||||
|
|
||||||
### Web 平台 ✅
|
|
||||||
- ✅ 应用成功启动
|
|
||||||
- ✅ 数据库初始化成功
|
|
||||||
- ✅ 通知服务优雅降级
|
|
||||||
- ✅ 字体正确渲染
|
|
||||||
- ✅ 所有页面导航正常
|
|
||||||
|
|
||||||
### Android/iOS ⏳
|
|
||||||
- ⏳ 需要连接真机测试
|
|
||||||
- ⏳ 验证通知权限请求
|
|
||||||
- ⏳ 验证通知显示和交互
|
|
||||||
- ⏳ 验证字体在移动设备上的渲染
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 遗留任务
|
|
||||||
|
|
||||||
### 立即任务(1%)
|
|
||||||
1. 🎨 设计应用图标
|
|
||||||
- iOS: 1024×1024
|
|
||||||
- Android: 512×512
|
|
||||||
- 生成所有尺寸变体
|
|
||||||
|
|
||||||
### 短期任务
|
|
||||||
2. 📸 准备应用商店截图
|
|
||||||
- 6张截图展示核心功能
|
|
||||||
- iOS 和 Android 两种格式
|
|
||||||
|
|
||||||
3. 🧪 真机测试
|
|
||||||
- Android 设备测试
|
|
||||||
- iOS 设备测试(需要 Mac)
|
|
||||||
- 验证所有功能
|
|
||||||
|
|
||||||
### 中期任务
|
|
||||||
4. 📝 完善应用描述
|
|
||||||
5. 🌐 部署隐私政策页面
|
|
||||||
6. 📋 填写应用商店上架表单
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 经验总结
|
|
||||||
|
|
||||||
### 成功经验
|
|
||||||
1. **系统性问题解决**:
|
|
||||||
- 遇到 const 关键字冲突后,立即搜索所有相关位置
|
|
||||||
- 一次性修复所有问题,避免重复编译错误
|
|
||||||
|
|
||||||
2. **完整文档记录**:
|
|
||||||
- 每个重要功能都创建独立文档
|
|
||||||
- 包含问题背景、解决方案、测试步骤
|
|
||||||
- 便于后续回顾和团队协作
|
|
||||||
|
|
||||||
3. **优雅降级设计**:
|
|
||||||
- 通知系统在 Web 平台上不报错
|
|
||||||
- 使用 `kIsWeb` 进行平台检测
|
|
||||||
- 保证跨平台一致的用户体验
|
|
||||||
|
|
||||||
### 遇到的挑战
|
|
||||||
1. **const 优化与运行时计算的冲突**
|
|
||||||
- Google Fonts 返回的是运行时计算的 TextStyle
|
|
||||||
- 需要删除所有相关的 const 关键字
|
|
||||||
- 解决方案:系统性搜索和修复
|
|
||||||
|
|
||||||
2. **跨平台兼容性**
|
|
||||||
- Web 不支持本地通知
|
|
||||||
- 需要在服务层做平台检测
|
|
||||||
- 避免在 UI 层暴露平台差异
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 里程碑
|
|
||||||
|
|
||||||
- ✅ **Bug 修复**: Complete Screen 导航恢复正常
|
|
||||||
- ✅ **本地通知**: 完整的通知系统实现(200行)
|
|
||||||
- ✅ **字体优化**: Google Fonts 集成成功
|
|
||||||
- ✅ **编译成功**: 所有 const 冲突解决
|
|
||||||
- ✅ **Web 运行**: 应用在浏览器中成功运行
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 项目进度
|
|
||||||
|
|
||||||
### 总体完成度: 99%
|
|
||||||
|
|
||||||
| 模块 | 完成度 | 状态 |
|
|
||||||
|------|--------|------|
|
|
||||||
| 核心功能 | 100% | ✅ |
|
|
||||||
| 页面系统 | 100% | ✅ |
|
|
||||||
| 数据管理 | 100% | ✅ |
|
|
||||||
| 通知系统 | 100% | ✅ |
|
|
||||||
| 字体优化 | 100% | ✅ |
|
|
||||||
| 应用图标 | 0% | ⏳ |
|
|
||||||
| 商店截图 | 0% | ⏳ |
|
|
||||||
| 真机测试 | 0% | ⏳ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 下一步行动
|
|
||||||
|
|
||||||
### 明天计划
|
|
||||||
1. **设计应用图标** (2小时)
|
|
||||||
- 使用 Figma/Canva 设计
|
|
||||||
- 导出所有需要的尺寸
|
|
||||||
- 更新 iOS 和 Android 配置
|
|
||||||
|
|
||||||
2. **准备商店截图** (2小时)
|
|
||||||
- 捕获 6 张关键截图
|
|
||||||
- 添加简短说明文字
|
|
||||||
- 准备多语言版本(中英文)
|
|
||||||
|
|
||||||
3. **真机测试** (3小时)
|
|
||||||
- 在 Android 设备上测试
|
|
||||||
- 验证通知功能
|
|
||||||
- 记录并修复 bug
|
|
||||||
|
|
||||||
### 本周计划
|
|
||||||
- 完成上架前的所有准备工作
|
|
||||||
- 提交到 Google Play 和 App Store
|
|
||||||
- 准备市场推广材料
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎊 总结
|
|
||||||
|
|
||||||
**今天是非常成功的一天!**
|
|
||||||
|
|
||||||
从 95% 到 99% 的进展,不仅完成了关键的功能实现(通知系统),还解决了重要的质量问题(字体优化、bug 修复)。
|
|
||||||
|
|
||||||
应用现在已经具备了完整的 MVP 功能,并且在 Web 平台上成功运行。只需要完成最后的润色工作(图标、截图、真机测试),就可以提交到应用商店了。
|
|
||||||
|
|
||||||
**你已经非常接近目标了!** 🚀
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**会话时间**: 2025年11月22日
|
|
||||||
**开发者**: FocusBuddy 团队
|
|
||||||
**版本**: v1.0-rc1 (Release Candidate 1)
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
# 🚀 Quick Testing Guide - Start Here!
|
|
||||||
|
|
||||||
Your FocusBuddy app is **running successfully** in Edge browser!
|
|
||||||
|
|
||||||
## ✅ Current Status
|
|
||||||
|
|
||||||
```
|
|
||||||
✅ App compiled successfully
|
|
||||||
✅ Running in Edge browser
|
|
||||||
✅ Database initialized (Hive)
|
|
||||||
✅ Hot reload enabled
|
|
||||||
✅ All 5 screens implemented
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Quick 10-Minute Test Flow
|
|
||||||
|
|
||||||
Follow this streamlined test to verify all core features work:
|
|
||||||
|
|
||||||
### **Test 1: Check Home Screen (30 seconds)**
|
|
||||||
1. Open your Edge browser
|
|
||||||
2. You should see "FocusBuddy" title
|
|
||||||
3. Check: "25 minutes" is displayed
|
|
||||||
4. ✅ **Pass if**: UI looks good, buttons visible
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 2: Change Settings (1 minute)**
|
|
||||||
1. Click **"Settings"** button
|
|
||||||
2. Click **"15 minutes"** option
|
|
||||||
3. Observe the green checkmark
|
|
||||||
4. Click **back arrow** to return home
|
|
||||||
5. ✅ **Pass if**: Home now shows "15 minutes"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 3: Quick Focus Session (2 minutes)**
|
|
||||||
|
|
||||||
⚠️ **Important**: To test quickly without waiting 15 minutes, I can modify the timer to use seconds instead. Should I do that?
|
|
||||||
|
|
||||||
For now, let's test the UI:
|
|
||||||
1. Click **"Start Focusing"**
|
|
||||||
2. Observe timer screen
|
|
||||||
3. Check timer is counting down from 15:00
|
|
||||||
4. ✅ **Pass if**: Timer updates every second
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 4: Distraction Button - Critical! (1 minute)**
|
|
||||||
**This is the core feature - must work perfectly:**
|
|
||||||
|
|
||||||
1. While timer is running, click **"I got distracted"**
|
|
||||||
2. **Critical check**: Timer should KEEP RUNNING (not pause!)
|
|
||||||
3. Look for message: "It happens. Let's gently come back."
|
|
||||||
4. Bottom sheet appears with 4 distraction types
|
|
||||||
5. Click **"📱 Scrolling social media"**
|
|
||||||
6. Click **"I got distracted"** again
|
|
||||||
7. Select **"💭 Just zoned out"**
|
|
||||||
8. Observe distraction counter increases
|
|
||||||
9. ✅ **Pass if**: Timer NEVER stops, distractions recorded
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 5: Pause/Resume (30 seconds)**
|
|
||||||
1. Click **"Pause"** button
|
|
||||||
2. Observe timer stops
|
|
||||||
3. Wait 5 seconds
|
|
||||||
4. Click **"Resume"**
|
|
||||||
5. ✅ **Pass if**: Timer continues from paused time
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 6: Stop Early (1 minute)**
|
|
||||||
1. Click **"Stop session"** button
|
|
||||||
2. Read confirmation dialog
|
|
||||||
3. Click **"Yes, stop"**
|
|
||||||
4. You should land on **Complete Screen**
|
|
||||||
5. Check: Shows actual minutes focused (e.g., "2 minutes")
|
|
||||||
6. Check: Shows distraction count (should be 2 from Test 4)
|
|
||||||
7. Check: Shows random encouragement message
|
|
||||||
8. ✅ **Pass if**: All stats are correct
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 7: View History (1 minute)**
|
|
||||||
1. Click **"View History"** button
|
|
||||||
2. Observe **"📅 Today"** summary card
|
|
||||||
3. Check: Total minutes displayed
|
|
||||||
4. Check: Distraction count displayed
|
|
||||||
5. Scroll down to see your session listed
|
|
||||||
6. Session should show: time, duration, "⏸️ Stopped early" badge
|
|
||||||
7. ✅ **Pass if**: Data matches what you just did
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 8: Complete Another Session (2 minutes)**
|
|
||||||
1. Go back to **Home**
|
|
||||||
2. Click **"Start Focusing"** again
|
|
||||||
3. Let it run for 30 seconds (no distractions this time)
|
|
||||||
4. Click **"Stop session"** → **"Yes, stop"**
|
|
||||||
5. Go to **History**
|
|
||||||
6. Check: Now shows **2 sessions**
|
|
||||||
7. Check: Total minutes increased
|
|
||||||
8. ✅ **Pass if**: Both sessions listed
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 9: Data Persistence (1 minute)**
|
|
||||||
1. In the terminal, press **`R`** (capital R) to hot restart
|
|
||||||
2. Or close and reopen browser tab
|
|
||||||
3. Go to **History**
|
|
||||||
4. ✅ **Pass if**: Your sessions are still there!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **Test 10: About & Privacy (30 seconds)**
|
|
||||||
1. Go to **Settings**
|
|
||||||
2. Click **"Privacy Policy"**
|
|
||||||
3. Read dialog, click **"Close"**
|
|
||||||
4. Click **"About FocusBuddy"**
|
|
||||||
5. Read dialog, click **"Close"**
|
|
||||||
6. ✅ **Pass if**: Dialogs display properly
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎊 If All Tests Pass
|
|
||||||
|
|
||||||
**Congratulations!** Your MVP is working perfectly.
|
|
||||||
|
|
||||||
### ✅ What This Means:
|
|
||||||
- All core features work
|
|
||||||
- Data persistence works
|
|
||||||
- UI is functional
|
|
||||||
- No critical bugs
|
|
||||||
|
|
||||||
### 📋 Next Steps:
|
|
||||||
1. See [TEST_REPORT.md](TEST_REPORT.md) for 20 detailed test cases
|
|
||||||
2. Test on Android/iOS devices
|
|
||||||
3. Polish UI if needed
|
|
||||||
4. Add notifications (optional)
|
|
||||||
5. Prepare app store assets
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 If Something Doesn't Work
|
|
||||||
|
|
||||||
### How to Report Issues:
|
|
||||||
|
|
||||||
**For each problem, note:**
|
|
||||||
1. **Which test failed?** (Test 1-10)
|
|
||||||
2. **What happened?** (exact error message or behavior)
|
|
||||||
3. **What did you expect?** (correct behavior)
|
|
||||||
|
|
||||||
### Common Issues & Fixes:
|
|
||||||
|
|
||||||
#### **Issue**: Timer doesn't update every second
|
|
||||||
**Fix**: Check browser console (F12) for JavaScript errors
|
|
||||||
|
|
||||||
#### **Issue**: Distraction button pauses timer
|
|
||||||
**Fix**: This is a critical bug - needs code fix in focus_screen.dart
|
|
||||||
|
|
||||||
#### **Issue**: History is empty after restart
|
|
||||||
**Fix**: Hive database issue - check initialization
|
|
||||||
|
|
||||||
#### **Issue**: Settings don't persist
|
|
||||||
**Fix**: SharedPreferences issue
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔥 Hot Reload Commands
|
|
||||||
|
|
||||||
While testing, you can use these in the terminal:
|
|
||||||
|
|
||||||
- **`r`** - Hot reload (fast, keeps state)
|
|
||||||
- **`R`** - Hot restart (full reset)
|
|
||||||
- **`c`** - Clear console
|
|
||||||
- **`q`** - Quit app
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚡ Speed Up Testing
|
|
||||||
|
|
||||||
### Option 1: Modify Timer to Use Seconds (Temporary)
|
|
||||||
I can change the timer to count seconds instead of minutes so you don't have to wait 15 minutes per test.
|
|
||||||
|
|
||||||
**Would you like me to do this?**
|
|
||||||
|
|
||||||
### Option 2: Test at 1x Speed
|
|
||||||
Just test the UI interactions (pause, distraction, etc.) and trust the timer logic works. You can do one full session overnight.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Quick Checklist
|
|
||||||
|
|
||||||
After testing, fill this out:
|
|
||||||
|
|
||||||
```
|
|
||||||
✅ Home screen displays correctly
|
|
||||||
✅ Settings change duration
|
|
||||||
✅ Settings persist after reload
|
|
||||||
✅ Focus timer counts down
|
|
||||||
✅ Pause/Resume works
|
|
||||||
✅ "I got distracted" doesn't stop timer ⚠️ CRITICAL
|
|
||||||
✅ Distraction types can be selected
|
|
||||||
✅ Stop early saves partial session
|
|
||||||
✅ Complete screen shows correct stats
|
|
||||||
✅ History shows all sessions
|
|
||||||
✅ Today's summary is accurate
|
|
||||||
✅ Data persists after restart
|
|
||||||
✅ Privacy/About dialogs work
|
|
||||||
✅ Navigation works (all screens)
|
|
||||||
✅ UI looks good (colors, fonts, spacing)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 The Most Important Test
|
|
||||||
|
|
||||||
**Test 4** (Distraction Button) is **THE MOST CRITICAL TEST**.
|
|
||||||
|
|
||||||
This is the core differentiator of FocusBuddy:
|
|
||||||
> "I got distracted" must NEVER pause the timer.
|
|
||||||
|
|
||||||
If this doesn't work, everything else doesn't matter. Please test this carefully!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 Pro Tips
|
|
||||||
|
|
||||||
1. **Keep the terminal visible** - you'll see console logs and can hot reload
|
|
||||||
2. **Test distraction button multiple times** - try 10+ distractions in one session
|
|
||||||
3. **Try edge cases** - What if you tap distraction 20 times rapidly?
|
|
||||||
4. **Check responsive design** - Resize browser window to mobile size
|
|
||||||
5. **Read encouragement messages** - Are they emotionally appropriate?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 Browser Access
|
|
||||||
|
|
||||||
If you closed the browser, open a new tab and go to:
|
|
||||||
```
|
|
||||||
http://localhost:<port>/
|
|
||||||
```
|
|
||||||
|
|
||||||
The port number is shown in the terminal output. Look for:
|
|
||||||
```
|
|
||||||
Debug service listening on ws://127.0.0.1:XXXXX/...
|
|
||||||
```
|
|
||||||
|
|
||||||
Or just press `R` in the terminal to restart the app.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ Current State
|
|
||||||
|
|
||||||
```
|
|
||||||
🟢 App Running: Yes
|
|
||||||
🟢 Database: Initialized
|
|
||||||
🟢 Hot Reload: Enabled
|
|
||||||
⚪ Testing: Ready to start
|
|
||||||
```
|
|
||||||
|
|
||||||
**You can start testing now!**
|
|
||||||
|
|
||||||
Follow Tests 1-10 above, and report back any issues. If everything works, we'll move on to preparing for launch! 🚀
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Happy Testing!** 🎉
|
|
||||||
595
TEST_REPORT.md
595
TEST_REPORT.md
@@ -1,595 +0,0 @@
|
|||||||
# 🧪 FocusBuddy - Test Report
|
|
||||||
|
|
||||||
**Date**: 2025-11-22
|
|
||||||
**Build**: MVP v1.0.0
|
|
||||||
**Platform**: Web (Edge Browser)
|
|
||||||
**Status**: ✅ Running Successfully
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 Test Environment
|
|
||||||
|
|
||||||
### System Information
|
|
||||||
- **Platform**: Windows (Web fallback due to Developer Mode requirement)
|
|
||||||
- **Browser**: Microsoft Edge
|
|
||||||
- **Flutter Version**: 3.10.0-290.4.beta
|
|
||||||
- **SDK**: Dart ^3.10.0-290.4.beta
|
|
||||||
|
|
||||||
### Build Status
|
|
||||||
- ✅ **Web Build**: Success
|
|
||||||
- ❌ **Windows Desktop**: Blocked (requires Developer Mode for symlink support)
|
|
||||||
- ⏳ **Android**: Not tested yet (requires device/emulator)
|
|
||||||
- ⏳ **iOS**: Not tested yet (requires macOS + device/simulator)
|
|
||||||
|
|
||||||
### Database Initialization
|
|
||||||
```
|
|
||||||
Got object store box in database focus_sessions.
|
|
||||||
```
|
|
||||||
✅ **Hive database initialized successfully**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Test Plan
|
|
||||||
|
|
||||||
### Test Coverage Matrix
|
|
||||||
|
|
||||||
| Feature | Status | Priority | Notes |
|
|
||||||
|---------|--------|----------|-------|
|
|
||||||
| Home Screen | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| Settings Screen | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| Focus Timer | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| Distraction Tracking | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| Complete Screen | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| History Screen | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| Data Persistence | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
| Navigation Flow | 🟡 Ready | P0 | Manual testing required |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 Detailed Test Cases
|
|
||||||
|
|
||||||
### Test 1: Home Screen - Initial Load
|
|
||||||
**Objective**: Verify default state and UI elements
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Open app in browser
|
|
||||||
2. Observe home screen
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ "FocusBuddy" title displayed
|
|
||||||
- ✅ "25 minutes" duration displayed (default)
|
|
||||||
- ✅ "Start Focusing" button visible
|
|
||||||
- ✅ Helper text: "Tap 'I got distracted' anytime — no guilt."
|
|
||||||
- ✅ "History" and "Settings" buttons at bottom
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 2: Settings Screen - Change Duration
|
|
||||||
**Objective**: Verify settings persistence and UI updates
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. From Home screen, tap "Settings"
|
|
||||||
2. Select "15 minutes" option
|
|
||||||
3. Tap back button to return to Home
|
|
||||||
4. Observe duration display
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Settings screen opens
|
|
||||||
- ✅ Duration options: 15, 25 (Default), 45 minutes
|
|
||||||
- ✅ Radio button UI indicates selection
|
|
||||||
- ✅ Home screen updates to "15 minutes"
|
|
||||||
- ✅ Duration persists in SharedPreferences
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 3: Settings Screen - Privacy Policy
|
|
||||||
**Objective**: Verify dialogs display correctly
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Go to Settings
|
|
||||||
2. Tap "Privacy Policy"
|
|
||||||
3. Read content
|
|
||||||
4. Close dialog
|
|
||||||
5. Tap "About FocusBuddy"
|
|
||||||
6. Close dialog
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Privacy dialog shows offline commitment
|
|
||||||
- ✅ About dialog shows app description
|
|
||||||
- ✅ Close button works
|
|
||||||
- ✅ Returns to Settings screen
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 4: Focus Session - Complete Flow
|
|
||||||
**Objective**: Verify full 15-minute session (accelerated testing recommended)
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Set duration to 15 minutes
|
|
||||||
2. Tap "Start Focusing"
|
|
||||||
3. Observe timer countdown
|
|
||||||
4. Wait until timer reaches 00:00
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Focus screen displays timer
|
|
||||||
- ✅ Timer counts down from 15:00
|
|
||||||
- ✅ "I got distracted" button visible
|
|
||||||
- ✅ "Pause" button visible
|
|
||||||
- ✅ Timer reaches 00:00
|
|
||||||
- ✅ Automatically navigates to Complete screen
|
|
||||||
- ✅ Complete screen shows: "15 minutes", today's total, encouragement
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
**⚠️ Testing Note**: For rapid testing, consider temporarily modifying timer to use seconds instead of minutes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 5: Focus Session - Pause/Resume
|
|
||||||
**Objective**: Verify pause functionality
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a focus session
|
|
||||||
2. After 30 seconds, tap "Pause"
|
|
||||||
3. Wait 10 seconds
|
|
||||||
4. Tap "Resume"
|
|
||||||
5. Verify timer continues
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Timer pauses immediately
|
|
||||||
- ✅ Button changes to "Resume"
|
|
||||||
- ✅ Timer resumes from paused time
|
|
||||||
- ✅ No time is lost
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 6: Focus Session - Distraction Tracking
|
|
||||||
**Objective**: Verify "no punishment" distraction mechanism
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a focus session
|
|
||||||
2. Tap "I got distracted" (DO NOT pause timer)
|
|
||||||
3. Observe SnackBar message
|
|
||||||
4. Select "📱 Scrolling social media" from bottom sheet
|
|
||||||
5. Observe timer continues
|
|
||||||
6. Tap "I got distracted" again
|
|
||||||
7. Select "🌪️ Felt overwhelmed"
|
|
||||||
8. Tap "I got distracted" a third time
|
|
||||||
9. Select "💭 Just zoned out"
|
|
||||||
10. Let session complete
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ SnackBar shows: "It happens. Let's gently come back."
|
|
||||||
- ✅ Bottom sheet appears with 4 distraction types
|
|
||||||
- ✅ Timer NEVER stops or pauses
|
|
||||||
- ✅ Distraction counter updates
|
|
||||||
- ✅ Session completes normally
|
|
||||||
- ✅ Complete screen shows 3 distractions
|
|
||||||
- ✅ All distraction types are recorded
|
|
||||||
|
|
||||||
**Critical Verification**: Timer must continue running throughout all distraction clicks.
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 7: Focus Session - Stop Early
|
|
||||||
**Objective**: Verify early stop with confirmation
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a session
|
|
||||||
2. After 2 minutes, tap "Stop session" button
|
|
||||||
3. Observe confirmation dialog
|
|
||||||
4. Tap "Yes, stop"
|
|
||||||
5. Observe navigation to Complete screen
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Confirmation dialog appears
|
|
||||||
- ✅ Dialog message: "Are you sure you want to stop this focus session early?"
|
|
||||||
- ✅ Two buttons: "Yes, stop" and "No, continue"
|
|
||||||
- ✅ "Yes, stop" saves partial session
|
|
||||||
- ✅ Complete screen shows actual minutes (e.g., "2 minutes")
|
|
||||||
- ✅ Session marked as incomplete
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 8: Focus Session - Cancel Early Stop
|
|
||||||
**Objective**: Verify "No, continue" returns to timer
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a session
|
|
||||||
2. Tap "Stop session"
|
|
||||||
3. In confirmation dialog, tap "No, continue"
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Dialog closes
|
|
||||||
- ✅ Timer continues from where it was
|
|
||||||
- ✅ No session is saved
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 9: Complete Screen - Statistics Display
|
|
||||||
**Objective**: Verify post-session summary accuracy
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Complete a 15-minute session with 3 distractions
|
|
||||||
2. Observe Complete screen
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ "You focused for" section shows "15 minutes"
|
|
||||||
- ✅ "Today's Total" shows cumulative minutes
|
|
||||||
- ✅ Distraction count displayed
|
|
||||||
- ✅ Random encouragement message shown
|
|
||||||
- ✅ "Start Another" button visible
|
|
||||||
- ✅ "View History" button visible
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 10: Complete Screen - Start Another Session
|
|
||||||
**Objective**: Verify quick restart flow
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. From Complete screen, tap "Start Another"
|
|
||||||
2. Observe navigation
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Navigates directly to Focus screen (not Home)
|
|
||||||
- ✅ Timer starts with same duration
|
|
||||||
- ✅ Previous session is saved
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 11: History Screen - Empty State
|
|
||||||
**Objective**: Verify first-time user experience
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Clear all data (if needed: delete Hive box)
|
|
||||||
2. Open History screen
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Empty state message: "No focus sessions yet"
|
|
||||||
- ✅ Helper text: "Start your first session to see your progress here!"
|
|
||||||
- ✅ "Start Focusing" button visible
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 12: History Screen - Today's Summary
|
|
||||||
**Objective**: Verify today's statistics accuracy
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Complete 2 sessions:
|
|
||||||
- Session 1: 15 mins, 3 distractions, completed
|
|
||||||
- Session 2: 25 mins, 1 distraction, stopped early at 20 mins
|
|
||||||
2. Open History screen
|
|
||||||
3. Observe "📅 Today" summary card
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Total: 35 mins (15 + 20)
|
|
||||||
- ✅ Distractions: 4 times (3 + 1)
|
|
||||||
- ✅ Sessions badge: "2 sessions"
|
|
||||||
- ✅ Summary card at top of screen
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 13: History Screen - Session List
|
|
||||||
**Objective**: Verify session detail display
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. After Test 12, scroll down in History screen
|
|
||||||
2. Observe session list under "Today"
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Two session cards displayed
|
|
||||||
- ✅ Each shows: time (HH:mm), duration, distraction count
|
|
||||||
- ✅ Session 1: "✅ Completed" badge (green)
|
|
||||||
- ✅ Session 2: "⏸️ Stopped early" badge (gray)
|
|
||||||
- ✅ Newest session at top
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 14: Data Persistence - App Reload
|
|
||||||
**Objective**: Verify Hive database persists across sessions
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Complete 2 focus sessions
|
|
||||||
2. Change settings to 45 minutes
|
|
||||||
3. Close browser tab (or hot restart: press 'R' in terminal)
|
|
||||||
4. Reopen app
|
|
||||||
5. Check History screen
|
|
||||||
6. Check Home screen duration
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ History shows all previous sessions
|
|
||||||
- ✅ Today's total is correct
|
|
||||||
- ✅ Settings duration is 45 minutes
|
|
||||||
- ✅ No data loss
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 15: Navigation Flow - Complete Journey
|
|
||||||
**Objective**: Verify all navigation paths work
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Home → Settings → Back to Home
|
|
||||||
2. Home → History → Back to Home
|
|
||||||
3. Home → Focus → Complete → View History → Back to Home
|
|
||||||
4. Home → Focus → Complete → Start Another → Focus again
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ All back buttons work
|
|
||||||
- ✅ All forward navigations work
|
|
||||||
- ✅ No navigation errors
|
|
||||||
- ✅ State preserved correctly
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 16: UI/UX - Color & Typography
|
|
||||||
**Objective**: Verify design system implementation
|
|
||||||
|
|
||||||
**Visual Checks**:
|
|
||||||
- ✅ Morandi color palette (calm greens, warm off-white)
|
|
||||||
- ✅ Primary color: #A7C4BC visible in buttons
|
|
||||||
- ✅ Background: #F8F6F2 (warm off-white)
|
|
||||||
- ✅ Nunito font used (or fallback system font if not installed)
|
|
||||||
- ✅ Consistent padding/spacing (24px)
|
|
||||||
- ✅ Rounded corners (16px cards, 12px buttons)
|
|
||||||
- ✅ Button height: 56px
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 17: Responsive Design
|
|
||||||
**Objective**: Verify app works at different viewport sizes
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Browser: normal desktop size (1920x1080)
|
|
||||||
2. Browser: narrow desktop (1024x768)
|
|
||||||
3. Browser: tablet simulation (768x1024)
|
|
||||||
4. Browser: mobile simulation (375x667)
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ UI adapts to all sizes
|
|
||||||
- ✅ No horizontal scrolling
|
|
||||||
- ✅ Buttons remain accessible
|
|
||||||
- ✅ Text remains readable
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 18: Performance - Timer Accuracy
|
|
||||||
**Objective**: Verify timer countdown is accurate
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a 1-minute focus session (temporary modification)
|
|
||||||
2. Use stopwatch on phone
|
|
||||||
3. Compare when timer reaches 00:00
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Timer completes in exactly 60 seconds (±1 second tolerance)
|
|
||||||
- ✅ UI updates every second
|
|
||||||
- ✅ No freezing or stuttering
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 19: Edge Cases - Multiple Distractions
|
|
||||||
**Objective**: Verify app handles high distraction counts
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a session
|
|
||||||
2. Tap "I got distracted" 20 times rapidly
|
|
||||||
3. Select different distraction types
|
|
||||||
4. Complete session
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ All 20 distractions recorded
|
|
||||||
- ✅ No UI freeze
|
|
||||||
- ✅ Complete screen shows correct count
|
|
||||||
- ✅ History shows correct count
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Test 20: Edge Cases - Zero Duration Sessions
|
|
||||||
**Objective**: Verify app handles edge case
|
|
||||||
|
|
||||||
**Steps**:
|
|
||||||
1. Start a session
|
|
||||||
2. Immediately tap "Stop session"
|
|
||||||
3. Confirm stop
|
|
||||||
|
|
||||||
**Expected Results**:
|
|
||||||
- ✅ Session saves with 0 minutes
|
|
||||||
- ✅ Complete screen shows "0 minutes" (or "Less than a minute")
|
|
||||||
- ✅ History records session
|
|
||||||
- ✅ No crash
|
|
||||||
|
|
||||||
**Actual Results**: [TO BE TESTED]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 Known Issues
|
|
||||||
|
|
||||||
### Critical Issues (Blocking Launch)
|
|
||||||
*None identified yet - requires testing*
|
|
||||||
|
|
||||||
### High Priority Issues (Should fix before launch)
|
|
||||||
*None identified yet - requires testing*
|
|
||||||
|
|
||||||
### Medium Priority Issues (Nice to fix)
|
|
||||||
1. **Nunito Font Not Loaded**
|
|
||||||
- **Impact**: Using system fallback fonts
|
|
||||||
- **Fix**: Download Nunito fonts or use google_fonts package
|
|
||||||
- **Workaround**: Acceptable for MVP, fonts load fine in production
|
|
||||||
|
|
||||||
### Low Priority Issues (Post-launch)
|
|
||||||
1. **Windows Requires Developer Mode**
|
|
||||||
- **Impact**: Cannot test Windows desktop version
|
|
||||||
- **Fix**: Enable Developer Mode in Windows settings
|
|
||||||
- **Workaround**: Test using Web and mobile platforms
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 Visual Testing Checklist
|
|
||||||
|
|
||||||
### Home Screen
|
|
||||||
- [ ] App title "FocusBuddy" is prominent
|
|
||||||
- [ ] Duration display is in white rounded card
|
|
||||||
- [ ] "Start Focusing" button is primary green color
|
|
||||||
- [ ] Helper text is subtle gray color
|
|
||||||
- [ ] Bottom navigation buttons are evenly spaced
|
|
||||||
- [ ] Overall spacing feels balanced
|
|
||||||
|
|
||||||
### Settings Screen
|
|
||||||
- [ ] Duration options have clear radio buttons
|
|
||||||
- [ ] Selected option has green border
|
|
||||||
- [ ] "Default" badge shows on 25 minutes
|
|
||||||
- [ ] Privacy/About list items have arrow icons
|
|
||||||
- [ ] Version number displays at bottom
|
|
||||||
- [ ] Cards have subtle shadows
|
|
||||||
|
|
||||||
### Focus Screen
|
|
||||||
- [ ] Timer display is very large (64px)
|
|
||||||
- [ ] "I got distracted" button is not red/alarming
|
|
||||||
- [ ] Pause/Resume button is clear
|
|
||||||
- [ ] Stop button is less prominent
|
|
||||||
- [ ] Distraction counter is visible but not intrusive
|
|
||||||
- [ ] Overall feeling is calm, not stressful
|
|
||||||
|
|
||||||
### Complete Screen
|
|
||||||
- [ ] Congratulatory feeling (success green)
|
|
||||||
- [ ] Statistics are easy to read
|
|
||||||
- [ ] Encouragement quote is emphasized
|
|
||||||
- [ ] Call-to-action buttons are clear
|
|
||||||
- [ ] Today's summary is informative
|
|
||||||
|
|
||||||
### History Screen
|
|
||||||
- [ ] Today's summary card stands out
|
|
||||||
- [ ] Session cards are scannable
|
|
||||||
- [ ] Date grouping is clear
|
|
||||||
- [ ] Empty state is friendly
|
|
||||||
- [ ] Stats use appropriate emojis
|
|
||||||
|
|
||||||
### Distraction Bottom Sheet
|
|
||||||
- [ ] All 4 types are listed
|
|
||||||
- [ ] Emojis make types recognizable
|
|
||||||
- [ ] Text is clear
|
|
||||||
- [ ] Easy to dismiss
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Test Metrics
|
|
||||||
|
|
||||||
### Code Coverage
|
|
||||||
- **Unit Tests**: Not implemented (MVP)
|
|
||||||
- **Integration Tests**: Not implemented (MVP)
|
|
||||||
- **Manual Tests**: 20 test cases defined
|
|
||||||
|
|
||||||
### Quality Gates
|
|
||||||
- [ ] All P0 tests passing
|
|
||||||
- [ ] No critical bugs
|
|
||||||
- [ ] Data persistence working
|
|
||||||
- [ ] UI matches design spec
|
|
||||||
- [ ] Navigation flow complete
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Test Sign-off
|
|
||||||
|
|
||||||
### Testing Completed By
|
|
||||||
**Name**: [To be filled]
|
|
||||||
**Date**: [To be filled]
|
|
||||||
**Environment**: Web (Edge), [other platforms]
|
|
||||||
|
|
||||||
### Issues Found
|
|
||||||
- **Critical**: 0
|
|
||||||
- **High**: 0
|
|
||||||
- **Medium**: 0
|
|
||||||
- **Low**: 0
|
|
||||||
|
|
||||||
### Recommendation
|
|
||||||
- [ ] **Ready for Launch** - All tests passing
|
|
||||||
- [ ] **Needs Fixes** - Critical/high issues found
|
|
||||||
- [ ] **Needs Retesting** - Fixes implemented, retest required
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Hot Reload Testing
|
|
||||||
|
|
||||||
The app supports Flutter hot reload for rapid testing:
|
|
||||||
|
|
||||||
### Quick Commands (in terminal)
|
|
||||||
- `r` - Hot reload (preserves app state)
|
|
||||||
- `R` - Hot restart (resets app state)
|
|
||||||
- `h` - List all commands
|
|
||||||
- `c` - Clear console
|
|
||||||
- `q` - Quit app
|
|
||||||
|
|
||||||
### Hot Reload Test
|
|
||||||
1. Make a small UI change (e.g., change button text)
|
|
||||||
2. Save file
|
|
||||||
3. Press `r` in terminal
|
|
||||||
4. Verify change appears in browser (2-3 seconds)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 Next Platform Testing
|
|
||||||
|
|
||||||
### Android Testing (Planned)
|
|
||||||
1. Connect Android device or start emulator
|
|
||||||
2. Run: `flutter devices`
|
|
||||||
3. Run: `flutter run -d <android-device-id>`
|
|
||||||
4. Repeat all 20 test cases
|
|
||||||
5. Additional checks: back button, notifications, permissions
|
|
||||||
|
|
||||||
### iOS Testing (Planned)
|
|
||||||
1. Open project in Xcode (macOS required)
|
|
||||||
2. Configure signing
|
|
||||||
3. Run: `flutter run -d <ios-device-id>`
|
|
||||||
4. Repeat all 20 test cases
|
|
||||||
5. Additional checks: gestures, notifications, privacy prompts
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Test Summary
|
|
||||||
|
|
||||||
**Current Status**: ✅ App running successfully in browser
|
|
||||||
**Test Execution**: ⏳ Manual testing required
|
|
||||||
**Recommendation**: Proceed with Test Cases 1-20 in sequence
|
|
||||||
|
|
||||||
**Estimated Testing Time**: 2-3 hours for complete test suite
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated**: 2025-11-22
|
|
||||||
**Document Version**: 1.0
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|||||||
43
ios/Podfile
Normal file
43
ios/Podfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '13.0'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
35
ios/Podfile.lock
Normal file
35
ios/Podfile.lock
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
PODS:
|
||||||
|
- Flutter (1.0.0)
|
||||||
|
- flutter_local_notifications (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- objective_c (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- shared_preferences_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
|
- objective_c (from `.symlinks/plugins/objective_c/ios`)
|
||||||
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
Flutter:
|
||||||
|
:path: Flutter
|
||||||
|
flutter_local_notifications:
|
||||||
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
|
objective_c:
|
||||||
|
:path: ".symlinks/plugins/objective_c/ios"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
|
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||||
|
objective_c: 77e887b5ba1827970907e10e832eec1683f3431d
|
||||||
|
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||||
|
|
||||||
|
COCOAPODS: 1.16.2
|
||||||
@@ -10,10 +10,12 @@
|
|||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
4F21DDA732CE5EA3FD4BD227 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8ECA8E3F2419A8BC809DE90 /* Pods_RunnerTests.framework */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
FFCEB2D462F39BF41BAFCABE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E276AD767481FD11C70B026 /* Pods_Runner.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -42,9 +44,14 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
2881EAAC21813692B4AC2F49 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
3E276AD767481FD11C70B026 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
415B4DBE2E2506ADAAAD1865 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
5D1A9F6676FCA54E97B916A0 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
676FCE9D693E27667F83610A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
@@ -55,19 +62,40 @@
|
|||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
D381B0F26A7F11974654A2CE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F474F144AE4C782893810FC3 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F8ECA8E3F2419A8BC809DE90 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
510C2968BD4F957E687C54CE /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
4F21DDA732CE5EA3FD4BD227 /* Pods_RunnerTests.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
FFCEB2D462F39BF41BAFCABE /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
01439B170118F84CA54C1FDC /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3E276AD767481FD11C70B026 /* Pods_Runner.framework */,
|
||||||
|
F8ECA8E3F2419A8BC809DE90 /* Pods_RunnerTests.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -94,6 +122,8 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
|
DFDA229EBBEF45AD064A13DF /* Pods */,
|
||||||
|
01439B170118F84CA54C1FDC /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -121,6 +151,20 @@
|
|||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DFDA229EBBEF45AD064A13DF /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D381B0F26A7F11974654A2CE /* Pods-Runner.debug.xcconfig */,
|
||||||
|
2881EAAC21813692B4AC2F49 /* Pods-Runner.release.xcconfig */,
|
||||||
|
415B4DBE2E2506ADAAAD1865 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
5D1A9F6676FCA54E97B916A0 /* Pods-RunnerTests.debug.xcconfig */,
|
||||||
|
F474F144AE4C782893810FC3 /* Pods-RunnerTests.release.xcconfig */,
|
||||||
|
676FCE9D693E27667F83610A /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@@ -128,8 +172,10 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
97BC673F17C73E284DC59D4B /* [CP] Check Pods Manifest.lock */,
|
||||||
331C807D294A63A400263BE5 /* Sources */,
|
331C807D294A63A400263BE5 /* Sources */,
|
||||||
331C807F294A63A400263BE5 /* Resources */,
|
331C807F294A63A400263BE5 /* Resources */,
|
||||||
|
510C2968BD4F957E687C54CE /* Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -145,12 +191,14 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
4ED45F3DF92002CC4B5E0221 /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
C5783D838864AB8D6AFB6900 /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -238,6 +286,28 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
};
|
};
|
||||||
|
4ED45F3DF92002CC4B5E0221 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@@ -253,6 +323,45 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
|
97BC673F17C73E284DC59D4B /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
C5783D838864AB8D6AFB6900 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -378,6 +487,7 @@
|
|||||||
};
|
};
|
||||||
331C8088294A63A400263BE5 /* Debug */ = {
|
331C8088294A63A400263BE5 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 5D1A9F6676FCA54E97B916A0 /* Pods-RunnerTests.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@@ -395,6 +505,7 @@
|
|||||||
};
|
};
|
||||||
331C8089294A63A400263BE5 /* Release */ = {
|
331C8089294A63A400263BE5 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = F474F144AE4C782893810FC3 /* Pods-RunnerTests.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@@ -410,6 +521,7 @@
|
|||||||
};
|
};
|
||||||
331C808A294A63A400263BE5 /* Profile */ = {
|
331C808A294A63A400263BE5 /* Profile */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 676FCE9D693E27667F83610A /* Pods-RunnerTests.profile.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
|||||||
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
3
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
@@ -4,4 +4,7 @@
|
|||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|||||||
@@ -146,13 +146,20 @@ class _FocusScreenState extends State<FocusScreen> {
|
|||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
backgroundColor: AppColors.white,
|
backgroundColor: AppColors.white,
|
||||||
|
isScrollControlled: true,
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||||
),
|
),
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(24.0),
|
padding: EdgeInsets.only(
|
||||||
|
left: 24.0,
|
||||||
|
right: 24.0,
|
||||||
|
top: 24.0,
|
||||||
|
bottom: 24.0 + MediaQuery.of(context).viewInsets.bottom,
|
||||||
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -221,6 +228,7 @@ class _FocusScreenState extends State<FocusScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -260,12 +268,16 @@ class _FocusScreenState extends State<FocusScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColors.background,
|
backgroundColor: AppColors.background,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Padding(
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(24.0),
|
padding: const EdgeInsets.all(24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
const Spacer(),
|
SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height * 0.2,
|
||||||
|
),
|
||||||
|
|
||||||
// Timer Display
|
// Timer Display
|
||||||
Text(
|
Text(
|
||||||
@@ -336,10 +348,18 @@ class _FocusScreenState extends State<FocusScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const Spacer(),
|
SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height * 0.2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// Stop Button (text button at bottom)
|
// Stop Button (text button at bottom)
|
||||||
TextButton(
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 24.0),
|
||||||
|
child: TextButton(
|
||||||
onPressed: _stopEarly,
|
onPressed: _stopEarly,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Stop session',
|
'Stop session',
|
||||||
@@ -349,8 +369,8 @@ class _FocusScreenState extends State<FocusScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||||
|
|||||||
42
macos/Podfile
Normal file
42
macos/Podfile
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
platform :osx, '10.15'
|
||||||
|
|
||||||
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
|
project 'Runner', {
|
||||||
|
'Debug' => :debug,
|
||||||
|
'Profile' => :release,
|
||||||
|
'Release' => :release,
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutter_root
|
||||||
|
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||||
|
unless File.exist?(generated_xcode_build_settings_path)
|
||||||
|
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||||
|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||||
|
return matches[1].strip if matches
|
||||||
|
end
|
||||||
|
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||||
|
end
|
||||||
|
|
||||||
|
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||||
|
|
||||||
|
flutter_macos_podfile_setup
|
||||||
|
|
||||||
|
target 'Runner' do
|
||||||
|
use_frameworks!
|
||||||
|
|
||||||
|
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_macos_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
35
macos/Podfile.lock
Normal file
35
macos/Podfile.lock
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
PODS:
|
||||||
|
- flutter_local_notifications (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- FlutterMacOS (1.0.0)
|
||||||
|
- objective_c (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- shared_preferences_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
|
||||||
|
DEPENDENCIES:
|
||||||
|
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
||||||
|
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||||
|
- objective_c (from `Flutter/ephemeral/.symlinks/plugins/objective_c/macos`)
|
||||||
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
|
||||||
|
EXTERNAL SOURCES:
|
||||||
|
flutter_local_notifications:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
|
||||||
|
FlutterMacOS:
|
||||||
|
:path: Flutter/ephemeral
|
||||||
|
objective_c:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/objective_c/macos
|
||||||
|
shared_preferences_foundation:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||||
|
|
||||||
|
SPEC CHECKSUMS:
|
||||||
|
flutter_local_notifications: 4b427ffabf278fc6ea9484c97505e231166927a5
|
||||||
|
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||||
|
objective_c: e5f8194456e8fc943e034d1af00510a1bc29c067
|
||||||
|
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||||
|
|
||||||
|
PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009
|
||||||
|
|
||||||
|
COCOAPODS: 1.16.2
|
||||||
@@ -21,12 +21,14 @@
|
|||||||
/* End PBXAggregateTarget section */
|
/* End PBXAggregateTarget section */
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
12DDB076302A62DE195F7F77 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E332783FE90BB2B8120EEE3 /* Pods_RunnerTests.framework */; };
|
||||||
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
|
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
|
||||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||||
|
5188293C12144F78779A8C31 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF0133E3EB04D8BDDA6B3049 /* Pods_Runner.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -60,11 +62,12 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
207D36439035889740B9108F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||||
33CC10ED2044A3C60003C045 /* focus_buddy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "focus_buddy.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
33CC10ED2044A3C60003C045 /* focus_buddy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = focus_buddy.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||||
@@ -76,8 +79,15 @@
|
|||||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||||
|
5D2FB4A0DFBEFD6DB1B945E7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
5E332783FE90BB2B8120EEE3 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
|
B1DDCC2184A080B42C34C6A0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
D91D5683968BC068A4DB7036 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
DA80A10E8BEAB07C4D0F6C0A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
E5BD3EA4A8FE454CBEAC804E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
FF0133E3EB04D8BDDA6B3049 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -85,6 +95,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
12DDB076302A62DE195F7F77 /* Pods_RunnerTests.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -92,12 +103,27 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
5188293C12144F78779A8C31 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
08D24E5EE93115F48655C185 /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DA80A10E8BEAB07C4D0F6C0A /* Pods-Runner.debug.xcconfig */,
|
||||||
|
207D36439035889740B9108F /* Pods-Runner.release.xcconfig */,
|
||||||
|
5D2FB4A0DFBEFD6DB1B945E7 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
D91D5683968BC068A4DB7036 /* Pods-RunnerTests.debug.xcconfig */,
|
||||||
|
B1DDCC2184A080B42C34C6A0 /* Pods-RunnerTests.release.xcconfig */,
|
||||||
|
E5BD3EA4A8FE454CBEAC804E /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Pods;
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
331C80D6294CF71000263BE5 /* RunnerTests */ = {
|
331C80D6294CF71000263BE5 /* RunnerTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -125,6 +151,7 @@
|
|||||||
331C80D6294CF71000263BE5 /* RunnerTests */,
|
331C80D6294CF71000263BE5 /* RunnerTests */,
|
||||||
33CC10EE2044A3C60003C045 /* Products */,
|
33CC10EE2044A3C60003C045 /* Products */,
|
||||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
||||||
|
08D24E5EE93115F48655C185 /* Pods */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -175,6 +202,8 @@
|
|||||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
FF0133E3EB04D8BDDA6B3049 /* Pods_Runner.framework */,
|
||||||
|
5E332783FE90BB2B8120EEE3 /* Pods_RunnerTests.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -186,6 +215,7 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
ABA4769891F909893C38B75F /* [CP] Check Pods Manifest.lock */,
|
||||||
331C80D1294CF70F00263BE5 /* Sources */,
|
331C80D1294CF70F00263BE5 /* Sources */,
|
||||||
331C80D2294CF70F00263BE5 /* Frameworks */,
|
331C80D2294CF70F00263BE5 /* Frameworks */,
|
||||||
331C80D3294CF70F00263BE5 /* Resources */,
|
331C80D3294CF70F00263BE5 /* Resources */,
|
||||||
@@ -204,11 +234,13 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
32C93CD8F3D0D706DC5ADA5B /* [CP] Check Pods Manifest.lock */,
|
||||||
33CC10E92044A3C60003C045 /* Sources */,
|
33CC10E92044A3C60003C045 /* Sources */,
|
||||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||||
33CC10EB2044A3C60003C045 /* Resources */,
|
33CC10EB2044A3C60003C045 /* Resources */,
|
||||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||||
|
188537C08472C94556A10B01 /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -291,6 +323,45 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
188537C08472C94556A10B01 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
32C93CD8F3D0D706DC5ADA5B /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@@ -329,6 +400,28 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||||
};
|
};
|
||||||
|
ABA4769891F909893C38B75F /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -380,6 +473,7 @@
|
|||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
331C80DB294CF71000263BE5 /* Debug */ = {
|
331C80DB294CF71000263BE5 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = D91D5683968BC068A4DB7036 /* Pods-RunnerTests.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@@ -394,6 +488,7 @@
|
|||||||
};
|
};
|
||||||
331C80DC294CF71000263BE5 /* Release */ = {
|
331C80DC294CF71000263BE5 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = B1DDCC2184A080B42C34C6A0 /* Pods-RunnerTests.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@@ -408,6 +503,7 @@
|
|||||||
};
|
};
|
||||||
331C80DD294CF71000263BE5 /* Profile */ = {
|
331C80DD294CF71000263BE5 /* Profile */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = E5BD3EA4A8FE454CBEAC804E /* Pods-RunnerTests.profile.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
|||||||
@@ -4,4 +4,7 @@
|
|||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|||||||
198
pubspec.lock
198
pubspec.lock
@@ -6,7 +6,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "67.0.0"
|
version: "67.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
@@ -14,7 +14,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.4.1"
|
version: "6.4.1"
|
||||||
args:
|
args:
|
||||||
@@ -22,7 +22,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: args
|
name: args
|
||||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.7.0"
|
version: "2.7.0"
|
||||||
async:
|
async:
|
||||||
@@ -30,7 +30,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.13.0"
|
version: "2.13.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
@@ -38,7 +38,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
build:
|
build:
|
||||||
@@ -46,7 +46,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: build
|
name: build
|
||||||
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
build_config:
|
build_config:
|
||||||
@@ -54,7 +54,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: build_config
|
name: build_config
|
||||||
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
|
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.2"
|
||||||
build_daemon:
|
build_daemon:
|
||||||
@@ -62,7 +62,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: build_daemon
|
name: build_daemon
|
||||||
sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957
|
sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.1"
|
version: "4.1.1"
|
||||||
build_resolvers:
|
build_resolvers:
|
||||||
@@ -70,7 +70,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: build_resolvers
|
name: build_resolvers
|
||||||
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.4.2"
|
||||||
build_runner:
|
build_runner:
|
||||||
@@ -78,7 +78,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
|
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.13"
|
version: "2.4.13"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
@@ -86,7 +86,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: build_runner_core
|
name: build_runner_core
|
||||||
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
|
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.3.2"
|
version: "7.3.2"
|
||||||
built_collection:
|
built_collection:
|
||||||
@@ -94,7 +94,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: built_collection
|
name: built_collection
|
||||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.1"
|
version: "5.1.1"
|
||||||
built_value:
|
built_value:
|
||||||
@@ -102,7 +102,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: built_value
|
name: built_value
|
||||||
sha256: "426cf75afdb23aa74bd4e471704de3f9393f3c7b04c1e2d9c6f1073ae0b8b139"
|
sha256: "426cf75afdb23aa74bd4e471704de3f9393f3c7b04c1e2d9c6f1073ae0b8b139"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.12.1"
|
version: "8.12.1"
|
||||||
characters:
|
characters:
|
||||||
@@ -110,7 +110,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
checked_yaml:
|
checked_yaml:
|
||||||
@@ -118,7 +118,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: checked_yaml
|
name: checked_yaml
|
||||||
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
|
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.4"
|
version: "2.0.4"
|
||||||
clock:
|
clock:
|
||||||
@@ -126,7 +126,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.2"
|
||||||
code_builder:
|
code_builder:
|
||||||
@@ -134,7 +134,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: code_builder
|
name: code_builder
|
||||||
sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243"
|
sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.11.0"
|
version: "4.11.0"
|
||||||
collection:
|
collection:
|
||||||
@@ -142,7 +142,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.19.1"
|
version: "1.19.1"
|
||||||
convert:
|
convert:
|
||||||
@@ -150,7 +150,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: convert
|
name: convert
|
||||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
crypto:
|
crypto:
|
||||||
@@ -158,7 +158,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.7"
|
version: "3.0.7"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
@@ -166,7 +166,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: cupertino_icons
|
||||||
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
version: "1.0.8"
|
||||||
dart_style:
|
dart_style:
|
||||||
@@ -174,7 +174,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
|
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.6"
|
version: "2.3.6"
|
||||||
dbus:
|
dbus:
|
||||||
@@ -182,7 +182,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: dbus
|
name: dbus
|
||||||
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
|
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.11"
|
version: "0.7.11"
|
||||||
fake_async:
|
fake_async:
|
||||||
@@ -190,7 +190,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.3"
|
version: "1.3.3"
|
||||||
ffi:
|
ffi:
|
||||||
@@ -198,7 +198,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
file:
|
file:
|
||||||
@@ -206,7 +206,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: file
|
name: file
|
||||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.1"
|
version: "7.0.1"
|
||||||
fixnum:
|
fixnum:
|
||||||
@@ -214,7 +214,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: fixnum
|
name: fixnum
|
||||||
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
flutter:
|
flutter:
|
||||||
@@ -227,7 +227,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
|
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.0"
|
version: "6.0.0"
|
||||||
flutter_local_notifications:
|
flutter_local_notifications:
|
||||||
@@ -235,7 +235,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: flutter_local_notifications
|
name: flutter_local_notifications
|
||||||
sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35"
|
sha256: "674173fd3c9eda9d4c8528da2ce0ea69f161577495a9cc835a2a4ecd7eadeb35"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "17.2.4"
|
version: "17.2.4"
|
||||||
flutter_local_notifications_linux:
|
flutter_local_notifications_linux:
|
||||||
@@ -243,7 +243,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: flutter_local_notifications_linux
|
name: flutter_local_notifications_linux
|
||||||
sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af
|
sha256: c49bd06165cad9beeb79090b18cd1eb0296f4bf4b23b84426e37dd7c027fc3af
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.1"
|
||||||
flutter_local_notifications_platform_interface:
|
flutter_local_notifications_platform_interface:
|
||||||
@@ -251,7 +251,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: flutter_local_notifications_platform_interface
|
name: flutter_local_notifications_platform_interface
|
||||||
sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
|
sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.0"
|
version: "7.2.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -269,7 +269,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: frontend_server_client
|
name: frontend_server_client
|
||||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
glob:
|
glob:
|
||||||
@@ -277,7 +277,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: glob
|
name: glob
|
||||||
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
@@ -285,7 +285,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: google_fonts
|
name: google_fonts
|
||||||
sha256: "517b20870220c48752eafa0ba1a797a092fb22df0d89535fd9991e86ee2cdd9c"
|
sha256: "517b20870220c48752eafa0ba1a797a092fb22df0d89535fd9991e86ee2cdd9c"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.2"
|
version: "6.3.2"
|
||||||
graphs:
|
graphs:
|
||||||
@@ -293,7 +293,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: graphs
|
name: graphs
|
||||||
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
|
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.2"
|
||||||
hive:
|
hive:
|
||||||
@@ -301,7 +301,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: hive
|
name: hive
|
||||||
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
|
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.3"
|
version: "2.2.3"
|
||||||
hive_flutter:
|
hive_flutter:
|
||||||
@@ -309,7 +309,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: hive_flutter
|
name: hive_flutter
|
||||||
sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc
|
sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
hive_generator:
|
hive_generator:
|
||||||
@@ -317,7 +317,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: hive_generator
|
name: hive_generator
|
||||||
sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4"
|
sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
http:
|
http:
|
||||||
@@ -325,7 +325,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.0"
|
version: "1.6.0"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
@@ -333,7 +333,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: http_multi_server
|
name: http_multi_server
|
||||||
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.2"
|
version: "3.2.2"
|
||||||
http_parser:
|
http_parser:
|
||||||
@@ -341,7 +341,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: http_parser
|
name: http_parser
|
||||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.2"
|
version: "4.1.2"
|
||||||
intl:
|
intl:
|
||||||
@@ -349,7 +349,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.19.0"
|
version: "0.19.0"
|
||||||
io:
|
io:
|
||||||
@@ -357,7 +357,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: io
|
name: io
|
||||||
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.5"
|
||||||
js:
|
js:
|
||||||
@@ -365,7 +365,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.2"
|
version: "0.7.2"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
@@ -373,7 +373,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: json_annotation
|
name: json_annotation
|
||||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.9.0"
|
version: "4.9.0"
|
||||||
leak_tracker:
|
leak_tracker:
|
||||||
@@ -381,7 +381,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.0.2"
|
version: "11.0.2"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
@@ -389,7 +389,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.10"
|
version: "3.0.10"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
@@ -397,7 +397,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.2"
|
||||||
lints:
|
lints:
|
||||||
@@ -405,7 +405,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0
|
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.0"
|
version: "6.0.0"
|
||||||
logging:
|
logging:
|
||||||
@@ -413,7 +413,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: logging
|
name: logging
|
||||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
matcher:
|
matcher:
|
||||||
@@ -421,7 +421,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.17"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
@@ -429,7 +429,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.1"
|
version: "0.11.1"
|
||||||
meta:
|
meta:
|
||||||
@@ -437,7 +437,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.0"
|
version: "1.17.0"
|
||||||
mime:
|
mime:
|
||||||
@@ -445,7 +445,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
objective_c:
|
objective_c:
|
||||||
@@ -453,7 +453,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: objective_c
|
name: objective_c
|
||||||
sha256: "1f81ed9e41909d44162d7ec8663b2c647c202317cc0b56d3d56f6a13146a0b64"
|
sha256: "1f81ed9e41909d44162d7ec8663b2c647c202317cc0b56d3d56f6a13146a0b64"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.1.0"
|
version: "9.1.0"
|
||||||
package_config:
|
package_config:
|
||||||
@@ -461,7 +461,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: package_config
|
name: package_config
|
||||||
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
path:
|
path:
|
||||||
@@ -469,7 +469,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.9.1"
|
||||||
path_provider:
|
path_provider:
|
||||||
@@ -477,7 +477,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.5"
|
version: "2.1.5"
|
||||||
path_provider_android:
|
path_provider_android:
|
||||||
@@ -485,7 +485,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path_provider_android
|
name: path_provider_android
|
||||||
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
|
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.22"
|
version: "2.2.22"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
@@ -493,7 +493,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path_provider_foundation
|
name: path_provider_foundation
|
||||||
sha256: "6192e477f34018ef1ea790c56fffc7302e3bc3efede9e798b934c252c8c105ba"
|
sha256: "6192e477f34018ef1ea790c56fffc7302e3bc3efede9e798b934c252c8c105ba"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0"
|
version: "2.5.0"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
@@ -501,7 +501,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "2.2.1"
|
||||||
path_provider_platform_interface:
|
path_provider_platform_interface:
|
||||||
@@ -509,7 +509,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path_provider_platform_interface
|
name: path_provider_platform_interface
|
||||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
path_provider_windows:
|
path_provider_windows:
|
||||||
@@ -517,7 +517,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
petitparser:
|
petitparser:
|
||||||
@@ -525,7 +525,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: petitparser
|
name: petitparser
|
||||||
sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1"
|
sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.1"
|
version: "7.0.1"
|
||||||
platform:
|
platform:
|
||||||
@@ -533,7 +533,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: platform
|
name: platform
|
||||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.6"
|
version: "3.1.6"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
@@ -541,7 +541,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: plugin_platform_interface
|
name: plugin_platform_interface
|
||||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.8"
|
version: "2.1.8"
|
||||||
pool:
|
pool:
|
||||||
@@ -549,7 +549,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: pool
|
name: pool
|
||||||
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
|
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.2"
|
version: "1.5.2"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
@@ -557,7 +557,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: pub_semver
|
name: pub_semver
|
||||||
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
pubspec_parse:
|
pubspec_parse:
|
||||||
@@ -565,7 +565,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: pubspec_parse
|
name: pubspec_parse
|
||||||
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
|
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.5.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
@@ -573,7 +573,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
|
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.3"
|
version: "2.5.3"
|
||||||
shared_preferences_android:
|
shared_preferences_android:
|
||||||
@@ -581,7 +581,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "46a46fd64659eff15f4638bbe19de43f9483f0e0bf024a9fb6b3582064bacc7b"
|
sha256: "46a46fd64659eff15f4638bbe19de43f9483f0e0bf024a9fb6b3582064bacc7b"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.17"
|
version: "2.4.17"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
@@ -589,7 +589,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences_foundation
|
name: shared_preferences_foundation
|
||||||
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.6"
|
version: "2.5.6"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
@@ -597,7 +597,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences_linux
|
name: shared_preferences_linux
|
||||||
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
shared_preferences_platform_interface:
|
shared_preferences_platform_interface:
|
||||||
@@ -605,7 +605,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences_platform_interface
|
name: shared_preferences_platform_interface
|
||||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
shared_preferences_web:
|
shared_preferences_web:
|
||||||
@@ -613,7 +613,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences_web
|
name: shared_preferences_web
|
||||||
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.3"
|
version: "2.4.3"
|
||||||
shared_preferences_windows:
|
shared_preferences_windows:
|
||||||
@@ -621,7 +621,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shared_preferences_windows
|
name: shared_preferences_windows
|
||||||
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
shelf:
|
shelf:
|
||||||
@@ -629,7 +629,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shelf
|
name: shelf
|
||||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.2"
|
version: "1.4.2"
|
||||||
shelf_web_socket:
|
shelf_web_socket:
|
||||||
@@ -637,7 +637,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shelf_web_socket
|
name: shelf_web_socket
|
||||||
sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
|
sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
@@ -650,7 +650,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: source_gen
|
name: source_gen
|
||||||
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
|
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.5.0"
|
||||||
source_helper:
|
source_helper:
|
||||||
@@ -658,7 +658,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: source_helper
|
name: source_helper
|
||||||
sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c"
|
sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.5"
|
version: "1.3.5"
|
||||||
source_span:
|
source_span:
|
||||||
@@ -666,7 +666,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.1"
|
version: "1.10.1"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
@@ -674,7 +674,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.12.1"
|
version: "1.12.1"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
@@ -682,7 +682,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
stream_transform:
|
stream_transform:
|
||||||
@@ -690,7 +690,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: stream_transform
|
name: stream_transform
|
||||||
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
|
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
@@ -698,7 +698,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.1"
|
version: "1.4.1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
@@ -706,7 +706,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.2"
|
version: "1.2.2"
|
||||||
test_api:
|
test_api:
|
||||||
@@ -714,7 +714,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.7"
|
version: "0.7.7"
|
||||||
timezone:
|
timezone:
|
||||||
@@ -722,7 +722,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: timezone
|
name: timezone
|
||||||
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
|
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.4"
|
version: "0.9.4"
|
||||||
timing:
|
timing:
|
||||||
@@ -730,7 +730,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: timing
|
name: timing
|
||||||
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
|
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
typed_data:
|
typed_data:
|
||||||
@@ -738,7 +738,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
vector_math:
|
vector_math:
|
||||||
@@ -746,7 +746,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
@@ -754,7 +754,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
|
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.0.2"
|
version: "15.0.2"
|
||||||
watcher:
|
watcher:
|
||||||
@@ -762,7 +762,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a"
|
sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.4"
|
version: "1.1.4"
|
||||||
web:
|
web:
|
||||||
@@ -770,7 +770,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: web
|
name: web
|
||||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
web_socket:
|
web_socket:
|
||||||
@@ -778,7 +778,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: web_socket
|
name: web_socket
|
||||||
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
@@ -786,7 +786,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: web_socket_channel
|
name: web_socket_channel
|
||||||
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
@@ -794,7 +794,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
xml:
|
xml:
|
||||||
@@ -802,7 +802,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: xml
|
name: xml
|
||||||
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
|
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.6.1"
|
version: "6.6.1"
|
||||||
yaml:
|
yaml:
|
||||||
@@ -810,7 +810,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: yaml
|
name: yaml
|
||||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
|
|||||||
Reference in New Issue
Block a user