Skip to content

Commit

Permalink
started on flashcards
Browse files Browse the repository at this point in the history
  • Loading branch information
st3v3nmw committed Apr 17, 2021
1 parent df30fb8 commit a4c2fd6
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/constants.ts
@@ -1,6 +1,6 @@
export const SCHEDULING_INFO_REGEX = /^---\n((?:.*\n)*)sr-due: ([0-9A-Za-z ]+)\nsr-interval: ([0-9]+)\nsr-ease: ([0-9]+)\n((?:.*\n)*)---/;
export const YAML_FRONT_MATTER_REGEX = /^---\n((?:.*\n)*)---/;
export const REVIEW_QUEUE_VIEW_TYPE = "review-queue-list-view";
export const REMNOTE_STYLE_REGEX = /^(.+)::(.+)(?:\n<!--([0-9]+),([0-9]+),([0-9]+)-->)?/gm;

export const CROSS_HAIRS_ICON = `<path style=" stroke:none;fill-rule:nonzero;fill:currentColor;fill-opacity:1;" d="M 99.921875 47.941406 L 93.074219 47.941406 C 92.84375 42.03125 91.390625 36.238281 88.800781 30.921875 L 85.367188 32.582031 C 87.667969 37.355469 88.964844 42.550781 89.183594 47.84375 L 82.238281 47.84375 C 82.097656 44.617188 81.589844 41.417969 80.734375 38.304688 L 77.050781 39.335938 C 77.808594 42.089844 78.261719 44.917969 78.40625 47.769531 L 65.871094 47.769531 C 64.914062 40.507812 59.144531 34.832031 51.871094 33.996094 L 51.871094 21.386719 C 54.816406 21.507812 57.742188 21.960938 60.585938 22.738281 L 61.617188 19.058594 C 58.4375 18.191406 55.164062 17.691406 51.871094 17.570312 L 51.871094 10.550781 C 57.164062 10.769531 62.355469 12.066406 67.132812 14.363281 L 68.789062 10.929688 C 63.5 8.382812 57.738281 6.953125 51.871094 6.734375 L 51.871094 0.0390625 L 48.054688 0.0390625 L 48.054688 6.734375 C 42.179688 6.976562 36.417969 8.433594 31.132812 11.007812 L 32.792969 14.441406 C 37.566406 12.140625 42.761719 10.84375 48.054688 10.625 L 48.054688 17.570312 C 44.828125 17.714844 41.628906 18.21875 38.515625 19.078125 L 39.546875 22.757812 C 42.324219 21.988281 45.175781 21.53125 48.054688 21.386719 L 48.054688 34.03125 C 40.796875 34.949219 35.089844 40.679688 34.203125 47.941406 L 21.5 47.941406 C 21.632812 45.042969 22.089844 42.171875 22.855469 39.375 L 19.171875 38.34375 C 18.3125 41.457031 17.808594 44.65625 17.664062 47.882812 L 10.664062 47.882812 C 10.882812 42.589844 12.179688 37.394531 14.480469 32.621094 L 11.121094 30.921875 C 8.535156 36.238281 7.078125 42.03125 6.847656 47.941406 L 0 47.941406 L 0 51.753906 L 6.847656 51.753906 C 7.089844 57.636719 8.542969 63.402344 11.121094 68.695312 L 14.554688 67.035156 C 12.257812 62.261719 10.957031 57.066406 10.738281 51.773438 L 17.742188 51.773438 C 17.855469 55.042969 18.34375 58.289062 19.191406 61.445312 L 22.871094 60.414062 C 22.089844 57.5625 21.628906 54.632812 21.5 51.679688 L 34.203125 51.679688 C 35.058594 58.96875 40.773438 64.738281 48.054688 65.660156 L 48.054688 78.308594 C 45.105469 78.1875 42.183594 77.730469 39.335938 76.957031 L 38.304688 80.636719 C 41.488281 81.511719 44.757812 82.015625 48.054688 82.144531 L 48.054688 89.144531 C 42.761719 88.925781 37.566406 87.628906 32.792969 85.328125 L 31.132812 88.765625 C 36.425781 91.3125 42.183594 92.742188 48.054688 92.960938 L 48.054688 99.960938 L 51.871094 99.960938 L 51.871094 92.960938 C 57.75 92.71875 63.519531 91.265625 68.808594 88.6875 L 67.132812 85.253906 C 62.355469 87.550781 57.164062 88.851562 51.871094 89.070312 L 51.871094 82.125 C 55.09375 81.980469 58.292969 81.476562 61.40625 80.617188 L 60.378906 76.9375 C 57.574219 77.703125 54.695312 78.15625 51.792969 78.289062 L 51.792969 65.679688 C 59.121094 64.828125 64.910156 59.0625 65.796875 51.734375 L 78.367188 51.734375 C 78.25 54.734375 77.789062 57.710938 76.992188 60.605469 L 80.675781 61.636719 C 81.558594 58.40625 82.066406 55.082031 82.183594 51.734375 L 89.261719 51.734375 C 89.042969 57.03125 87.742188 62.222656 85.445312 66.996094 L 88.878906 68.65625 C 91.457031 63.367188 92.910156 57.597656 93.152344 51.71875 L 100 51.71875 Z M 62.019531 51.734375 C 61.183594 56.945312 57.085938 61.023438 51.871094 61.828125 L 51.871094 57.515625 L 48.054688 57.515625 L 48.054688 61.808594 C 42.910156 60.949219 38.886719 56.902344 38.058594 51.753906 L 42.332031 51.753906 L 42.332031 47.941406 L 38.058594 47.941406 C 38.886719 42.789062 42.910156 38.746094 48.054688 37.886719 L 48.054688 42.179688 L 51.871094 42.179688 L 51.871094 37.847656 C 57.078125 38.648438 61.179688 42.71875 62.019531 47.921875 L 57.707031 47.921875 L 57.707031 51.734375 Z M 62.019531 51.734375 "/>`;
export const COLLAPSE_ICON = `<svg viewBox="0 0 100 100" width="8" height="8" class="right-triangle"><path fill="currentColor" stroke="currentColor" d="M94.9,20.8c-1.4-2.5-4.1-4.1-7.1-4.1H12.2c-3,0-5.7,1.6-7.1,4.1c-1.3,2.4-1.2,5.2,0.2,7.6L43.1,88c1.5,2.3,4,3.7,6.9,3.7 s5.4-1.4,6.9-3.7l37.8-59.6C96.1,26,96.2,23.2,94.9,20.8L94.9,20.8z"></path></svg>`;
82 changes: 82 additions & 0 deletions src/flashcard-modal.ts
@@ -0,0 +1,82 @@
import { Modal, App } from "obsidian";
import type SRPlugin from "./main";
import { BasicCard, ClozeCard } from "./main";

enum UserResponse {
ShowAnswer,
ReviewEasy,
ReviewGood,
ReviewHard,
Skip,
}

export class FlashcardModal extends Modal {
private plugin: SRPlugin;
private answerBtn: HTMLElement;
private flashcardView: HTMLElement;
private fileLinkView: HTMLElement;
private contextView: HTMLElement;
private currentCard: BasicCard | ClozeCard;

constructor(app: App, plugin: SRPlugin) {
super(app);

this.plugin = plugin;

this.titleEl.setText("Queue");
this.modalEl.style.height = "80%";
this.modalEl.style.width = "40%";

this.contentEl.style.position = "relative";
this.contentEl.style.height = "92%";

this.fileLinkView = createDiv("link");
this.fileLinkView.setText("Open file");
this.contentEl.appendChild(this.fileLinkView);

this.contextView = document.createElement("div");
this.contentEl.appendChild(this.contextView);

this.flashcardView = document.createElement("div");
this.contentEl.appendChild(this.flashcardView);

this.answerBtn = document.createElement("div");
this.answerBtn.setAttribute("id", "show-answer");
this.answerBtn.setText("Show Answer");
this.contentEl.appendChild(this.answerBtn);
}

onOpen() {
document.body.onkeypress = (e) => {
if (e.code === "Space")
this.processResponse(UserResponse.ShowAnswer);
};

this.titleEl.setText(
`Queue - ${
this.plugin.newFlashcards.length +
this.plugin.scheduledFlashcards.length
}`
);

if (this.plugin.newFlashcards.length > 0) {
this.currentCard = this.plugin.newFlashcards[0];
this.flashcardView.setText(this.currentCard.front);
} else if (this.plugin.scheduledFlashcards.length > 0) {
}

this.contextView.setText(this.currentCard.context);
this.fileLinkView.addEventListener("click", (_) => {
this.close();
this.plugin.app.workspace.activeLeaf.openFile(
this.currentCard.note
);
});
}

onClose() {}

processResponse(response: UserResponse) {
this.flashcardView.setText(this.currentCard.back);
}
}
59 changes: 57 additions & 2 deletions src/main.ts
@@ -1,12 +1,13 @@
import { Notice, Plugin, addIcon, TFile } from "obsidian";
import * as graph from "pagerank.js";
import { SRSettings, SRSettingTab, DEFAULT_SETTINGS } from "./settings";
import { ReviewQueueListView } from "./sidebar";
import { FlashcardModal } from "./flashcard-modal";
import { ReviewQueueListView, REVIEW_QUEUE_VIEW_TYPE } from "./sidebar";
import {
CROSS_HAIRS_ICON,
SCHEDULING_INFO_REGEX,
YAML_FRONT_MATTER_REGEX,
REVIEW_QUEUE_VIEW_TYPE,
REMNOTE_STYLE_REGEX,
} from "./constants";

interface PluginData {
Expand All @@ -33,6 +34,21 @@ enum ReviewResponse {
Hard,
}

interface Card {
dueUnix?: number;
ease?: number;
interval?: number;
context: string;
note: TFile;
}

export interface BasicCard extends Card {
front: string;
back: string;
}

export interface ClozeCard extends Card {}

export default class SRPlugin extends Plugin {
private statusBar: HTMLElement;
private reviewQueueView: ReviewQueueListView;
Expand All @@ -45,6 +61,10 @@ export default class SRPlugin extends Plugin {
private pageranks: Record<string, number> = {};
private dueNotesCount: number = 0;

public newFlashcards: (BasicCard | ClozeCard)[] = [];
public scheduledFlashcards: (BasicCard | ClozeCard)[] = [];
public dueFlashcardsCount: number = 0;

async onload() {
await this.loadPluginData();

Expand Down Expand Up @@ -166,6 +186,10 @@ export default class SRPlugin extends Plugin {
this.pageranks = {};
this.dueNotesCount = 0;

this.newFlashcards = [];
this.scheduledFlashcards = [];
this.dueFlashcardsCount = 0;

let now = Date.now();
for (let note of notes) {
if (this.incomingLinks[note.path] == undefined)
Expand Down Expand Up @@ -195,6 +219,11 @@ export default class SRPlugin extends Plugin {
let tags = fileCachedData.tags || [];
let shouldIgnore = true;
for (let tagObj of tags) {
if (tagObj.tag == "#flashcards") {
await this.findFlashcards(note);
break;
}

if (this.data.settings.tagsToReview.includes(tagObj.tag)) {
shouldIgnore = false;
break;
Expand Down Expand Up @@ -250,6 +279,8 @@ export default class SRPlugin extends Plugin {

this.statusBar.setText(`Review: ${this.dueNotesCount} due`);
this.reviewQueueView.redraw();

new FlashcardModal(this.app, this).open();
}

async saveReviewResponse(note: TFile, response: ReviewResponse) {
Expand Down Expand Up @@ -410,6 +441,30 @@ export default class SRPlugin extends Plugin {
new Notice("You're done for the day :D.");
}

async findFlashcards(note: TFile) {
let fileText = await this.app.vault.read(note);

for (let match of fileText.matchAll(REMNOTE_STYLE_REGEX)) {
let cardObj: BasicCard = {
front: match[1],
back: match[2],
context: "write > context > function",
note,
};

// note has scheduling information
if (match[3]) {
cardObj.dueUnix = Number.parseInt(match[3]);
cardObj.ease = Number.parseInt(match[4]);
cardObj.interval = Number.parseInt(match[5]);

this.scheduledFlashcards.push(cardObj);
} else {
this.newFlashcards.push(cardObj);
}
}
}

async loadPluginData() {
this.data = Object.assign({}, DEFAULT_DATA, await this.loadData());
}
Expand Down
4 changes: 3 additions & 1 deletion src/sidebar.ts
@@ -1,6 +1,8 @@
import { ItemView, WorkspaceLeaf, Menu, TFile } from "obsidian";
import type SRPlugin from "./main";
import { COLLAPSE_ICON, REVIEW_QUEUE_VIEW_TYPE } from "./constants";
import { COLLAPSE_ICON } from "./constants";

export const REVIEW_QUEUE_VIEW_TYPE = "review-queue-list-view";

export class ReviewQueueListView extends ItemView {
private plugin: SRPlugin;
Expand Down
16 changes: 16 additions & 0 deletions styles.css
Expand Up @@ -2,4 +2,20 @@
width: 100%;
text-align: center;
margin-top: 16px;
}

.link {
color: blue;
text-decoration: underline;
cursor: pointer;
}

#show-answer {
height: 48px;
line-height: 48px;
width: 100%;
text-align: center;
position: absolute;
bottom: 0;
backdrop-filter: invert(4%);
}
4 changes: 2 additions & 2 deletions tsconfig.json
Expand Up @@ -4,7 +4,7 @@
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
"target": "es5",
"target": "esnext",
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
Expand All @@ -13,7 +13,7 @@
"dom",
"es5",
"scripthost",
"es2015"
"esnext"
]
},
"include": [
Expand Down

0 comments on commit a4c2fd6

Please sign in to comment.