Skip to content

Commit

Permalink
refactor: add proper reactivity for deleting and creating cards
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianWoelki committed Jul 5, 2024
1 parent 089c6f3 commit 94b8b4c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 20 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ Things to do before release:
- [x] Add create modal for creating decks
- [x] Add ribbon icon which opens the recall view
- [x] Add data integration
- [ ] Add proper reactivity for deleting and creating a card
- [ ] Add settings view for customizing Anki algorithm parameters
- [ ] Test and adapt to mobile experience

Expand Down
28 changes: 27 additions & 1 deletion src/ui/modals/edit-cards-modal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Modal } from 'obsidian';
import { EditItemEvent } from 'src/data/event/events';
import { DeleteItemEvent, EditItemEvent } from 'src/data/event/events';
import BetterRecallPlugin from '../../main';
import { ButtonsBarComponent } from '../components/ButtonsBarComponent';
import { Deck } from 'src/data/deck';
Expand Down Expand Up @@ -28,6 +28,28 @@ export class EditCardsModal extends Modal {
this.plugin
.getEventEmitter()
.on('editItem', this.handleEditItem.bind(this));
this.plugin.getEventEmitter().on('addItem', this.handleAddItem.bind(this));
this.plugin
.getEventEmitter()
.on('deleteItem', this.handleDeleteItem.bind(this));
}

private handleDeleteItem({ payload }: DeleteItemEvent): void {
if (!payload) {
return;
}

const { deletedItem } = payload;

const cardEl = this.contentEl.querySelector(
`[${cardAttributes.cardId}="${deletedItem.id}"]`,
);
cardEl?.remove();
}

private handleAddItem(): void {
this.contentEl.empty();
this.render();
}

private handleEditItem({ payload }: EditItemEvent): void {
Expand Down Expand Up @@ -83,6 +105,10 @@ export class EditCardsModal extends Modal {
this.plugin
.getEventEmitter()
.off('editItem', this.handleEditItem.bind(this));
this.plugin.getEventEmitter().off('addItem', this.handleAddItem.bind(this));
this.plugin
.getEventEmitter()
.off('deleteItem', this.handleDeleteItem.bind(this));
this.plugin.decksManager.save();
this.contentEl.empty();
}
Expand Down
101 changes: 83 additions & 18 deletions src/ui/views/decks-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ const rowAttributes = {
plain: 'data-new-cards-count',
attr: '[data-new-cards-count]',
},
learnCardsCount: {
plain: 'data-learn-cards-count',
attr: '[data-learn-cards-count]',
},
dueCardsCount: {
plain: 'data-due-cards-count',
attr: '[data-due-cards-count]',
},
};

export class DecksView extends RecallSubView {
Expand All @@ -33,6 +41,9 @@ export class DecksView extends RecallSubView {
.getEventEmitter()
.on('editDeck', this.handleEditDeck.bind(this));
this.plugin.getEventEmitter().on('addItem', this.handleAddItem.bind(this));
this.plugin
.getEventEmitter()
.on('deleteItem', this.handleDeleteItem.bind(this));
}

public render(): void {
Expand Down Expand Up @@ -66,41 +77,84 @@ export class DecksView extends RecallSubView {
deckNameEl.title = deck.getDescription();
}

private handleDeleteItem({ payload }: AddItemEvent): void {
if (!payload) {
return;
}

const { deckId } = payload;

const deckRowEl = this.getDeckRowEl(deckId);
if (!deckRowEl) {
return;
}

this.refreshNewCardsCount(deckId, deckRowEl);
}

private handleAddItem({ payload }: AddItemEvent): void {
if (!payload) {
return;
}

const { deckId } = payload;

// Update cards count in `new cards` column.
const deckRowEl = this.getDeckRowEl(deckId);
if (!deckRowEl) {
return;
}

const newCardsCountEl = this.getNewCardsCountEl(deckRowEl);
if (!newCardsCountEl) {
this.refreshNewCardsCount(deckId, deckRowEl);
this.refreshLearnCardsCount(deckId, deckRowEl);
this.refreshDueCardsCount(deckId, deckRowEl);
}

private refreshDueCardsCount(deckId: string, deckRowEl: HTMLElement): void {
const cardsCountEl = this.getDueCardsCountEl(deckRowEl);
if (!cardsCountEl) {
return;
}

const currentCountValue = newCardsCountEl.getAttribute(
rowAttributes.newCardsCount.plain,
);
if (!currentCountValue) {
const cardsCount =
this.plugin.decksManager.getDecks()[deckId].dueCards.length;
this.updateCount(cardsCountEl, cardsCount, DUE_CARDS_COLOR);
}

private refreshLearnCardsCount(deckId: string, deckRowEl: HTMLElement): void {
const cardsCountEl = this.getLearnCardsCountEl(deckRowEl);
if (!cardsCountEl) {
return;
}

const currentCount = parseInt(currentCountValue);
const newCount = currentCount + 1;
if (newCount >= 0) {
newCardsCountEl.addClass(NEW_CARDS_COLOR);
const cardsCount =
this.plugin.decksManager.getDecks()[deckId].learnCards.length;
this.updateCount(cardsCountEl, cardsCount, LEARN_CARDS_COLOR);
}

private refreshNewCardsCount(deckId: string, deckRowEl: HTMLElement): void {
const cardsCountEl = this.getNewCardsCountEl(deckRowEl);
if (!cardsCountEl) {
return;
}
newCardsCountEl.setText(String(newCount));
newCardsCountEl.setAttribute(
rowAttributes.newCardsCount.plain,
String(newCount),
);

const cardsCount =
this.plugin.decksManager.getDecks()[deckId].newCards.length;
this.updateCount(cardsCountEl, cardsCount, NEW_CARDS_COLOR);
}

private updateCount(
el: HTMLElement,
cardsCount: number,
className: string,
): void {
if (cardsCount > 0) {
if (!el.hasClass(className)) {
el.addClass(className);
}
} else {
el.removeClass(className);
}
el.setText(String(cardsCount));
}

private getDeckRowEl(deckId: string): HTMLElement | null {
Expand All @@ -111,6 +165,14 @@ export class DecksView extends RecallSubView {
return deckRowEl.querySelector(rowAttributes.newCardsCount.attr);
}

private getLearnCardsCountEl(deckRowEl: HTMLElement): HTMLElement | null {
return deckRowEl.querySelector(rowAttributes.learnCardsCount.attr);
}

private getDueCardsCountEl(deckRowEl: HTMLElement): HTMLElement | null {
return deckRowEl.querySelector(rowAttributes.dueCardsCount.attr);
}

private handleDeckRowMouseEnter(event: MouseEvent): void {
event.preventDefault();
event.stopPropagation();
Expand Down Expand Up @@ -181,12 +243,12 @@ export class DecksView extends RecallSubView {
});
deckRowEl.createEl('td', {
text: `${learnCardsLength}`,
attr: { 'data-learn-cards-count': learnCardsLength },
attr: { [rowAttributes.learnCardsCount.plain]: learnCardsLength },
cls: learnCardsLength > 0 ? LEARN_CARDS_COLOR : '',
});
deckRowEl.createEl('td', {
text: `${dueCardsLength}`,
attr: { 'data-due-cards-count': dueCardsLength },
attr: { [rowAttributes.dueCardsCount.plain]: dueCardsLength },
cls: dueCardsLength > 0 ? DUE_CARDS_COLOR : '',
});
});
Expand Down Expand Up @@ -248,6 +310,9 @@ export class DecksView extends RecallSubView {
.getEventEmitter()
.off('editDeck', this.handleEditDeck.bind(this));
this.plugin.getEventEmitter().off('addItem', this.handleAddItem.bind(this));
this.plugin
.getEventEmitter()
.off('deleteItem', this.handleDeleteItem.bind(this));

const deckRowEls = this.rootEl.querySelectorAll('.better-recall-deck');
deckRowEls.forEach((deckRowEl) => {
Expand Down

0 comments on commit 94b8b4c

Please sign in to comment.