Skip to content

Commit

Permalink
Calendar: Split view model files into separate directory
Browse files Browse the repository at this point in the history
calendar-model/ was getting crowded.
  • Loading branch information
SLaks committed Oct 13, 2024
1 parent 561b237 commit a16b846
Show file tree
Hide file tree
Showing 16 changed files with 55 additions and 52 deletions.
37 changes: 1 addition & 36 deletions src/calendar-model/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

_For more details, see the [design doc](https://docs.google.com/document/d/17fsv4TVKUVNfSnh5wMu_FyDUKRkrtQo76KVLsa9QA1g/edit)_

This package declares the model and view-model that power the rest of the UI (loosely following the MVVM pattern).
This directory declares the model classes that specify how leinings are grouped and displayed (loosely following the MVVM pattern). It is primarily consumed by the view-model/ directory.

## Model Structure

Expand All @@ -16,38 +16,3 @@ We represent leinings as a hierarchical structure:
- For example, we use a separate `LeiningRun` for מפטיר (when not the end of the פרשה), for שביעי when three ספרי תורה are used, and for the הפטרה.
- But we don't declare a separate `LeiningRun` for minor skips like תענית ציבור.
- In particular, a הפטרה is _always_ a single `LeiningRun` (even שבת שובה).

## View Model

`ScrollViewModel` wraps the above model objects and calculates exactly what the scroll (the main view) should display.

This code takes the page URL (specifying a single `LeiningRun`) as input and calculates the pages (different for יום טוב) and עלייות to display in the scroll.

This class is mostly immutable (jumping to a new run requires creating a new instance), but tracks loaded pages internally to load more pages as the user scrolls.

The UI layer consumes the output of this class to render UI.

This class (and associated helper functions) has several purposes:

- Select the set of pages to render
- Fetch pages as the user scrolls
- Generate titles and navigation links for the header UI
- Calculate עלייה labels to show alongside the scroll

### Page Indices

The base `ScrollViewModel` class deals in abstract content indices – an index into a contiguous range of rendered content.

`FullScrollViewModel` simply renders every page of a scroll (this is used to render all of חומש for regular פרשיות, and to render מגילות). Therefore, it translates content indices directly to page numbers within the scroll.

`HolidayViewModel` renders only the pages that contain a particular day's leining. When multiple ספרי תורה are used, it will also render a message between those pages indicating how many עמודים are skipped between leinings (this can be useful to plan which ספרי תורה to scroll where, especially when sharing between multiple Minyanim).

Therefore, it maps the contiguous content indices to whatever pages from the scroll are rendered in this view, including the skip messages.

This logic is implemented in the `pageNumberFromContentIndex()` and `contentIndexFromPageNumber()`, which convert back and forth between these two indices. `pageNumberFromContentIndex()` can return either a page number or a message to render for that particular content index.

Note: Page numbers (which correspond to JSON page files and values in the tables of contents) are 1-based, whereas content indices are 0-based.

These methods (and the array in `HolidayViewModel` that backs them) specify exactly what gets displayed when a יום טוב is selected.

Tip: We could easily change this to allow a single `ScrollViewModel` to contain multiple scrolls as well. This would let us show the הפטרה for יום טוב by scrolling down past מפטיר, rather than clicking a navigation button. To do this, `pageNumber` in these two methods would change to a tuple of page number and scroll.
2 changes: 1 addition & 1 deletion src/calendar-model/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from '@hebcal/leyning'
import { invert, fromISODateString, toISODateString, last } from './utils.ts'
import { toLeiningAliyah, toAliyahIndex } from './hebcal-conversions.ts'
import { isSameRun } from './display.ts'
import { isSameRun } from './ref-utils.ts'

type PartialLeiningRun = Omit<LeiningRun, 'id' | 'scroll' | 'leining'>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/** @fileoverview Contains logic to build strings for display. */

import { physicalLocationFromRef } from '../location.ts'
import { Ref } from '../ref.ts'
import { LeiningRun, LeiningAliyah } from './model-types.ts'
Expand Down
2 changes: 1 addition & 1 deletion src/components/Line.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RenderedLineInfo } from '../calendar-model/scroll-view-model'
import { RenderedLineInfo } from '../view-model/scroll-view-model'
import displayRange from '../display-range'
import textFilter from '../text-filter'

Expand Down
2 changes: 1 addition & 1 deletion src/components/Page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Line from './Line.ts'
import { RenderedPageInfo } from '../calendar-model/scroll-view-model.ts'
import { RenderedPageInfo } from '../view-model/scroll-view-model.ts'

type Verse = {
book: number
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
RenderedMessageInfo,
RenderedPageInfo,
ScrollViewModel,
} from './calendar-model/scroll-view-model.ts'
} from './view-model/scroll-view-model.ts'
import { LeiningGenerator } from './calendar-model/generator.ts'

declare function gtag(
Expand Down
40 changes: 40 additions & 0 deletions src/view-model/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# View Model

This directory declares the view models that specify exactly what each part of the UI should display (loosely following the MVVM pattern).

They wrap the model types from calendar-model/ and decide exactly what gets displayed.

## ScrollViewModel

`ScrollViewModel` wraps the model objects and calculates exactly what the scroll (the main view) should display.

This code takes the page URL (specifying a single `LeiningRun`) as input and calculates the pages (different for יום טוב) and עלייות to display in the scroll.

This class is mostly immutable (jumping to a new run requires creating a new instance), but tracks loaded pages internally to load more pages as the user scrolls.

The UI layer consumes the output of this class to render UI.

This class (and associated helper functions) has several purposes:

- Select the set of pages to render
- Fetch pages as the user scrolls
- Generate titles and navigation links for the header UI
- Calculate עלייה labels to show alongside the scroll

### Page Indices

The base `ScrollViewModel` class deals in abstract content indices &ndash; an index into a contiguous range of rendered content.

`FullScrollViewModel` simply renders every page of a scroll (this is used to render all of חומש for regular פרשיות, and to render מגילות). Therefore, it translates content indices directly to page numbers within the scroll.

`HolidayViewModel` renders only the pages that contain a particular day's leining. When multiple ספרי תורה are used, it will also render a message between those pages indicating how many עמודים are skipped between leinings (this can be useful to plan which ספרי תורה to scroll where, especially when sharing between multiple Minyanim).

Therefore, it maps the contiguous content indices to whatever pages from the scroll are rendered in this view, including the skip messages.

This logic is implemented in the `pageNumberFromContentIndex()` and `contentIndexFromPageNumber()`, which convert back and forth between these two indices. `pageNumberFromContentIndex()` can return either a page number or a message to render for that particular content index.

Note: Page numbers (which correspond to JSON page files and values in the tables of contents) are 1-based, whereas content indices are 0-based.

These methods (and the array in `HolidayViewModel` that backs them) specify exactly what gets displayed when a יום טוב is selected.

Tip: We could easily change this to allow a single `ScrollViewModel` to contain multiple scrolls as well. This would let us show the הפטרה for יום טוב by scrolling down past מפטיר, rather than clicking a navigation button. To do this, `pageNumber` in these two methods would change to a tuple of page number and scroll.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/** @fileoverview This file tests both Aliyah labelling and run calculation in HolidayViewModel. */

import test from 'ava'
import { LeiningGenerator } from './generator.ts'
import { UserSettings } from './user-settings.ts'
import { LeiningGenerator } from '../calendar-model/generator.ts'
import { UserSettings } from '../calendar-model/user-settings.ts'
import { RenderedEntry, ScrollViewModel } from './scroll-view-model.ts'
import { renderLine } from './test-utils.ts'

Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Ref } from '../ref.ts'
import { compareRefs } from './display.ts'
import { LeiningRun, LeiningAliyah } from './model-types.ts'
import { compareRefs } from '../calendar-model/ref-utils.ts'
import { LeiningRun, LeiningAliyah } from '../calendar-model/model-types.ts'

export class AliyahLabeller {
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import test from 'ava'
import { LeiningGenerator } from './generator.ts'
import { UserSettings } from './user-settings.ts'
import { LeiningGenerator } from '../calendar-model/generator.ts'
import { UserSettings } from '../calendar-model/user-settings.ts'
import { RenderedEntry, ScrollViewModel } from './scroll-view-model.ts'
import { renderLine } from './test-utils.ts'

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { LineType } from '../components/Page.ts'
import { Ref, RefWithScroll } from '../ref.ts'
import { LeiningGenerator } from './generator.ts'
import { LeiningRun, LeiningRunType } from './model-types.ts'
import { LeiningGenerator } from '../calendar-model/generator.ts'
import { LeiningRun, LeiningRunType } from '../calendar-model/model-types.ts'
import IntegerIterator from '../integer-iterator.ts'
import { getPageCount, physicalLocationFromRef } from '../location.ts'
import { HDate } from '@hebcal/core'
import { containsRef } from './display.ts'
import { last, range } from './utils.ts'
import { containsRef } from '../calendar-model/ref-utils.ts'
import { last, range } from '../calendar-model/utils.ts'
import { AliyahLabeller } from './aliyah-labeller.ts'

/** Information to render a single page from a scroll. */
Expand Down
File renamed without changes.

0 comments on commit a16b846

Please sign in to comment.