sync local and remote display settings

This commit is contained in:
Jason Wall 2020-08-07 20:19:39 -04:00
parent 573b9dc29d
commit 25ed414aba
15 changed files with 471 additions and 323 deletions

View File

@ -10,7 +10,7 @@ trim_trailing_whitespace = true
[*.ts] [*.ts]
quote_type = single quote_type = single
max_line_length = 140 max_line_length = 120
end_of_line = lf end_of_line = lf
# this file has a need for arbitrarily long lines, so we exempt this here. # this file has a need for arbitrarily long lines, so we exempt this here.

View File

@ -1,11 +1,11 @@
{ {
"targets": { "targets": {
"dynamicbible-7c6cf": { "dynamic-bible-testing": {
"hosting": { "hosting": {
"db": [ "db": [
"dynamicbible-7c6cf" "dynamic-bible-testing"
] ]
} }
} }
} }
} }

View File

@ -1,6 +1,7 @@
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { AppService } from './services/app.service'; import { AppService } from './services/app.service';
import { NavService } from './services/nav.service'; import { NavService } from './services/nav.service';
import { StorageService } from './services/storage.service';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout'; import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
import { map, shareReplay } from 'rxjs/operators'; import { map, shareReplay } from 'rxjs/operators';
@ -16,20 +17,15 @@ import { SubscriberComponent } from './common/components/subscriber.component';
styleUrls: ['./app.component.scss'], styleUrls: ['./app.component.scss'],
}) })
export class AppComponent extends SubscriberComponent implements AfterViewInit { export class AppComponent extends SubscriberComponent implements AfterViewInit {
savedPages$ = this.appService.select((state) => state.savedPages); savedPages$ = this.appService.select((state) => state.savedPages.value);
mainPages$ = this.appService.select((state) => state.mainPages); mainPages$ = this.appService.select((state) => state.mainPages);
fontSize$ = this.appService.select( fontSize$ = this.appService.select((state) => state.displaySettings.value.cardFontSize + 'pt');
(state) => state.displaySettings.fontSize + 'pt' cardFont$ = this.appService.select((state) => state.displaySettings.value.cardFontFamily);
);
cardFont$ = this.appService.select((state) => state.displaySettings.cardFont);
displaySettings$ = this.appService.select((state) => state.displaySettings);
isHandset$: Observable<boolean> = this.breakpointObserver isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
.observe(Breakpoints.Handset) map((result) => result.matches),
.pipe( shareReplay()
map((result) => result.matches), );
shareReplay()
);
@ViewChild('drawer') public sidenav: MatSidenav; @ViewChild('drawer') public sidenav: MatSidenav;
@ViewChild('settings') public settings: MatSidenav; @ViewChild('settings') public settings: MatSidenav;
@ -37,26 +33,28 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
constructor( constructor(
private appService: AppService, private appService: AppService,
private navService: NavService, private navService: NavService,
private storageService: StorageService,
private breakpointObserver: BreakpointObserver, private breakpointObserver: BreakpointObserver,
private dialog: MatDialog private dialog: MatDialog
) { ) {
super(); super();
this.appService.initSavedPages(); this.storageService.initSavedPages();
this.appService.initDisplaySettings(); this.storageService.initDisplaySettings();
//#region handle local storage //#region Handle recieving updates from firebase
this.addSubscription( this.addSubscription(
this.displaySettings$.subscribe((settings) => { // when the user object changes, respond
this.appService.saveSettingsApi(settings); this.appService
}) // this should trigger only once, when the user logs in.
); .select((state) => state.user)
.subscribe((user) => {
this.addSubscription( if (!user) {
this.savedPages$.subscribe((savedPages) => { return; // if the user is null, avoid this.
this.appService.savePagesApi(savedPages); }
}) this.storageService.initRemote(user);
})
); );
//#endregion //#endregion
@ -73,10 +71,7 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
this.addSubscription( this.addSubscription(
this.cardFont$.subscribe((family) => { this.cardFont$.subscribe((family) => {
if (family) { if (family) {
document.documentElement.style.setProperty( document.documentElement.style.setProperty('--card-font-family', family);
'--card-font-family',
family
);
} }
}) })
); );
@ -93,7 +88,7 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
} }
updatePage() { updatePage() {
this.appService.updatePage(); this.appService.updateSavedPage();
} }
createNote() { createNote() {

View File

@ -1,29 +1,34 @@
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { NgxMdModule } from 'ngx-md'; import { NgxMdModule } from 'ngx-md';
import { AngularFireModule } from '@angular/fire';
import { FirebaseConfig } from './constants';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFireDatabaseModule } from '@angular/fire/database';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SearchPage } from './search/components/search-page/search.page'; import { SearchPage } from './search/components/search-page/search.page';
import { PassageCardComponent } from './search/components/passage/passage-card.component';
import { WordsCardComponent } from './search/components/words/words-card.component';
import { NoteCardComponent } from './search/components/note/note-card.component';
import { SettingsComponent } from './common/components/settings/settings.component';
import { StrongsComponent } from './search/components/strongs/strongs.component';
import { StrongsCardComponent } from './search/components/strongs/card/strongs-card.component';
import { StrongsModalComponent } from './search/components/strongs/modal/strongs-modal.component';
import { AddToPageModalComponent } from './search/components/saved-page/add-to-page-modal/add-to-page-modal.component'; import { AddToPageModalComponent } from './search/components/saved-page/add-to-page-modal/add-to-page-modal.component';
import { PageEditModalComponent } from './search/components/saved-page/page-edit-modal/page-edit-modal.component'; import { PageEditModalComponent } from './search/components/saved-page/page-edit-modal/page-edit-modal.component';
import { NoteEditModalComponent } from './search/components/note/edit-modal/note-edit-modal.component'; import { NoteEditModalComponent } from './search/components/note/edit-modal/note-edit-modal.component';
import { VersePickerModalComponent } from './search/components/verse-picker-modal/verse-picker-modal.component'; import { VersePickerModalComponent } from './search/components/verse-picker-modal/verse-picker-modal.component';
import { SettingsComponent } from './common/components/settings/settings.component';
import { PassageCardComponent } from './search/components/passage/passage-card.component';
import { WordsCardComponent } from './search/components/words/words-card.component';
import { NoteCardComponent } from './search/components/note/note-card.component';
import { StrongsComponent } from './search/components/strongs/strongs.component';
import { StrongsCardComponent } from './search/components/strongs/card/strongs-card.component';
import { StrongsModalComponent } from './search/components/strongs/modal/strongs-modal.component';
import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
@ -60,8 +65,6 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core'; import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
import { MatTreeModule } from '@angular/material/tree'; import { MatTreeModule } from '@angular/material/tree';
import { ClipboardModule } from '@angular/cdk/clipboard'; import { ClipboardModule } from '@angular/cdk/clipboard';
import { AngularFireModule } from '@angular/fire';
import { FirebaseConfig } from './constants';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -91,6 +94,8 @@ import { FirebaseConfig } from './constants';
NgxMdModule.forRoot(), NgxMdModule.forRoot(),
AngularFireModule.initializeApp(FirebaseConfig), AngularFireModule.initializeApp(FirebaseConfig),
AngularFireAuthModule,
AngularFireDatabaseModule,
MatSidenavModule, MatSidenavModule,
MatToolbarModule, MatToolbarModule,

View File

@ -1,10 +1,4 @@
import { import { EventEmitter, Output, Input, ElementRef, Component } from '@angular/core';
EventEmitter,
Output,
Input,
ElementRef,
Component,
} from '@angular/core';
import { CardItem, OpenData } from '../../models/app-state'; import { CardItem, OpenData } from '../../models/app-state';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';

View File

@ -75,7 +75,7 @@
<div class="settings-h2">Card Font Family</div> <div class="settings-h2">Card Font Family</div>
<mat-form-field appearance="fill" class="card-fonts"> <mat-form-field appearance="fill" class="card-fonts">
<mat-select <mat-select
[(value)]="cardFont" [(value)]="cardFontFamily"
(selectionChange)="cardFontSelected($event)" (selectionChange)="cardFontSelected($event)"
> >
<mat-option *ngFor="let font of fonts" [value]="font"> <mat-option *ngFor="let font of fonts" [value]="font">
@ -88,9 +88,9 @@
<div class="settings-h2">Card Font Size</div> <div class="settings-h2">Card Font Size</div>
<mat-slider <mat-slider
class="font-size-slider" class="font-size-slider"
max="32" max="24"
min="10" min="12"
step="1" step="2"
thumbLabel="true" thumbLabel="true"
(change)="cardFontSizeChanged($event)" (change)="cardFontSizeChanged($event)"
[(ngModel)]="cardFontSize" [(ngModel)]="cardFontSize"

View File

@ -8,6 +8,7 @@ import { MatSelectChange } from '@angular/material/select';
import { MatSliderChange } from '@angular/material/slider'; import { MatSliderChange } from '@angular/material/slider';
import { AngularFireAuth } from '@angular/fire/auth'; import { AngularFireAuth } from '@angular/fire/auth';
import { auth } from 'firebase/app'; import { auth } from 'firebase/app';
import { Storable } from 'src/app/models/storable';
@Component({ @Component({
selector: 'app-settings', selector: 'app-settings',
@ -17,7 +18,7 @@ import { auth } from 'firebase/app';
export class SettingsComponent extends SubscriberComponent { export class SettingsComponent extends SubscriberComponent {
displaySettings: DisplaySettings; displaySettings: DisplaySettings;
fonts: string[]; fonts: string[];
cardFont = ''; cardFontFamily = '';
cardFontSize = 10; cardFontSize = 10;
user$ = this.appService.select((state) => state.user); user$ = this.appService.select((state) => state.user);
@ -26,25 +27,30 @@ export class SettingsComponent extends SubscriberComponent {
this.fonts = CardFonts; this.fonts = CardFonts;
this.addSubscription( this.addSubscription(
this.appService.state$.subscribe((state) => { this.appService.state$.subscribe((state) => {
this.displaySettings = state.displaySettings; this.displaySettings = state.displaySettings.value;
this.cardFont = state.displaySettings.cardFont; this.cardFontFamily = state.displaySettings.value.cardFontFamily;
this.cardFontSize = state.displaySettings.value.cardFontSize;
}) })
); );
this.addSubscription( this.addSubscription(
this.authService.authState.subscribe((user) => { this.authService.authState.subscribe((user) => {
this.appService.setUser({ if (user) {
uid: user.uid, this.appService.setUser({
displayName: user.displayName, uid: user.uid,
providerId: user.providerId, displayName: user.displayName,
email: user.email, providerId: user.providerId,
}); email: user.email,
});
}
}) })
); );
} }
login() { login() {
this.authService.signInWithPopup(new auth.GoogleAuthProvider()); this.authService.signInWithPopup(new auth.GoogleAuthProvider()).then((cred) => {
console.log('Authenticated.');
});
} }
logout() { logout() {
this.authService.signOut(); this.authService.signOut();
@ -65,68 +71,86 @@ export class SettingsComponent extends SubscriberComponent {
//#region Search Settings //#region Search Settings
toggleStrongsAsModal(toggle: MatSlideToggleChange) { toggleStrongsAsModal(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
showStrongsAsModal: toggle.checked, ...this.displaySettings,
}); showStrongsAsModal: toggle.checked,
})
);
} }
toggleAppendCardToBottom(toggle: MatSlideToggleChange) { toggleAppendCardToBottom(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
appendCardToBottom: toggle.checked, ...this.displaySettings,
}); appendCardToBottom: toggle.checked,
})
);
} }
toggleInsertCardNextToItem(toggle: MatSlideToggleChange) { toggleInsertCardNextToItem(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
insertCardNextToItem: toggle.checked, ...this.displaySettings,
}); insertCardNextToItem: toggle.checked,
})
);
} }
toggleClearSearchAfterQuery(toggle: MatSlideToggleChange) { toggleClearSearchAfterQuery(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
clearSearchAfterQuery: toggle.checked, ...this.displaySettings,
}); clearSearchAfterQuery: toggle.checked,
})
);
} }
toggleSyncCardsAcrossDevices(toggle: MatSlideToggleChange) { toggleSyncCardsAcrossDevices(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
syncCardsAcrossDevices: toggle.checked, ...this.displaySettings,
}); syncCardsAcrossDevices: toggle.checked,
})
);
} }
//#endregion //#endregion
//#region Passage Settings //#region Passage Settings
toggleParagraphHeadings(toggle: MatSlideToggleChange) { toggleParagraphHeadings(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
showParagraphHeadings: toggle.checked, ...this.displaySettings,
}); showParagraphHeadings: toggle.checked,
})
);
} }
toggleParagraphs(toggle: MatSlideToggleChange) { toggleParagraphs(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
showParagraphs: toggle.checked, ...this.displaySettings,
}); showParagraphs: toggle.checked,
})
);
} }
toggleVerseNumbers(toggle: MatSlideToggleChange) { toggleVerseNumbers(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
showVerseNumbers: toggle.checked, ...this.displaySettings,
}); showVerseNumbers: toggle.checked,
})
);
} }
toggleVersesOnNewLine(toggle: MatSlideToggleChange) { toggleVersesOnNewLine(toggle: MatSlideToggleChange) {
this.appService.updateDisplaySettings({ this.appService.updateDisplaySettings(
...this.displaySettings, new Storable({
showVersesOnNewLine: toggle.checked, ...this.displaySettings,
}); showVersesOnNewLine: toggle.checked,
})
);
} }
//#endregion //#endregion

View File

@ -14,13 +14,30 @@ export const CardIcons = {
Strongs: 'article', Strongs: 'article',
}; };
export const CardFonts = ['Merriweather', 'PT Sans', 'PT Serif', 'Open Sans', 'Roboto', 'Roboto Condensed', 'Inconsolata']; export const CardFonts = [
'Merriweather',
'PT Sans',
'PT Serif',
'Open Sans',
'Roboto',
'Roboto Condensed',
'Inconsolata',
];
// export const FirebaseConfig = {
// apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8',
// authDomain: 'dynamicbible-7c6cf.firebaseapp.com',
// databaseURL: 'https://dynamicbible-7c6cf.firebaseio.com',
// projectId: 'dynamicbible-7c6cf',
// storageBucket: '',
// messagingSenderId: '200739882604',
// };
export const FirebaseConfig = { export const FirebaseConfig = {
apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8', apiKey: 'AIzaSyA4b587psiOnpjbzu0t6z75A_hFksPyQkI',
authDomain: 'dynamicbible-7c6cf.firebaseapp.com', authDomain: 'dynamic-bible-testing.firebaseapp.com',
databaseURL: 'https://dynamicbible-7c6cf.firebaseio.com', databaseURL: 'https://dynamic-bible-testing.firebaseio.com',
projectId: 'dynamicbible-7c6cf', projectId: 'dynamic-bible-testing',
storageBucket: '', storageBucket: 'dynamic-bible-testing.appspot.com',
messagingSenderId: '200739882604', messagingSenderId: '813845246474',
appId: '1:813845246474:web:6dccfa057b6cb3067565f3',
}; };

View File

@ -1,12 +1,14 @@
import { IStorable } from './storable';
export interface AppState { export interface AppState {
readonly currentPage: SavedPage; readonly currentPage: SavedPage;
readonly savedPages: readonly SavedPage[]; readonly savedPages: IStorable<readonly SavedPage[]>;
readonly savedPagesLoaded: boolean; readonly savedPagesLoaded: boolean;
readonly mainPages: readonly Page[]; readonly mainPages: readonly Page[];
readonly cards: readonly CardItem[]; readonly cards: readonly CardItem[];
readonly autocomplete: readonly string[]; readonly autocomplete: readonly string[];
readonly error: Error; readonly error: Error;
readonly displaySettings: DisplaySettings; readonly displaySettings: IStorable<DisplaySettings>;
readonly cardIcons: CardIcons; readonly cardIcons: CardIcons;
readonly user: User; readonly user: User;
} }
@ -33,12 +35,14 @@ export interface CardIcons {
export interface DisplaySettings { export interface DisplaySettings {
readonly showStrongsAsModal: boolean; readonly showStrongsAsModal: boolean;
readonly appendCardToBottom: boolean; readonly appendCardToBottom: boolean;
readonly insertCardNextToItem: boolean; readonly insertCardNextToItem: boolean;
readonly clearSearchAfterQuery: boolean; readonly clearSearchAfterQuery: boolean;
readonly fontSize: number; readonly cardFontSize: number;
readonly cardFont: string; readonly cardFontFamily: string;
readonly showVersesOnNewLine: boolean; readonly showVersesOnNewLine: boolean;
readonly showVerseNumbers: boolean; readonly showVerseNumbers: boolean;

View File

@ -0,0 +1,14 @@
export interface IStorable<T> {
readonly createdOn: string;
readonly value: T;
}
export class Storable<T> implements IStorable<T> {
constructor(v: T) {
this.value = v;
this.createdOn = new Date().toISOString();
}
createdOn: string;
value: T;
}

View File

@ -15,30 +15,18 @@ import { StrongsModalComponent } from '../strongs/modal/strongs-modal.component'
export class PassageCardComponent extends CardComponent implements OnInit { export class PassageCardComponent extends CardComponent implements OnInit {
ref: BibleReference; ref: BibleReference;
showParagraphs$ = this.appService.select( showParagraphs$ = this.appService.select((state) => state.displaySettings.value.showParagraphs);
(state) => state.displaySettings.showParagraphs
);
showParagraphHeadings$ = this.appService.select( showParagraphHeadings$ = this.appService.select(
(state) => (state) => state.displaySettings.value.showParagraphHeadings && state.displaySettings.value.showParagraphs
state.displaySettings.showParagraphHeadings &&
state.displaySettings.showParagraphs
);
showVersesOnNewLine$ = this.appService.select(
(state) => state.displaySettings.showVersesOnNewLine
);
showVerseNumbers$ = this.appService.select(
(state) => state.displaySettings.showVerseNumbers
); );
showVersesOnNewLine$ = this.appService.select((state) => state.displaySettings.value.showVersesOnNewLine);
showVerseNumbers$ = this.appService.select((state) => state.displaySettings.value.showVerseNumbers);
displaySettings$ = this.appService.select((state) => state.displaySettings); displaySettings$ = this.appService.select((state) => state.displaySettings.value);
@ViewChild('passage') passageElement: ElementRef; @ViewChild('passage') passageElement: ElementRef;
constructor( constructor(protected elementRef: ElementRef, private appService: AppService, public dialog: MatDialog) {
protected elementRef: ElementRef,
private appService: AppService,
public dialog: MatDialog
) {
super(elementRef, dialog); super(elementRef, dialog);
this.icon$ = appService.select((state) => state.cardIcons.passage); this.icon$ = appService.select((state) => state.cardIcons.passage);
} }
@ -54,14 +42,9 @@ export class PassageCardComponent extends CardComponent implements OnInit {
} }
next() { next() {
const lastVerseForEnd = this.ref.section.book.chapters[ const lastVerseForEnd = this.ref.section.book.chapters[this.ref.section.end.chapter];
this.ref.section.end.chapter
];
if ( if (this.ref.section.end.verse !== 0 && this.ref.section.end.verse !== lastVerseForEnd) {
this.ref.section.end.verse !== 0 &&
this.ref.section.end.verse !== lastVerseForEnd
) {
this.ref.section.end.chapter = this.ref.section.end.chapter; this.ref.section.end.chapter = this.ref.section.end.chapter;
} else { } else {
this.ref.section.end.chapter = this.ref.section.end.chapter + 1; this.ref.section.end.chapter = this.ref.section.end.chapter + 1;
@ -69,9 +52,7 @@ export class PassageCardComponent extends CardComponent implements OnInit {
this.ref.section.start.chapter = this.ref.section.end.chapter; this.ref.section.start.chapter = this.ref.section.end.chapter;
this.ref.section.start.verse = 1; this.ref.section.start.verse = 1;
this.ref.section.end.verse = this.ref.section.book.chapters[ this.ref.section.end.verse = this.ref.section.book.chapters[this.ref.section.end.chapter];
this.ref.section.end.chapter
];
this.appService.updatePassage(this.cardItem, this.ref); this.appService.updatePassage(this.cardItem, this.ref);
} }
@ -85,24 +66,19 @@ export class PassageCardComponent extends CardComponent implements OnInit {
this.ref.section.end.chapter = this.ref.section.start.chapter; this.ref.section.end.chapter = this.ref.section.start.chapter;
this.ref.section.start.verse = 1; this.ref.section.start.verse = 1;
this.ref.section.end.verse = this.ref.section.book.chapters[ this.ref.section.end.verse = this.ref.section.book.chapters[this.ref.section.end.chapter];
this.ref.section.end.chapter
];
this.appService.updatePassage(this.cardItem, this.ref); this.appService.updatePassage(this.cardItem, this.ref);
} }
expand() { expand() {
const lastVerseForEnd = this.ref.section.book.chapters[ const lastVerseForEnd = this.ref.section.book.chapters[this.ref.section.end.chapter];
this.ref.section.end.chapter
];
// if your verse is at the beginning, to go the prev chapter and add 3 verses from that // if your verse is at the beginning, to go the prev chapter and add 3 verses from that
if (this.ref.section.start.verse < 4) { if (this.ref.section.start.verse < 4) {
this.ref.section.start.chapter = this.ref.section.start.chapter - 1; this.ref.section.start.chapter = this.ref.section.start.chapter - 1;
this.ref.section.start.verse = this.ref.section.start.verse =
this.ref.section.book.chapters[this.ref.section.start.chapter] - this.ref.section.book.chapters[this.ref.section.start.chapter] - (3 - this.ref.section.start.verse);
(3 - this.ref.section.start.verse);
if (this.ref.section.start.chapter === 0) { if (this.ref.section.start.chapter === 0) {
this.ref.section.start.chapter = 1; this.ref.section.start.chapter = 1;
this.ref.section.start.verse = 1; this.ref.section.start.verse = 1;
@ -113,22 +89,15 @@ export class PassageCardComponent extends CardComponent implements OnInit {
} }
// if your verse is at the end, go to the next chapter // if your verse is at the end, go to the next chapter
if ( if (this.ref.section.end.verse === 0 || this.ref.section.end.verse + 3 > lastVerseForEnd) {
this.ref.section.end.verse === 0 ||
this.ref.section.end.verse + 3 > lastVerseForEnd
) {
this.ref.section.end.chapter = this.ref.section.end.chapter + 1; this.ref.section.end.chapter = this.ref.section.end.chapter + 1;
if (this.ref.section.end.verse === 0) { if (this.ref.section.end.verse === 0) {
this.ref.section.end.verse = 3; this.ref.section.end.verse = 3;
} else { } else {
this.ref.section.end.verse = this.ref.section.end.verse = this.ref.section.end.verse + 3 - lastVerseForEnd;
this.ref.section.end.verse + 3 - lastVerseForEnd;
} }
if ( if (this.ref.section.end.chapter === this.ref.section.book.lastChapter + 1) {
this.ref.section.end.chapter ===
this.ref.section.book.lastChapter + 1
) {
this.ref.section.end.chapter = this.ref.section.book.lastChapter; this.ref.section.end.chapter = this.ref.section.book.lastChapter;
this.ref.section.end.verse = lastVerseForEnd; this.ref.section.end.verse = lastVerseForEnd;
} }

View File

@ -9,10 +9,7 @@ import { BibleReference } from '../../../common/bible-reference';
import { VersePickerModalComponent } from '../verse-picker-modal/verse-picker-modal.component'; import { VersePickerModalComponent } from '../verse-picker-modal/verse-picker-modal.component';
import { SubscriberComponent } from '../../../common/components/subscriber.component'; import { SubscriberComponent } from '../../../common/components/subscriber.component';
import { import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
MatAutocompleteTrigger,
MatAutocomplete,
} from '@angular/material/autocomplete';
@Component({ @Component({
selector: 'app-search-page', selector: 'app-search-page',
@ -46,8 +43,7 @@ export class SearchPage extends SubscriberComponent implements OnInit {
this.addSubscription( this.addSubscription(
this.appService.state$.subscribe((state) => { this.appService.state$.subscribe((state) => {
this.savedPagedLoaded = state.savedPagesLoaded; this.savedPagedLoaded = state.savedPagesLoaded;
this.clearSearchAfterQuery = this.clearSearchAfterQuery = state.displaySettings.value.clearSearchAfterQuery;
state.displaySettings.clearSearchAfterQuery;
}) })
); );
} }
@ -65,9 +61,7 @@ export class SearchPage extends SubscriberComponent implements OnInit {
this.init(); this.init();
// subscribe to autocomplete input control's changes // subscribe to autocomplete input control's changes
this.addSubscription( this.addSubscription(
this.searchControl.valueChanges.subscribe((value: string) => this.searchControl.valueChanges.subscribe((value: string) => this.appService.getAutoComplete(value.toLowerCase()))
this.appService.getAutoComplete(value.toLowerCase())
)
); );
} }

View File

@ -15,16 +15,12 @@ export class StrongsCardComponent extends CardComponent {
asModal = false; asModal = false;
@ViewChild('strongs') strongsElement: ElementRef; @ViewChild('strongs') strongsElement: ElementRef;
constructor( constructor(protected elementRef: ElementRef, protected appService: AppService, protected dialog: MatDialog) {
protected elementRef: ElementRef,
protected appService: AppService,
protected dialog: MatDialog
) {
super(elementRef, dialog); super(elementRef, dialog);
this.icon$ = appService.select((state) => state.cardIcons.strongs); this.icon$ = appService.select((state) => state.cardIcons.strongs);
this.addSubscription( this.addSubscription(
this.appService.state$.subscribe((state) => { this.appService.state$.subscribe((state) => {
this.asModal = state.displaySettings.showStrongsAsModal; this.asModal = state.displaySettings.value.showStrongsAsModal;
}) })
); );
} }

View File

@ -28,6 +28,8 @@ import { PageTitles, PageIcons } from '../constants';
import { createStateService } from '../common/state-service'; import { createStateService } from '../common/state-service';
import { UUID } from 'angular2-uuid'; import { UUID } from 'angular2-uuid';
import { StorageMap } from '@ngx-pwa/local-storage'; import { StorageMap } from '@ngx-pwa/local-storage';
import { AngularFireDatabase } from '@angular/fire/database';
import { IStorable, Storable } from '../models/storable';
const initialState: AppState = { const initialState: AppState = {
user: null, user: null,
@ -46,7 +48,10 @@ const initialState: AppState = {
], ],
autocomplete: [], autocomplete: [],
currentPage: null, currentPage: null,
savedPages: [], savedPages: {
createdOn: new Date(0).toISOString(),
value: [],
},
savedPagesLoaded: false, savedPagesLoaded: false,
mainPages: [ mainPages: [
{ title: PageTitles.Search, icon: PageIcons.Search, route: 'search' }, { title: PageTitles.Search, icon: PageIcons.Search, route: 'search' },
@ -54,17 +59,20 @@ const initialState: AppState = {
], ],
error: null, error: null,
displaySettings: { displaySettings: {
showStrongsAsModal: false, createdOn: new Date(0).toISOString(),
appendCardToBottom: true, value: {
insertCardNextToItem: true, showStrongsAsModal: false,
clearSearchAfterQuery: true, appendCardToBottom: true,
fontSize: 12, insertCardNextToItem: true,
cardFont: 'PT Serif', clearSearchAfterQuery: true,
showVersesOnNewLine: false, cardFontSize: 12,
showVerseNumbers: false, cardFontFamily: 'PT Serif',
showParagraphs: true, showVersesOnNewLine: false,
showParagraphHeadings: true, showVerseNumbers: false,
syncCardsAcrossDevices: false, showParagraphs: true,
showParagraphHeadings: true,
syncCardsAcrossDevices: false,
},
}, },
cardIcons: { cardIcons: {
words: 'font_download', words: 'font_download',
@ -88,7 +96,7 @@ type AppAction =
} }
| { | {
type: 'UPDATE_SAVED_PAGES'; type: 'UPDATE_SAVED_PAGES';
savedPages: SavedPage[]; savedPages: IStorable<readonly SavedPage[]>;
} }
| { | {
type: 'ADD_CARD_TO_SAVED_PAGE'; type: 'ADD_CARD_TO_SAVED_PAGE';
@ -115,11 +123,11 @@ type AppAction =
} }
| { | {
type: 'UPDATE_FONT_SIZE'; type: 'UPDATE_FONT_SIZE';
size: number; cardFontSize: number;
} }
| { | {
type: 'UPDATE_FONT_FAMILY'; type: 'UPDATE_FONT_FAMILY';
cardFont: string; cardFontFamily: string;
} }
| { | {
type: 'UPDATE_AUTOCOMPLETE'; type: 'UPDATE_AUTOCOMPLETE';
@ -127,13 +135,28 @@ type AppAction =
} }
| { | {
type: 'UPDATE_DISPLAY_SETTINGS'; type: 'UPDATE_DISPLAY_SETTINGS';
settings: DisplaySettings; settings: IStorable<DisplaySettings>;
} }
| { | {
type: 'SET_USER'; type: 'SET_USER';
user: User; user: User;
}; };
function maybeMutateStorable<T>(
state: AppState,
candidate: IStorable<T>,
incumbant: IStorable<T>,
composeState: (item: IStorable<T>) => AppState
): AppState {
// only update if the settings are newer.
if (new Date(candidate.createdOn) > new Date(incumbant.createdOn)) {
return composeState(candidate);
}
// candidate didn't win. return state untouched.
return state;
}
function reducer(state: AppState, action: AppAction): AppState { function reducer(state: AppState, action: AppAction): AppState {
// somtimes the state is null. lets not complain if that happens. // somtimes the state is null. lets not complain if that happens.
if (state === undefined) { if (state === undefined) {
@ -141,12 +164,41 @@ function reducer(state: AppState, action: AppAction): AppState {
} }
switch (action.type) { switch (action.type) {
//#region Display Settings
case 'UPDATE_DISPLAY_SETTINGS': { case 'UPDATE_DISPLAY_SETTINGS': {
return { return maybeMutateStorable(state, action.settings, state.displaySettings, (item) => {
...state, return {
displaySettings: action.settings, ...state,
}; displaySettings: item,
};
});
} }
case 'UPDATE_FONT_SIZE': {
const settings = new Storable<DisplaySettings>({
...state.displaySettings.value,
cardFontSize: action.cardFontSize,
});
return reducer(state, {
type: 'UPDATE_DISPLAY_SETTINGS',
settings,
});
}
case 'UPDATE_FONT_FAMILY': {
const settings = new Storable<DisplaySettings>({
...state.displaySettings.value,
cardFontFamily: action.cardFontFamily,
});
return reducer(state, {
type: 'UPDATE_DISPLAY_SETTINGS',
settings,
});
}
//#endregion
case 'UPDATE_AUTOCOMPLETE': { case 'UPDATE_AUTOCOMPLETE': {
return { return {
...state, ...state,
@ -154,49 +206,50 @@ function reducer(state: AppState, action: AppAction): AppState {
}; };
} }
case 'UPDATE_SAVED_PAGES': { case 'UPDATE_SAVED_PAGES': {
return { return maybeMutateStorable(state, action.savedPages, state.savedPages, (item) => {
...state, return {
savedPagesLoaded: true, ...state,
savedPages: action.savedPages, savedPagesLoaded: true,
}; savedPages: item,
};
});
} }
case 'UPDATE_CURRENT_PAGE': { case 'UPDATE_CURRENT_PAGE': {
const savedPages = [ const savedPages = new Storable<SavedPage[]>([
...state.savedPages.filter((o) => o.id === state.currentPage.id), ...state.savedPages.value.filter((o) => o.id === state.currentPage.id),
{ {
id: state.currentPage.id, id: state.currentPage.id,
title: state.currentPage.title, title: state.currentPage.title,
queries: [...state.cards], queries: [...state.cards],
}, },
]; ]);
return { return reducer(state, {
...state, type: 'UPDATE_SAVED_PAGES',
savedPagesLoaded: true,
savedPages, savedPages,
}; });
} }
case 'SAVE_PAGE': { case 'SAVE_PAGE': {
const savedPages = [ const savedPages = new Storable([
...state.savedPages, ...state.savedPages.value,
{ {
// create a new saved page object // create a new saved page object
title: action.title, title: action.title,
id: UUID.UUID().toString(), id: UUID.UUID().toString(),
queries: [...state.cards], queries: [...state.cards],
}, },
]; ]);
return {
...state, return reducer(state, {
savedPagesLoaded: true, type: 'UPDATE_SAVED_PAGES',
savedPages, savedPages,
}; });
} }
case 'GET_SAVED_PAGE': { case 'GET_SAVED_PAGE': {
const page = state.savedPages.find((o) => o.id.toString() === action.pageId); const page = state.savedPages.value.find((o) => o.id.toString() === action.pageId);
if (!page) { if (!page) {
return; return state;
} }
return { return {
@ -206,34 +259,36 @@ function reducer(state: AppState, action: AppAction): AppState {
}; };
} }
case 'ADD_CARD_TO_SAVED_PAGE': { case 'ADD_CARD_TO_SAVED_PAGE': {
return { const savedPages = new Storable([
...state, ...state.savedPages.value.map((o) => {
savedPages: [ if (o.id.toString() === action.pageId) {
...state.savedPages.map((o) => { let cards = [];
if (o.id.toString() === action.pageId) { if (state.displaySettings.value.appendCardToBottom) {
let cards = []; cards = [...o.queries, action.card];
if (state.displaySettings.appendCardToBottom) { } else {
cards = [...o.queries, action.card]; cards = [action.card, ...o.queries];
} else {
cards = [action.card, ...o.queries];
}
return {
...o,
queries: cards,
};
} }
return o; return {
}), ...o,
], queries: cards,
}; };
}
return o;
}),
]);
return reducer(state, {
type: 'UPDATE_SAVED_PAGES',
savedPages,
});
} }
case 'ADD_CARD': { case 'ADD_CARD': {
let cards = []; let cards = [];
if (action.nextToItem && state.displaySettings.insertCardNextToItem) { if (action.nextToItem && state.displaySettings.value.insertCardNextToItem) {
const idx = state.cards.indexOf(action.nextToItem); const idx = state.cards.indexOf(action.nextToItem);
if (state.displaySettings.appendCardToBottom) { if (state.displaySettings.value.appendCardToBottom) {
const before = state.cards.slice(0, idx + 1); const before = state.cards.slice(0, idx + 1);
const after = state.cards.slice(idx + 1); const after = state.cards.slice(idx + 1);
cards = [...before, action.card, ...after]; cards = [...before, action.card, ...after];
@ -243,7 +298,7 @@ function reducer(state: AppState, action: AppAction): AppState {
cards = [...before, action.card, ...after]; cards = [...before, action.card, ...after];
} }
} else { } else {
if (state.displaySettings.appendCardToBottom) { if (state.displaySettings.value.appendCardToBottom) {
cards = [...state.cards, action.card]; cards = [...state.cards, action.card];
} else { } else {
cards = [action.card, ...state.cards]; cards = [action.card, ...state.cards];
@ -271,24 +326,6 @@ function reducer(state: AppState, action: AppAction): AppState {
cards: [...state.cards.filter((c) => c !== action.card)], cards: [...state.cards.filter((c) => c !== action.card)],
}; };
} }
case 'UPDATE_FONT_SIZE': {
return {
...state,
displaySettings: {
...state.displaySettings,
fontSize: action.size,
},
};
}
case 'UPDATE_FONT_FAMILY': {
return {
...state,
displaySettings: {
...state.displaySettings,
cardFont: action.cardFont,
},
};
}
case 'SET_USER': { case 'SET_USER': {
return { return {
...state, ...state,
@ -309,7 +346,7 @@ export class AppService extends createStateService(reducer, initialState) {
private readonly dataPath = 'assets/data'; private readonly dataPath = 'assets/data';
constructor(private http: HttpClient, private localStorageService: StorageMap) { constructor(private http: HttpClient, private localStorageService: StorageMap, private db: AngularFireDatabase) {
super(); super();
this.searchIndexArray = this.buildIndexArray().sort(); this.searchIndexArray = this.buildIndexArray().sort();
@ -322,7 +359,7 @@ export class AppService extends createStateService(reducer, initialState) {
}); });
} }
private dispatchError(msg: string) { dispatchError(msg: string) {
this.dispatch({ this.dispatch({
type: 'UPDATE_ERROR', type: 'UPDATE_ERROR',
error: { error: {
@ -341,19 +378,6 @@ export class AppService extends createStateService(reducer, initialState) {
//#region Saved Pages //#region Saved Pages
async initSavedPages() {
const exists = await this.localStorageService.has('savedPages').toPromise();
if (exists) {
const savedPages = (await this.localStorageService.get('savedPages').toPromise()) as SavedPage[];
this.dispatch({
type: 'UPDATE_SAVED_PAGES',
savedPages,
});
}
}
getSavedPage(pageid: string) { getSavedPage(pageid: string) {
this.dispatch({ this.dispatch({
type: 'GET_SAVED_PAGE', type: 'GET_SAVED_PAGE',
@ -368,30 +392,19 @@ export class AppService extends createStateService(reducer, initialState) {
}); });
} }
savePagesApi(savedPages: readonly SavedPage[]) { updateSavedPage() {
this.localStorageService.set('savedPages', savedPages).subscribe(
() => {
// nop
},
// error
() => {
this.dispatch({
type: 'UPDATE_ERROR',
error: {
// tslint:disable-next-line: quotemark
msg: "Something went wrong and the page wasn't saved. :(",
},
});
}
);
}
updatePage() {
this.dispatch({ this.dispatch({
type: 'UPDATE_CURRENT_PAGE', type: 'UPDATE_CURRENT_PAGE',
}); });
} }
updateSavedPages(savedPages: IStorable<readonly SavedPage[]>) {
this.dispatch({
type: 'UPDATE_SAVED_PAGES',
savedPages,
});
}
addCardToSavedPage(pageId: string, card: CardItem) { addCardToSavedPage(pageId: string, card: CardItem) {
this.dispatch({ this.dispatch({
type: 'ADD_CARD_TO_SAVED_PAGE', type: 'ADD_CARD_TO_SAVED_PAGE',
@ -407,45 +420,24 @@ export class AppService extends createStateService(reducer, initialState) {
changeCardFontFamily(cardFont: string) { changeCardFontFamily(cardFont: string) {
this.dispatch({ this.dispatch({
type: 'UPDATE_FONT_FAMILY', type: 'UPDATE_FONT_FAMILY',
cardFont, cardFontFamily: cardFont,
}); });
} }
changeCardFontSize(size: number) { changeCardFontSize(size: number) {
this.dispatch({ this.dispatch({
type: 'UPDATE_FONT_SIZE', type: 'UPDATE_FONT_SIZE',
size, cardFontSize: size,
}); });
} }
updateDisplaySettings(settings: DisplaySettings) { updateDisplaySettings(settings: IStorable<DisplaySettings>) {
this.dispatch({ this.dispatch({
type: 'UPDATE_DISPLAY_SETTINGS', type: 'UPDATE_DISPLAY_SETTINGS',
settings, settings,
}); });
} }
async initDisplaySettings() {
const hasDisplaySettings = await this.localStorageService.has('displaySettings').toPromise();
if (hasDisplaySettings) {
const settings = await this.getSettingsApi();
this.dispatch({
type: 'UPDATE_DISPLAY_SETTINGS',
settings,
});
}
}
saveSettingsApi(settings: DisplaySettings) {
return this.localStorageService.set('displaySettings', settings);
}
private async getSettingsApi() {
return (await this.localStorageService.get('displaySettings').toPromise()) as DisplaySettings;
}
//#endregion //#endregion
//#region Notes //#region Notes
@ -581,13 +573,17 @@ export class AppService extends createStateService(reducer, initialState) {
if (dict === 'grk') { if (dict === 'grk') {
result.prefix = 'G'; result.prefix = 'G';
if (sn > 5624 || sn < 1) { if (sn > 5624 || sn < 1) {
this.dispatchError(`Strong's Number G${sn} is out of range. Strong's numbers range from 1 - 5624 in the New Testament.`); this.dispatchError(
`Strong's Number G${sn} is out of range. Strong's numbers range from 1 - 5624 in the New Testament.`
);
return; return;
} }
} else { } else {
result.prefix = 'H'; result.prefix = 'H';
if (sn > 8674 || sn < 1) { if (sn > 8674 || sn < 1) {
this.dispatchError(`Strong's Number H${sn} is out of range. Strong's numbers range from 1 - 8674 in the Old Testament.`); this.dispatchError(
`Strong's Number H${sn} is out of range. Strong's numbers range from 1 - 8674 in the Old Testament.`
);
return; return;
} }
} }
@ -788,7 +784,11 @@ export class AppService extends createStateService(reducer, initialState) {
return passages; return passages;
} }
private convertToParagraphs(ch: BiblePassage, section: Section, paragraphMarkers: HashTable<Paragraph>): BibleParagraph[] { private convertToParagraphs(
ch: BiblePassage,
section: Section,
paragraphMarkers: HashTable<Paragraph>
): BibleParagraph[] {
// group the verses into paragraphs. // group the verses into paragraphs.
// create an initial paragraph to hold verses that might come before a paragraph. // create an initial paragraph to hold verses that might come before a paragraph.
@ -875,7 +875,9 @@ export class AppService extends createStateService(reducer, initialState) {
// handle the first case. // handle the first case.
if (stem <= this.searchIndexArray[0]) { if (stem <= this.searchIndexArray[0]) {
results.unshift(await this.getSearchReferences(`${this.dataPath}/index/${this.searchIndexArray[0]}idx.json`, stem)); results.unshift(
await this.getSearchReferences(`${this.dataPath}/index/${this.searchIndexArray[0]}idx.json`, stem)
);
break; break;
} }
@ -883,7 +885,9 @@ export class AppService extends createStateService(reducer, initialState) {
for (let w = 1; w < this.searchIndexArray.length; w++) { for (let w = 1; w < this.searchIndexArray.length; w++) {
// If we are at the end of the array, we want to use a different test. // If we are at the end of the array, we want to use a different test.
if (stem <= this.searchIndexArray[w] && stem > this.searchIndexArray[w - 1]) { if (stem <= this.searchIndexArray[w] && stem > this.searchIndexArray[w - 1]) {
results.unshift(await this.getSearchReferences(`${this.dataPath}/index/${this.searchIndexArray[w]}idx.json`, stem)); results.unshift(
await this.getSearchReferences(`${this.dataPath}/index/${this.searchIndexArray[w]}idx.json`, stem)
);
} }
} }
} // End of loop through query terms } // End of loop through query terms
@ -1290,7 +1294,8 @@ export class AppService extends createStateService(reducer, initialState) {
for (const item of BibleReference.Books) { for (const item of BibleReference.Books) {
if ( if (
item.name !== 'Unknown' && item.name !== 'Unknown' &&
(item.name.toLowerCase().indexOf(qry.toLowerCase()) > -1 || item.abbreviation.toLowerCase().indexOf(qry.toLowerCase()) > -1) (item.name.toLowerCase().indexOf(qry.toLowerCase()) > -1 ||
item.abbreviation.toLowerCase().indexOf(qry.toLowerCase()) > -1)
) { ) {
words.push(prefix + item.name); words.push(prefix + item.name);
if (words.length > 2) { if (words.length > 2) {

View File

@ -0,0 +1,131 @@
import { Injectable } from '@angular/core';
import { StorageMap } from '@ngx-pwa/local-storage';
import { AngularFireDatabase, AngularFireObject } from '@angular/fire/database';
import { IStorable } from '../models/storable';
import { AppService } from './app.service';
import { DisplaySettings, SavedPage, User } from '../models/app-state';
import { SubscriberComponent } from '../common/components/subscriber.component';
@Injectable({
providedIn: 'root',
})
export class StorageService extends SubscriberComponent {
private displaySettingsState$ = this.appService.select((state) => state.displaySettings);
private displaySettingsPath = 'displaySettings';
private displaySettingsRemoteObject: AngularFireObject<IStorable<DisplaySettings>>;
private savedPagesState$ = this.appService.select((state) => state.savedPages);
private savedPagesPath = 'savedPaged';
private savedPagesRemoteObject: AngularFireObject<IStorable<readonly SavedPage[]>>;
constructor(private local: StorageMap, private remote: AngularFireDatabase, private appService: AppService) {
super();
//#region handle remote and local storage
// when the specific items change in the state,
// store them locally and remotely, if you're logged in.
this.addSubscription(
this.displaySettingsState$.subscribe((settings) => {
if (!settings) {
return;
}
// update local
this.local.set('displaySettings', settings).subscribe(
() => {
// nop
},
// error
() => {
// tslint:disable-next-line: quotemark
this.appService.dispatchError("Something went wrong and the display settings weren't saved. :(");
}
);
// update remote
if (this.displaySettingsRemoteObject) {
this.displaySettingsRemoteObject.set(settings);
}
})
);
this.addSubscription(
this.savedPagesState$.subscribe((savedPages) => {
if (!savedPages) {
return;
}
// update local
this.local.set('savedPages', savedPages).subscribe(
() => {
// nop
},
// error
() => {
// tslint:disable-next-line: quotemark
this.appService.dispatchError("Something went wrong and the page wasn't saved. :(");
}
);
// update remote
if (this.savedPagesRemoteObject) {
this.savedPagesRemoteObject.set(savedPages);
}
})
);
//#endregion
}
initRemote(user: User) {
this.displaySettingsRemoteObject = this.remote.object<IStorable<DisplaySettings>>(
`/${this.displaySettingsPath}/${user.uid}`
);
this.savedPagesRemoteObject = this.remote.object<IStorable<SavedPage[]>>(`/${this.savedPagesPath}/${user.uid}`);
// display settings
this.addSubscription(
this.displaySettingsRemoteObject
.valueChanges() // when the value changes
.subscribe((remoteDisplaySettings) => {
if (remoteDisplaySettings) {
// update the display settings locally from remote if it isn't null
this.appService.updateDisplaySettings(remoteDisplaySettings);
}
})
);
// saved pages
this.addSubscription(
this.savedPagesRemoteObject
.valueChanges() // when the saved pages have changed
.subscribe((remoteSavedPages) => {
if (remoteSavedPages) {
// update the saved pages locally from remote if it isn't null
this.appService.updateSavedPages(remoteSavedPages);
}
})
);
}
async initDisplaySettings() {
const hasDisplaySettings = await this.local.has(this.displaySettingsPath).toPromise();
if (hasDisplaySettings) {
const settings = (await this.local.get(this.displaySettingsPath).toPromise()) as IStorable<DisplaySettings>;
this.appService.updateDisplaySettings(settings);
}
}
async initSavedPages() {
const exists = await this.local.has(this.savedPagesPath).toPromise();
if (exists) {
const savedPages = (await this.local.get(this.savedPagesPath).toPromise()) as IStorable<SavedPage[]>;
this.appService.updateSavedPages(savedPages);
}
}
}