Skip to content

Commit 76dcc67

Browse files
Merge pull request #85 from OctagonalStar/dev
Dev Merge
2 parents 3d40033 + 4c645a8 commit 76dcc67

13 files changed

Lines changed: 408 additions & 449 deletions

File tree

.github/workflows/FlutterBuild.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
uses: subosito/flutter-action@v2
1919
with:
2020
channel: stable
21-
flutter-version: '3.41.0'
21+
flutter-version: '3.44.0'
2222
- name: Decode keystore
2323
run: |
2424
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/release.jks

.github/workflows/FlutterBuildTest.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
uses: subosito/flutter-action@v2
1616
with:
1717
channel: stable
18-
flutter-version: '3.41.0'
18+
flutter-version: '3.44.0'
1919

2020
- run: flutter pub get
2121
- run: flutter build windows
@@ -32,7 +32,7 @@ jobs:
3232
- uses: actions/checkout@v6
3333
- uses: subosito/flutter-action@v2
3434
with:
35-
flutter-version: '3.41.0'
35+
flutter-version: '3.44.0'
3636
- run: flutter pub get
3737
- run: flutter build web --release
3838
- uses: actions/upload-artifact@v7

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@
66

77
- 复习模块添加了强化学习选项
88
- 添加了学习中单词自动播放发音的功能
9+
- 复习阶段添加了进度指示
910

1011
### Improvement
1112

1213
- 优化了FSRS学习机制
1314
- 听写界面不熄屏
1415
- 优化解压逻辑,避免主线程卡死
16+
- 复习改为自动乱序
17+
- 更新Flutter框架至3.44.0
1518

1619
### Fix
1720

1821
- 修复了可能的复习列表重复问题
1922
- 补全控制器销毁逻辑,避免内存泄露
2023
- 修复了网页端中无法通过文件导入数据的问题
24+
- 修复了单词推送不截止的问题
2125

2226
## v1.0.0 - 2026-3-18 - (100000)
2327

CONTRIBUTING.md

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
待审查通过后,你的提交就会被合并。
3838

39+
---
40+
3941
## 你必须做到的
4042

4143
请在你进行提交和PR时关注以下的问题:
@@ -44,7 +46,7 @@
4446

4547
这个项目设置了必须要有GPG验证了是你的更改后才能进行合并。
4648

47-
> 如果你不知道GPG是什么,请参照[这篇文章](https://docs.github.com/zh/authentication/managing-commit-signature-verification/about-commit-signature-verification)
49+
> 如果你不知道GPG是什么,请参照[这篇文章](https://docs.github.com/authentication/managing-commit-signature-verification/about-commit-signature-verification)
4850
4951
### DCO签名
5052

@@ -54,6 +56,8 @@
5456

5557
你可以通过 `git commit -s` 对提交进行签署。
5658

59+
---
60+
5761
## 其他的事项
5862

5963
### 代码规范
@@ -67,18 +71,17 @@
6771
- 对于一个类,请使用大写字母或者下划线开头
6872
- 对于一个函数,请使用小写字母开头
6973

70-
违反此规定的PR会要求进行相应修改后即可
74+
---
75+
76+
### 关于AI辅助生成代码
77+
78+
> 该定义仅对此项目生效
7179
72-
#### 存储单词数据的变量
80+
定义: 通过 **自然语言** 请求或指导 **大语言模型(LLM)** 生成贡献中的 **编程语言代码** ,并且 **由人工的编写代码** 占贡献中 **40%** 以下的,即认为是 **AI辅助生成代码**
7381

74-
在应用中,存储单个阿拉伯语单词数据的变量使用`word`为变量名`Map<String, dynamic>`为其类型,内部详细结构如下
82+
要求: 我并不反对通过AI辅助生成代码,但**十分希望**通过AI辅助生成的贡献能做到以下几点:
7583

76-
``` dart
77-
Map<String, dynamic> word = {"arabic": "{Arabic}",
78-
"chinese": "{Chinese}",
79-
"explanation": "{explanation}",
80-
"subClass": "{className}",
81-
"learningProgress": "{times}", //int
82-
"id": "{id}" // int getSelectedWords函数结果中会有,并且所有面向用户的界面中调用的数据都应具有此键值对。
83-
};
84-
```
84+
1. 尊重他人,避免出现有侮辱性的部分。(要是出现了这类问题,**请不要拿AI做挡箭牌**
85+
2. 注意不要在代码中泄露你的Key。(当然,如果你想让别人也免费用的话,那就另说了)
86+
3. 先在你自己的环境下确保你的代码能正常运行。
87+
4. AI也会犯错,在你请求核查之前请先自己理解并排查可能的问题。

README.md

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,105 @@
1+
<!-- markdownlint-disable MD033 -->
12
# arabic_learning | Ar 学
23

3-
> 该软件目前还在开发阶段,很多功能尚未完善,使用时请倍加小心。
4+
<p align="center">
5+
<img src="https://github.com/OctagonalStar/arabic_learning/actions/workflows/FlutterBuild.yml/badge.svg" alt="Flutter Build">
6+
<img src="https://img.shields.io/badge/License-AGPL_3.0-blue.svg" alt="License: AGPL-3.0">
7+
</p>
48

5-
一个用于记背阿拉伯语单词的学习软件。
9+
一个跨平台的阿拉伯语 ~~背单词~~ 单词学习软件,支持 **Android / Windows / Linux / macOS / Web**
10+
11+
## 功能
12+
13+
### 学习
14+
15+
- 选择课程进行单词学习
16+
- 多种题型可自由配置与排序:单词卡片、中译阿选择题、阿译中选择题、拼写题、听力题
17+
- 题型内/题型间/全局三级乱序
18+
- 偏好易混词或同课词
19+
20+
### 规律复习(FSRS)
21+
22+
> [!TIP]
23+
> 你需要手动启用复习功能才会生效
24+
25+
- 基于 [FSRS](https://github.com/open-spaced-repetition/fsrs4anki) 算法的间隔重复复习
26+
- 可自由配置期望提取率、评分限时(优秀/良好)
27+
- 自我评级模式
28+
- 每日单词推送,学习即加入复习计划
29+
- 强化记忆循环:同一到期卡片在队列中交错出现多次
30+
31+
### 测试
32+
33+
- **自主听写**:配置播放速度/次数/间隔,听写期间不熄屏
34+
- **局域网联机对战**:通过 WebRTC 实现,支持扫码/口令连接,双方实时 PK
35+
36+
### 词库管理
37+
38+
- 从Github[此仓库](https://github.com/JYinherit/Arabiclearning)线上下载词库
39+
- 本地 JSON 文件导入
40+
- 词汇总览:按词库-课程分级展示,支持网格列数自定义
41+
- 词汇查找:阿语/中文双向搜索,支持 BK 树模糊匹配及编辑距离容错
42+
43+
### 数据同步
44+
45+
- **WebDAV** 远程备份与恢复
46+
- 本地数据导出/导入(JSON 文件)
47+
48+
### 音频与 TTS
49+
50+
- 系统 TTS / 在线 TTS/ 神经网络语音合成(sherpa-onnx / VITS)
51+
- 播放速度可调(0.5x – 1.5x)
52+
- 自动播放发音(学习中进入阿译中选择题时自动朗读)
53+
54+
### 个性化
55+
56+
- 多种主题色
57+
- Material UI
58+
- 深色模式
59+
- 备用字体(阿语 Vazirmatn / 中文 NotoSansSC)
60+
61+
### 统计
62+
63+
- 连胜天数
64+
- 已学词汇
65+
- 待复习数量
66+
- 词库单词总数
67+
68+
## 平台
69+
70+
| 平台 | 支持 |
71+
| ------ | ------ |
72+
| Android ||
73+
| Windows ||
74+
| Linux | ✅ (请自行构建) |
75+
| macOS ||
76+
| iOS | 已在v0.1.12终止支持 |
77+
| Web |[在线体验](https://octagonalstar.github.io/arabic_learning/) |
78+
79+
> 网页版为最新构建版,相对于软件版本可能有更多功能和更多 bug。
80+
81+
## 技术栈
82+
83+
- **框架**:Flutter/Dart
84+
- **状态管理**:Provider
85+
- **复习算法**:FSRS
86+
- **音频**:flutter_tts / just_audio / sherpa_onnx
87+
- **联机**:flutter_webrtc
88+
- **同步**:webdav_client
89+
- **搜索**:BK 树
90+
- **存储**:shared_preferences / idb_shim(Web IndexedDB)
91+
92+
## 构建
93+
94+
```bash
95+
flutter pub get
96+
flutter run
97+
```
98+
99+
各平台构建产物参见 GitHub Releases 和 Github Action。
100+
101+
## 许可证
102+
103+
[AGPL-3.0](LICENSE)
104+
105+
Copyright (C) 2025 OctagonalStar

lib/funcs/fsrs_func.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ class FSRS {
149149
logger.fine("计算得分: hard");
150150
return Rating.hard;
151151
}
152+
153+
DateTime? getCardBirthday(int wordId) {
154+
try {
155+
return config.reviewLogs.firstWhere((ReviewLog rvl) => rvl.cardId == wordId).reviewDateTime;
156+
} catch (e) {
157+
logger.severe("wordID: $wordId card not found or has more than one");
158+
return null;
159+
}
160+
}
152161
}
153162

154163
@immutable

lib/package_replacement/fake_dart_io.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class File {
55
// nothing
66
return "";
77
}
8-
bool existsSync() {return true;}
8+
bool existsSync() {return false;}
99

1010
void deleteSync() {}
1111

lib/pages/learning_page.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,13 @@ class LearningPage extends StatelessWidget {
113113
int tries = 0;
114114
while(pushWords.length < FSRS().config.pushAmount && tries < FSRS().config.pushAmount * 10){
115115
int chosen = rnd.nextInt(AppData().wordData.words.length);
116-
if(!FSRS().isContained(chosen)) {
116+
DateTime? cardBirthday = FSRS().getCardBirthday(chosen);
117+
if(cardBirthday == null || cardBirthday.difference(DateTime.now()).inDays == 0) {
117118
pushWords.add(AppData().wordData.words.elementAt(chosen));
118119
}
119120
tries++;
120121
}
122+
pushWords.removeWhere((WordItem item) => FSRS().isContained(item.id));
121123
if(pushWords.isEmpty) {
122124
ScaffoldMessenger.of(context).showSnackBar(
123125
SnackBar(content: Text("今日的推送已完成"), duration: Duration(seconds: 1),),

0 commit comments

Comments
 (0)