Skip to content

Commit f0fc9ac

Browse files
KyleKlusdependabot[bot]LoriteCopilotBeaconSage
authored
chore: collecting next patch version (#1555)
* fix: Fixed a few small bugs that have accumulated (#1514) * feat: Improved version release workflow (#1509) * FIX: Excluded gh-pages from tests rather than just including the main branch, as all other branches should also have to abide by the tests * FEAT: Improved the contributing page in the docs * FIX: Fixed wrong deck progress counter * FIX: Fixed that clozes didn't save when editing them * FIX: Fixed that the edit modal would remove question marks * FIX: Fixed that a multiline card would become a single line card * FIX: Fixed the design of tables in callouts * chore: bump version to v1.14.2 * fix: Fix obsidian comunity issues (#1521) * FIX: Fixed that the fetch of the newest version number happens automatically without user consent * FIX: Fixed that the locale helper used dangerous use of new Function * FIX: Fixed a lot of scorecard issues * fix: Fixed more community issues (#1532) * chore(deps): bump brace-expansion from 5.0.5 to 5.0.6 (#1525) Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 5.0.5 to 5.0.6. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](juliangruber/brace-expansion@v5.0.5...v5.0.6) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 5.0.6 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump pymdown-extensions from 10.21.2 to 10.21.3 (#1531) Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 10.21.2 to 10.21.3. - [Release notes](https://github.com/facelessuser/pymdown-extensions/releases) - [Commits](facelessuser/pymdown-extensions@10.21.2...10.21.3) --- updated-dependencies: - dependency-name: pymdown-extensions dependency-version: 10.21.3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * FIX: Fixed that the plugin wasnt using window.setTimeout * FEAT: Added Artifact attestation * FEAT: Added file verification --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * CHORE: Prepped next release * feat: store scheduling data in plugin data instead of inline in notes (#1471) * feat: store scheduling data in plugin data instead of inline in notes (#162) Adds an optional 'Store in plugin data' mode (beta) that keeps all scheduling metadata in plugin data rather than writing <!--SR:...--> comments into note markdown. - Schedule state (note + card schedules) persisted in plugin data under `scheduleState`, with a one-time migration path for legacy `notePath::hash` card keys to content-hash-only keys that survive renames and external moves - `ScheduleDataRepository` handles CRUD for persisted schedules; `StoreInPluginData` implements `IDataStore` with inline-comment fallback for graceful migration when the mode is first enabled - `DataStoreInPluginDataAlgorithmOsr` returns an empty schedule comment so no SR annotations are written back to notes in this mode - `OsrCore` routes note schedule reads/writes through the repository when the mode is active, with frontmatter fallback on first switch - `vault.on('rename')` listener keeps note schedule keys consistent after Obsidian-internal renames (card keys are content-hash-based and need no rename handling) - Settings UI dropdown to switch between NOTES and PLUGIN_DATA modes - Full unit test coverage for repository and store classes * feat: migrate scheduling data when switching storage modes When the user switches between 'Store in notes' and 'Store in plugin data' in settings, a confirmation modal now prompts before migrating all existing scheduling data to the new location. - NOTES → PLUGIN_DATA: reads sr-* frontmatter fields and <!--SR:...--> inline comments from all vault files, writes them to the plugin data repository, then strips the SR metadata from the files - PLUGIN_DATA → NOTES: reads all schedules from the repository and writes them back as inline comments and sr-* frontmatter, then clears the repository state - Settings dropdown reverts immediately on change and only applies after the user confirms; migration runs before the mode switch so each direction reads from the correct source - DataStoreMigrator is excluded from coverage (Obsidian-API-coupled, same as file.ts and delete-scheduling-data.ts) - ScheduleDataRepository.clearState() added for post-migration cleanup * feat: UUID-based note identification, data settings page, and test coverage - Add sr-id UUID to note frontmatter so note schedules survive any rename or move, inside or outside Obsidian (crypto.randomUUID written once on first schedule write; existing path-keyed entries lazily migrated on read) - Update ISRFile with getNoteId / getOrCreateNoteId; implement in SrTFile and UnitTestSRFile - Update core.ts and DataStoreMigrator to use UUID as the note schedule key - Add "Data" settings page (data-page.tsx) with data storage dropdown and delete-scheduling-data buttons; move them out of scheduling-page.tsx - Add PLUGIN_DATA_STORE_INFO locale key explaining UUID and hash semantics - Add tests: DataStoreInPluginDataAlgorithmOsr (was 0% coverage), UUID-keyed note schedule behaviour in ScheduleDataRepository * PR fixes: store the scheduling data in a 2 different md files with json format inside * Add missing tests for coverage * Fix small bug * Add the final test for 100% test coverage!!!! * FEAT: Refactored data related stuff from main into a data manager * FEAT: Refactored data related stuff from main into a data manager (2nd try ;D ) * REFAC: Moved data store related files into data folder * REFAC: Moved more data related files into data folder * REFAC: Refactored osrAppCore into the dataManager & commented a bunch of code * REFAC: Established a data-structures folder in data * REFAC: Moved deck folder to the new data-structures folder * REFAC: Refactored & commented back end code * REFAC: Cleaned up data stores * REFAC: Removed tests * REFAC: Refactored file & fixed some typing issues * REFAC: Refactored deck to one day be able to support notes & fixed a lot of type issues Co-authored-by: Copilot <copilot@github.com> * REFAC: Moved scheduling related files to scheduling folder * FIX: Fixed wrong imports due to last refactoring * FIX: Fixed formatting issues * REFAC: Refactored tests so that they match the actual folder structure in src & fixed some config errors * REFAC: Renamed data stores folder to data store instances * REFAC: Moved data store related code to data store folder * REFAC: Refactored data store folders & Implemented a data store specific schedule deleter * WIP: Implemented folder data store * CHANGE: Fully removed not working implementation & packaged files for later use * FIX: Fixed some errors --------- Co-authored-by: Kyle Klus <kyle.klus.2@gmail.com> Co-authored-by: Copilot <copilot@github.com> * feat: Implemented a callou to hide away the sr comment (#1539) * FIX: Removed unnecessary awaits * FEAT: Implemented schedule comments in callouts * FEAT: Implemented that the sr callout hides away * FIX: Formatted * WIP: Implemented a migration tool * FEAT: Fully implemented metadata callouts * FIX: Formatted & fixed errors * FIX: FIxed some errors * FIX: Added some more tests * fix: bug hunt (#1542) * FIX: Fixed a whole boatload of type errors * FIX: Fixed another boat load of bugs * FIX: Fixed that data was loaded in the load function * feat: jump hotkey (#1543) FEAT: Implemented a jump to card hotkey * chore: prepped v1.15.0 * fix: Fix bugs of last refactor & implementing a language setting (#1551) * FIX: Removed built in package from dependencies * FIX: Hooked up commandManager in ui settings * FIX: Fixed that the statistics page was looping on infinit * FIX: Fixed that settings search breaks sr plugin by rudely calling the display function ;D * FIX: Fixed that the review queue sometimes didnt show anything & fixed that there wasnt an option for language selection * FIX: Removed postcss as it isnt needed anymore * FIX: Added pnpm settings * FIX: Fixed a type error * FIX: Fixed that obsidian build verification wasnt working * chore: prepped v1.15.1 * fix: Maybe fix the build error on the community page * feat: auto-open review sessions for ready flashcards (#1513) feat: add flashcard review reminders * FIX: Fixed that an open tab caused the plugin to crash * FIX: Fixed formatting --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alejandro Lorite Mora <a.lorite.mora@gmail.com> Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Beacon <beacon.sage@outlook.com>
1 parent 799582d commit f0fc9ac

14 files changed

Lines changed: 1507 additions & 787 deletions

File tree

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
build
22
coverage
33
node_modules
4+
styles.css
45
pnpm-lock.yaml
56
docs/vaults/
67
tests/vaults/

esbuild.config.mjs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@ import esbuild from "esbuild";
33
import fs from "fs";
44
import { builtinModules } from "node:module";
55
import path from "path";
6+
import prettier from "prettier";
67
import process from "process";
78

89
const prod = process.argv[2] === "production";
910

11+
// The published plugin expects CSS at the repository root, not under build/.
12+
// We also normalize the generated stylesheet through Prettier so CI does not
13+
// fail on formatting differences introduced by the bundler output.
1014
const moveToRootPlugin = {
1115
name: "move-to-root",
1216
setup(build) {
13-
build.onEnd((_) => {
17+
build.onEnd(async (_) => {
1418
const cssFile = path.join("build", "main.css");
1519
const targetFile = "styles.css";
1620

1721
if (fs.existsSync(cssFile)) {
1822
let contents = fs.readFileSync(cssFile, "utf8");
1923
// Remove source map comment
2024
contents = contents.replace(/\/\*#\s*sourceMappingURL=.*?\*\/\s*$/s, "");
25+
contents = await prettier.format(contents, { filepath: targetFile });
2126
fs.writeFileSync(targetFile, contents);
2227
fs.rmSync(cssFile);
2328

@@ -45,8 +50,15 @@ const context = await esbuild.context({
4550
});
4651

4752
if (prod) {
48-
context.rebuild().catch(() => process.exit(1));
49-
context.dispose();
53+
try {
54+
// Production mode must await rebuild/dispose so async post-processing of
55+
// styles.css has finished before the process exits.
56+
await context.rebuild();
57+
} catch {
58+
process.exit(1);
59+
} finally {
60+
await context.dispose();
61+
}
5062
} else {
5163
context.watch().catch(() => process.exit(1));
5264
}

pnpm-workspace.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
packages:
2+
- "."
3+
4+
onlyBuiltDependencies:
5+
- "."

src/data/settings.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ export interface SRSettings {
2323
multilineReversedCardSeparator: string;
2424
multilineCardEndMarker: string;
2525
editLaterTag: string | undefined;
26+
// Reminder settings are intentionally limited to "when and how to nudge the user back
27+
// into review". They do not model richer calendar-style scheduling for reminder delivery.
28+
enableReviewReminders: boolean;
29+
reviewReminderIntervalMinutes: number;
30+
reviewReminderCheckOnStartup: boolean;
31+
reviewReminderMessage: string;
32+
reviewReminderAutoOpen: boolean;
33+
reviewReminderShowNotice: boolean;
34+
reviewReminderPlaySound: boolean;
35+
reviewReminderBounceDock: boolean;
2636

2737
// notes
2838
enableNoteReviewPaneOnStartup: boolean;
@@ -104,6 +114,14 @@ export const DEFAULT_SETTINGS: SRSettings = {
104114
multilineReversedCardSeparator: "??",
105115
multilineCardEndMarker: "",
106116
editLaterTag: undefined,
117+
enableReviewReminders: false,
118+
reviewReminderIntervalMinutes: 5,
119+
reviewReminderCheckOnStartup: false,
120+
reviewReminderMessage: "",
121+
reviewReminderAutoOpen: true,
122+
reviewReminderShowNotice: true,
123+
reviewReminderPlaySound: true,
124+
reviewReminderBounceDock: true,
107125
randomizeCardOrder: undefined,
108126

109127
// notes
@@ -214,6 +232,56 @@ export function upgradeSettings(settings: SRSettings) {
214232
if (settings.fsrsDesiredRetention === null || settings.fsrsDesiredRetention === undefined) {
215233
settings.fsrsDesiredRetention = DEFAULT_SETTINGS.fsrsDesiredRetention;
216234
}
235+
236+
// Only published reminder settings are upgraded here. We deliberately do not preserve
237+
// unpublished draft field names from this feature branch, so the shipped schema stays clean.
238+
if (settings.enableReviewReminders === null || settings.enableReviewReminders === undefined) {
239+
settings.enableReviewReminders = DEFAULT_SETTINGS.enableReviewReminders;
240+
}
241+
242+
if (
243+
settings.reviewReminderIntervalMinutes === null ||
244+
settings.reviewReminderIntervalMinutes === undefined ||
245+
settings.reviewReminderIntervalMinutes < 1
246+
) {
247+
settings.reviewReminderIntervalMinutes = DEFAULT_SETTINGS.reviewReminderIntervalMinutes;
248+
}
249+
250+
if (
251+
settings.reviewReminderCheckOnStartup === null ||
252+
settings.reviewReminderCheckOnStartup === undefined
253+
) {
254+
settings.reviewReminderCheckOnStartup = DEFAULT_SETTINGS.reviewReminderCheckOnStartup;
255+
}
256+
257+
if (settings.reviewReminderMessage === null || settings.reviewReminderMessage === undefined) {
258+
settings.reviewReminderMessage = DEFAULT_SETTINGS.reviewReminderMessage;
259+
}
260+
261+
if (settings.reviewReminderAutoOpen === null || settings.reviewReminderAutoOpen === undefined) {
262+
settings.reviewReminderAutoOpen = DEFAULT_SETTINGS.reviewReminderAutoOpen;
263+
}
264+
265+
if (
266+
settings.reviewReminderShowNotice === null ||
267+
settings.reviewReminderShowNotice === undefined
268+
) {
269+
settings.reviewReminderShowNotice = DEFAULT_SETTINGS.reviewReminderShowNotice;
270+
}
271+
272+
if (
273+
settings.reviewReminderPlaySound === null ||
274+
settings.reviewReminderPlaySound === undefined
275+
) {
276+
settings.reviewReminderPlaySound = DEFAULT_SETTINGS.reviewReminderPlaySound;
277+
}
278+
279+
if (
280+
settings.reviewReminderBounceDock === null ||
281+
settings.reviewReminderBounceDock === undefined
282+
) {
283+
settings.reviewReminderBounceDock = DEFAULT_SETTINGS.reviewReminderBounceDock;
284+
}
217285
}
218286

219287
export class SettingsUtil {

src/lang/base-locale.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,24 @@ export interface IBaseLocale {
125125
REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: string;
126126
REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: string;
127127
REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: string;
128+
REVIEW_REMINDER_NOTICE: string;
129+
REVIEW_REMINDERS: string;
130+
REVIEW_REMINDERS_DESC: string;
131+
REVIEW_REMINDER_CHECK_ON_STARTUP: string;
132+
REVIEW_REMINDER_CHECK_ON_STARTUP_DESC: string;
133+
REVIEW_REMINDER_INTERVAL: string;
134+
REVIEW_REMINDER_INTERVAL_DESC: string;
135+
REVIEW_REMINDER_INTERVAL_MIN_WARNING: string;
136+
REVIEW_REMINDER_MESSAGE: string;
137+
REVIEW_REMINDER_MESSAGE_DESC: string;
138+
REVIEW_REMINDER_AUTO_OPEN: string;
139+
REVIEW_REMINDER_AUTO_OPEN_DESC: string;
140+
REVIEW_REMINDER_SHOW_NOTICE: string;
141+
REVIEW_REMINDER_SHOW_NOTICE_DESC: string;
142+
REVIEW_REMINDER_PLAY_SOUND: string;
143+
REVIEW_REMINDER_PLAY_SOUND_DESC: string;
144+
REVIEW_REMINDER_BOUNCE_DOCK: string;
145+
REVIEW_REMINDER_BOUNCE_DOCK_DESC: string;
128146
DISABLE_CLOZE_CARDS: string;
129147
CONVERT_CLOZE_PATTERNS_TO_INPUTS: string;
130148
CONVERT_CLOZE_PATTERNS_TO_INPUTS_DESC: string;

src/lang/locale/en.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ const en: IBaseLocale = {
5858
RESPONSE_RECEIVED: "Response received.",
5959
NO_DECK_EXISTS: "No deck exists for ${deckName}",
6060
ALL_CAUGHT_UP: "You're all caught up now :D.",
61+
REVIEW_REMINDER_NOTICE:
62+
"Flashcards are ready to review. Return to Obsidian to continue learning.",
6163

6264
// scheduling.ts
6365
DAYS_STR_IVL: "${interval} day(s)",
@@ -152,6 +154,29 @@ const en: IBaseLocale = {
152154
REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM:
153155
"Randomly (once all cards in previous deck reviewed)",
154156
REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "Random card from random deck",
157+
REVIEW_REMINDERS: "Review reminders",
158+
REVIEW_REMINDERS_DESC:
159+
"Periodically checks for new or due flashcards and reminds you when cards are ready to review.",
160+
REVIEW_REMINDER_CHECK_ON_STARTUP: "Check immediately on startup",
161+
REVIEW_REMINDER_CHECK_ON_STARTUP_DESC:
162+
"Runs one check when Obsidian startup layout is ready, without waiting for the first interval.",
163+
REVIEW_REMINDER_INTERVAL: "Reminder interval (minutes)",
164+
REVIEW_REMINDER_INTERVAL_DESC:
165+
"Checks every N minutes. Minimum 1 minute, maximum 1440 minutes.",
166+
REVIEW_REMINDER_INTERVAL_MIN_WARNING: "Reminder interval must be a number between 1 and 1440.",
167+
REVIEW_REMINDER_MESSAGE: "Reminder message",
168+
REVIEW_REMINDER_MESSAGE_DESC:
169+
"Optional custom message shown in the reminder notice. Leave empty to use the default message.",
170+
REVIEW_REMINDER_AUTO_OPEN: "Automatically open review",
171+
REVIEW_REMINDER_AUTO_OPEN_DESC:
172+
"When enabled, reminders open the existing flashcard review session directly.",
173+
REVIEW_REMINDER_SHOW_NOTICE: "Show notice when reminding",
174+
REVIEW_REMINDER_SHOW_NOTICE_DESC: "Displays a temporary notice when a review reminder fires.",
175+
REVIEW_REMINDER_PLAY_SOUND: "Play sound when reminding",
176+
REVIEW_REMINDER_PLAY_SOUND_DESC: "Plays a short alert sound when a review reminder fires.",
177+
REVIEW_REMINDER_BOUNCE_DOCK: "Bounce dock icon when reminding",
178+
REVIEW_REMINDER_BOUNCE_DOCK_DESC:
179+
"On desktop, bounces the dock icon when a review reminder fires.",
155180
DISABLE_CLOZE_CARDS: "Disable cloze cards?",
156181
CONVERT_CLOZE_PATTERNS_TO_INPUTS: "Convert cloze patterns to input fields",
157182
CONVERT_CLOZE_PATTERNS_TO_INPUTS_DESC:

src/lang/locale/zh-cn.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const zhCN: IBaseLocale = {
4646
RESPONSE_RECEIVED: "反馈已收到",
4747
NO_DECK_EXISTS: "没有 ${deckName} 卡组",
4848
ALL_CAUGHT_UP: "都复习完啦,你真棒!",
49+
REVIEW_REMINDER_NOTICE: "闪卡已经可以复习了。回到 Obsidian 继续学习。",
4950

5051
// scheduling.ts
5152
DAYS_STR_IVL: "${interval}天",
@@ -115,6 +116,24 @@ const zhCN: IBaseLocale = {
115116
REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_SEQUENTIAL: "顺序 (在前一卡片组内卡片都复习完后)",
116117
REVIEW_DECK_ORDER_PREV_DECK_COMPLETE_RANDOM: "乱序 (在前一卡片组内卡片都复习完后)",
117118
REVIEW_DECK_ORDER_RANDOM_DECK_AND_CARD: "卡片组及卡片都乱序",
119+
REVIEW_REMINDERS: "复习提醒",
120+
REVIEW_REMINDERS_DESC: "定期检查是否有新的或到期的闪卡,并在可以复习时提醒你。",
121+
REVIEW_REMINDER_CHECK_ON_STARTUP: "启动后立即检查",
122+
REVIEW_REMINDER_CHECK_ON_STARTUP_DESC:
123+
"在 Obsidian 布局就绪后立即执行一次检查,不等待首次周期触发。",
124+
REVIEW_REMINDER_INTERVAL: "提醒间隔(分钟)",
125+
REVIEW_REMINDER_INTERVAL_DESC: "每 N 分钟检查一次。最小 1 分钟,最大 1440 分钟。",
126+
REVIEW_REMINDER_INTERVAL_MIN_WARNING: "提醒间隔必须是 1 到 1440 之间的数字。",
127+
REVIEW_REMINDER_MESSAGE: "提醒消息",
128+
REVIEW_REMINDER_MESSAGE_DESC: "可选的自定义提醒文案。留空时使用默认消息。",
129+
REVIEW_REMINDER_AUTO_OPEN: "自动打开复习",
130+
REVIEW_REMINDER_AUTO_OPEN_DESC: "启用后,提醒触发时会直接打开现有的闪卡复习界面。",
131+
REVIEW_REMINDER_SHOW_NOTICE: "提醒时显示通知",
132+
REVIEW_REMINDER_SHOW_NOTICE_DESC: "提醒触发时显示一个临时通知。",
133+
REVIEW_REMINDER_PLAY_SOUND: "提醒时播放声音",
134+
REVIEW_REMINDER_PLAY_SOUND_DESC: "提醒触发时播放一段简短提示音。",
135+
REVIEW_REMINDER_BOUNCE_DOCK: "提醒时弹跳 Dock 图标",
136+
REVIEW_REMINDER_BOUNCE_DOCK_DESC: "在桌面端,提醒触发时弹跳 Dock 图标。",
118137
DISABLE_CLOZE_CARDS: "不进行完形填空",
119138
CONVERT_CLOZE_PATTERNS_TO_INPUTS: "Convert cloze patterns to input fields",
120139
CONVERT_CLOZE_PATTERNS_TO_INPUTS_DESC:

0 commit comments

Comments
 (0)