mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-23 15:30:14 -04:00
sync local and remote display settings
This commit is contained in:
parent
573b9dc29d
commit
25ed414aba
@ -10,7 +10,7 @@ trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
max_line_length = 140
|
||||
max_line_length = 120
|
||||
end_of_line = lf
|
||||
|
||||
# this file has a need for arbitrarily long lines, so we exempt this here.
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"targets": {
|
||||
"dynamicbible-7c6cf": {
|
||||
"dynamic-bible-testing": {
|
||||
"hosting": {
|
||||
"db": [
|
||||
"dynamicbible-7c6cf"
|
||||
"dynamic-bible-testing"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Component, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { AppService } from './services/app.service';
|
||||
import { NavService } from './services/nav.service';
|
||||
import { StorageService } from './services/storage.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { map, shareReplay } from 'rxjs/operators';
|
||||
@ -16,20 +17,15 @@ import { SubscriberComponent } from './common/components/subscriber.component';
|
||||
styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
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);
|
||||
fontSize$ = this.appService.select(
|
||||
(state) => state.displaySettings.fontSize + 'pt'
|
||||
);
|
||||
cardFont$ = this.appService.select((state) => state.displaySettings.cardFont);
|
||||
displaySettings$ = this.appService.select((state) => state.displaySettings);
|
||||
fontSize$ = this.appService.select((state) => state.displaySettings.value.cardFontSize + 'pt');
|
||||
cardFont$ = this.appService.select((state) => state.displaySettings.value.cardFontFamily);
|
||||
|
||||
isHandset$: Observable<boolean> = this.breakpointObserver
|
||||
.observe(Breakpoints.Handset)
|
||||
.pipe(
|
||||
map((result) => result.matches),
|
||||
shareReplay()
|
||||
);
|
||||
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
|
||||
map((result) => result.matches),
|
||||
shareReplay()
|
||||
);
|
||||
|
||||
@ViewChild('drawer') public sidenav: MatSidenav;
|
||||
@ViewChild('settings') public settings: MatSidenav;
|
||||
@ -37,26 +33,28 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
|
||||
constructor(
|
||||
private appService: AppService,
|
||||
private navService: NavService,
|
||||
private storageService: StorageService,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private dialog: MatDialog
|
||||
) {
|
||||
super();
|
||||
|
||||
this.appService.initSavedPages();
|
||||
this.appService.initDisplaySettings();
|
||||
this.storageService.initSavedPages();
|
||||
this.storageService.initDisplaySettings();
|
||||
|
||||
//#region handle local storage
|
||||
//#region Handle recieving updates from firebase
|
||||
|
||||
this.addSubscription(
|
||||
this.displaySettings$.subscribe((settings) => {
|
||||
this.appService.saveSettingsApi(settings);
|
||||
})
|
||||
);
|
||||
|
||||
this.addSubscription(
|
||||
this.savedPages$.subscribe((savedPages) => {
|
||||
this.appService.savePagesApi(savedPages);
|
||||
})
|
||||
// when the user object changes, respond
|
||||
this.appService
|
||||
// this should trigger only once, when the user logs in.
|
||||
.select((state) => state.user)
|
||||
.subscribe((user) => {
|
||||
if (!user) {
|
||||
return; // if the user is null, avoid this.
|
||||
}
|
||||
this.storageService.initRemote(user);
|
||||
})
|
||||
);
|
||||
|
||||
//#endregion
|
||||
@ -73,10 +71,7 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
|
||||
this.addSubscription(
|
||||
this.cardFont$.subscribe((family) => {
|
||||
if (family) {
|
||||
document.documentElement.style.setProperty(
|
||||
'--card-font-family',
|
||||
family
|
||||
);
|
||||
document.documentElement.style.setProperty('--card-font-family', family);
|
||||
}
|
||||
})
|
||||
);
|
||||
@ -93,7 +88,7 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
updatePage() {
|
||||
this.appService.updatePage();
|
||||
this.appService.updateSavedPage();
|
||||
}
|
||||
|
||||
createNote() {
|
||||
|
@ -1,29 +1,34 @@
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
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 { 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 { 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 { 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 { 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 { MatButtonModule } from '@angular/material/button';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
@ -60,8 +65,6 @@ import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
|
||||
import { MatTreeModule } from '@angular/material/tree';
|
||||
import { ClipboardModule } from '@angular/cdk/clipboard';
|
||||
import { AngularFireModule } from '@angular/fire';
|
||||
import { FirebaseConfig } from './constants';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -91,6 +94,8 @@ import { FirebaseConfig } from './constants';
|
||||
NgxMdModule.forRoot(),
|
||||
|
||||
AngularFireModule.initializeApp(FirebaseConfig),
|
||||
AngularFireAuthModule,
|
||||
AngularFireDatabaseModule,
|
||||
|
||||
MatSidenavModule,
|
||||
MatToolbarModule,
|
||||
|
@ -1,10 +1,4 @@
|
||||
import {
|
||||
EventEmitter,
|
||||
Output,
|
||||
Input,
|
||||
ElementRef,
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
import { EventEmitter, Output, Input, ElementRef, Component } from '@angular/core';
|
||||
import { CardItem, OpenData } from '../../models/app-state';
|
||||
import { Observable } from 'rxjs';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
@ -75,7 +75,7 @@
|
||||
<div class="settings-h2">Card Font Family</div>
|
||||
<mat-form-field appearance="fill" class="card-fonts">
|
||||
<mat-select
|
||||
[(value)]="cardFont"
|
||||
[(value)]="cardFontFamily"
|
||||
(selectionChange)="cardFontSelected($event)"
|
||||
>
|
||||
<mat-option *ngFor="let font of fonts" [value]="font">
|
||||
@ -88,9 +88,9 @@
|
||||
<div class="settings-h2">Card Font Size</div>
|
||||
<mat-slider
|
||||
class="font-size-slider"
|
||||
max="32"
|
||||
min="10"
|
||||
step="1"
|
||||
max="24"
|
||||
min="12"
|
||||
step="2"
|
||||
thumbLabel="true"
|
||||
(change)="cardFontSizeChanged($event)"
|
||||
[(ngModel)]="cardFontSize"
|
||||
|
@ -8,6 +8,7 @@ import { MatSelectChange } from '@angular/material/select';
|
||||
import { MatSliderChange } from '@angular/material/slider';
|
||||
import { AngularFireAuth } from '@angular/fire/auth';
|
||||
import { auth } from 'firebase/app';
|
||||
import { Storable } from 'src/app/models/storable';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
@ -17,7 +18,7 @@ import { auth } from 'firebase/app';
|
||||
export class SettingsComponent extends SubscriberComponent {
|
||||
displaySettings: DisplaySettings;
|
||||
fonts: string[];
|
||||
cardFont = '';
|
||||
cardFontFamily = '';
|
||||
cardFontSize = 10;
|
||||
user$ = this.appService.select((state) => state.user);
|
||||
|
||||
@ -26,25 +27,30 @@ export class SettingsComponent extends SubscriberComponent {
|
||||
this.fonts = CardFonts;
|
||||
this.addSubscription(
|
||||
this.appService.state$.subscribe((state) => {
|
||||
this.displaySettings = state.displaySettings;
|
||||
this.cardFont = state.displaySettings.cardFont;
|
||||
this.displaySettings = state.displaySettings.value;
|
||||
this.cardFontFamily = state.displaySettings.value.cardFontFamily;
|
||||
this.cardFontSize = state.displaySettings.value.cardFontSize;
|
||||
})
|
||||
);
|
||||
|
||||
this.addSubscription(
|
||||
this.authService.authState.subscribe((user) => {
|
||||
this.appService.setUser({
|
||||
uid: user.uid,
|
||||
displayName: user.displayName,
|
||||
providerId: user.providerId,
|
||||
email: user.email,
|
||||
});
|
||||
if (user) {
|
||||
this.appService.setUser({
|
||||
uid: user.uid,
|
||||
displayName: user.displayName,
|
||||
providerId: user.providerId,
|
||||
email: user.email,
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
login() {
|
||||
this.authService.signInWithPopup(new auth.GoogleAuthProvider());
|
||||
this.authService.signInWithPopup(new auth.GoogleAuthProvider()).then((cred) => {
|
||||
console.log('Authenticated.');
|
||||
});
|
||||
}
|
||||
logout() {
|
||||
this.authService.signOut();
|
||||
@ -65,68 +71,86 @@ export class SettingsComponent extends SubscriberComponent {
|
||||
//#region Search Settings
|
||||
|
||||
toggleStrongsAsModal(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
showStrongsAsModal: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
showStrongsAsModal: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
toggleAppendCardToBottom(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
appendCardToBottom: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
appendCardToBottom: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
toggleInsertCardNextToItem(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
insertCardNextToItem: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
insertCardNextToItem: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
toggleClearSearchAfterQuery(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
clearSearchAfterQuery: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
clearSearchAfterQuery: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
toggleSyncCardsAcrossDevices(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
syncCardsAcrossDevices: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
syncCardsAcrossDevices: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Passage Settings
|
||||
|
||||
toggleParagraphHeadings(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
showParagraphHeadings: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
showParagraphHeadings: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
toggleParagraphs(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
showParagraphs: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
showParagraphs: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
toggleVerseNumbers(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
showVerseNumbers: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
showVerseNumbers: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
toggleVersesOnNewLine(toggle: MatSlideToggleChange) {
|
||||
this.appService.updateDisplaySettings({
|
||||
...this.displaySettings,
|
||||
showVersesOnNewLine: toggle.checked,
|
||||
});
|
||||
this.appService.updateDisplaySettings(
|
||||
new Storable({
|
||||
...this.displaySettings,
|
||||
showVersesOnNewLine: toggle.checked,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
@ -14,13 +14,30 @@ export const CardIcons = {
|
||||
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 = {
|
||||
apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8',
|
||||
authDomain: 'dynamicbible-7c6cf.firebaseapp.com',
|
||||
databaseURL: 'https://dynamicbible-7c6cf.firebaseio.com',
|
||||
projectId: 'dynamicbible-7c6cf',
|
||||
storageBucket: '',
|
||||
messagingSenderId: '200739882604',
|
||||
apiKey: 'AIzaSyA4b587psiOnpjbzu0t6z75A_hFksPyQkI',
|
||||
authDomain: 'dynamic-bible-testing.firebaseapp.com',
|
||||
databaseURL: 'https://dynamic-bible-testing.firebaseio.com',
|
||||
projectId: 'dynamic-bible-testing',
|
||||
storageBucket: 'dynamic-bible-testing.appspot.com',
|
||||
messagingSenderId: '813845246474',
|
||||
appId: '1:813845246474:web:6dccfa057b6cb3067565f3',
|
||||
};
|
||||
|
@ -1,12 +1,14 @@
|
||||
import { IStorable } from './storable';
|
||||
|
||||
export interface AppState {
|
||||
readonly currentPage: SavedPage;
|
||||
readonly savedPages: readonly SavedPage[];
|
||||
readonly savedPages: IStorable<readonly SavedPage[]>;
|
||||
readonly savedPagesLoaded: boolean;
|
||||
readonly mainPages: readonly Page[];
|
||||
readonly cards: readonly CardItem[];
|
||||
readonly autocomplete: readonly string[];
|
||||
readonly error: Error;
|
||||
readonly displaySettings: DisplaySettings;
|
||||
readonly displaySettings: IStorable<DisplaySettings>;
|
||||
readonly cardIcons: CardIcons;
|
||||
readonly user: User;
|
||||
}
|
||||
@ -33,12 +35,14 @@ export interface CardIcons {
|
||||
|
||||
export interface DisplaySettings {
|
||||
readonly showStrongsAsModal: boolean;
|
||||
|
||||
readonly appendCardToBottom: boolean;
|
||||
readonly insertCardNextToItem: boolean;
|
||||
|
||||
readonly clearSearchAfterQuery: boolean;
|
||||
|
||||
readonly fontSize: number;
|
||||
readonly cardFont: string;
|
||||
readonly cardFontSize: number;
|
||||
readonly cardFontFamily: string;
|
||||
|
||||
readonly showVersesOnNewLine: boolean;
|
||||
readonly showVerseNumbers: boolean;
|
||||
|
14
app/db/src/app/models/storable.ts
Normal file
14
app/db/src/app/models/storable.ts
Normal 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;
|
||||
}
|
@ -15,30 +15,18 @@ import { StrongsModalComponent } from '../strongs/modal/strongs-modal.component'
|
||||
export class PassageCardComponent extends CardComponent implements OnInit {
|
||||
ref: BibleReference;
|
||||
|
||||
showParagraphs$ = this.appService.select(
|
||||
(state) => state.displaySettings.showParagraphs
|
||||
);
|
||||
showParagraphs$ = this.appService.select((state) => state.displaySettings.value.showParagraphs);
|
||||
showParagraphHeadings$ = this.appService.select(
|
||||
(state) =>
|
||||
state.displaySettings.showParagraphHeadings &&
|
||||
state.displaySettings.showParagraphs
|
||||
);
|
||||
showVersesOnNewLine$ = this.appService.select(
|
||||
(state) => state.displaySettings.showVersesOnNewLine
|
||||
);
|
||||
showVerseNumbers$ = this.appService.select(
|
||||
(state) => state.displaySettings.showVerseNumbers
|
||||
(state) => state.displaySettings.value.showParagraphHeadings && state.displaySettings.value.showParagraphs
|
||||
);
|
||||
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;
|
||||
|
||||
constructor(
|
||||
protected elementRef: ElementRef,
|
||||
private appService: AppService,
|
||||
public dialog: MatDialog
|
||||
) {
|
||||
constructor(protected elementRef: ElementRef, private appService: AppService, public dialog: MatDialog) {
|
||||
super(elementRef, dialog);
|
||||
this.icon$ = appService.select((state) => state.cardIcons.passage);
|
||||
}
|
||||
@ -54,14 +42,9 @@ export class PassageCardComponent extends CardComponent implements OnInit {
|
||||
}
|
||||
|
||||
next() {
|
||||
const lastVerseForEnd = this.ref.section.book.chapters[
|
||||
this.ref.section.end.chapter
|
||||
];
|
||||
const lastVerseForEnd = this.ref.section.book.chapters[this.ref.section.end.chapter];
|
||||
|
||||
if (
|
||||
this.ref.section.end.verse !== 0 &&
|
||||
this.ref.section.end.verse !== lastVerseForEnd
|
||||
) {
|
||||
if (this.ref.section.end.verse !== 0 && this.ref.section.end.verse !== lastVerseForEnd) {
|
||||
this.ref.section.end.chapter = this.ref.section.end.chapter;
|
||||
} else {
|
||||
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.verse = 1;
|
||||
this.ref.section.end.verse = this.ref.section.book.chapters[
|
||||
this.ref.section.end.chapter
|
||||
];
|
||||
this.ref.section.end.verse = this.ref.section.book.chapters[this.ref.section.end.chapter];
|
||||
|
||||
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.start.verse = 1;
|
||||
this.ref.section.end.verse = this.ref.section.book.chapters[
|
||||
this.ref.section.end.chapter
|
||||
];
|
||||
this.ref.section.end.verse = this.ref.section.book.chapters[this.ref.section.end.chapter];
|
||||
|
||||
this.appService.updatePassage(this.cardItem, this.ref);
|
||||
}
|
||||
|
||||
expand() {
|
||||
const lastVerseForEnd = this.ref.section.book.chapters[
|
||||
this.ref.section.end.chapter
|
||||
];
|
||||
const lastVerseForEnd = this.ref.section.book.chapters[this.ref.section.end.chapter];
|
||||
|
||||
// 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) {
|
||||
this.ref.section.start.chapter = this.ref.section.start.chapter - 1;
|
||||
this.ref.section.start.verse =
|
||||
this.ref.section.book.chapters[this.ref.section.start.chapter] -
|
||||
(3 - this.ref.section.start.verse);
|
||||
this.ref.section.book.chapters[this.ref.section.start.chapter] - (3 - this.ref.section.start.verse);
|
||||
if (this.ref.section.start.chapter === 0) {
|
||||
this.ref.section.start.chapter = 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 (
|
||||
this.ref.section.end.verse === 0 ||
|
||||
this.ref.section.end.verse + 3 > lastVerseForEnd
|
||||
) {
|
||||
if (this.ref.section.end.verse === 0 || this.ref.section.end.verse + 3 > lastVerseForEnd) {
|
||||
this.ref.section.end.chapter = this.ref.section.end.chapter + 1;
|
||||
if (this.ref.section.end.verse === 0) {
|
||||
this.ref.section.end.verse = 3;
|
||||
} else {
|
||||
this.ref.section.end.verse =
|
||||
this.ref.section.end.verse + 3 - lastVerseForEnd;
|
||||
this.ref.section.end.verse = this.ref.section.end.verse + 3 - lastVerseForEnd;
|
||||
}
|
||||
|
||||
if (
|
||||
this.ref.section.end.chapter ===
|
||||
this.ref.section.book.lastChapter + 1
|
||||
) {
|
||||
if (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.verse = lastVerseForEnd;
|
||||
}
|
||||
|
@ -9,10 +9,7 @@ import { BibleReference } from '../../../common/bible-reference';
|
||||
import { VersePickerModalComponent } from '../verse-picker-modal/verse-picker-modal.component';
|
||||
import { SubscriberComponent } from '../../../common/components/subscriber.component';
|
||||
|
||||
import {
|
||||
MatAutocompleteTrigger,
|
||||
MatAutocomplete,
|
||||
} from '@angular/material/autocomplete';
|
||||
import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-page',
|
||||
@ -46,8 +43,7 @@ export class SearchPage extends SubscriberComponent implements OnInit {
|
||||
this.addSubscription(
|
||||
this.appService.state$.subscribe((state) => {
|
||||
this.savedPagedLoaded = state.savedPagesLoaded;
|
||||
this.clearSearchAfterQuery =
|
||||
state.displaySettings.clearSearchAfterQuery;
|
||||
this.clearSearchAfterQuery = state.displaySettings.value.clearSearchAfterQuery;
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -65,9 +61,7 @@ export class SearchPage extends SubscriberComponent implements OnInit {
|
||||
this.init();
|
||||
// subscribe to autocomplete input control's changes
|
||||
this.addSubscription(
|
||||
this.searchControl.valueChanges.subscribe((value: string) =>
|
||||
this.appService.getAutoComplete(value.toLowerCase())
|
||||
)
|
||||
this.searchControl.valueChanges.subscribe((value: string) => this.appService.getAutoComplete(value.toLowerCase()))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -15,16 +15,12 @@ export class StrongsCardComponent extends CardComponent {
|
||||
asModal = false;
|
||||
@ViewChild('strongs') strongsElement: ElementRef;
|
||||
|
||||
constructor(
|
||||
protected elementRef: ElementRef,
|
||||
protected appService: AppService,
|
||||
protected dialog: MatDialog
|
||||
) {
|
||||
constructor(protected elementRef: ElementRef, protected appService: AppService, protected dialog: MatDialog) {
|
||||
super(elementRef, dialog);
|
||||
this.icon$ = appService.select((state) => state.cardIcons.strongs);
|
||||
this.addSubscription(
|
||||
this.appService.state$.subscribe((state) => {
|
||||
this.asModal = state.displaySettings.showStrongsAsModal;
|
||||
this.asModal = state.displaySettings.value.showStrongsAsModal;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ import { PageTitles, PageIcons } from '../constants';
|
||||
import { createStateService } from '../common/state-service';
|
||||
import { UUID } from 'angular2-uuid';
|
||||
import { StorageMap } from '@ngx-pwa/local-storage';
|
||||
import { AngularFireDatabase } from '@angular/fire/database';
|
||||
import { IStorable, Storable } from '../models/storable';
|
||||
|
||||
const initialState: AppState = {
|
||||
user: null,
|
||||
@ -46,7 +48,10 @@ const initialState: AppState = {
|
||||
],
|
||||
autocomplete: [],
|
||||
currentPage: null,
|
||||
savedPages: [],
|
||||
savedPages: {
|
||||
createdOn: new Date(0).toISOString(),
|
||||
value: [],
|
||||
},
|
||||
savedPagesLoaded: false,
|
||||
mainPages: [
|
||||
{ title: PageTitles.Search, icon: PageIcons.Search, route: 'search' },
|
||||
@ -54,17 +59,20 @@ const initialState: AppState = {
|
||||
],
|
||||
error: null,
|
||||
displaySettings: {
|
||||
showStrongsAsModal: false,
|
||||
appendCardToBottom: true,
|
||||
insertCardNextToItem: true,
|
||||
clearSearchAfterQuery: true,
|
||||
fontSize: 12,
|
||||
cardFont: 'PT Serif',
|
||||
showVersesOnNewLine: false,
|
||||
showVerseNumbers: false,
|
||||
showParagraphs: true,
|
||||
showParagraphHeadings: true,
|
||||
syncCardsAcrossDevices: false,
|
||||
createdOn: new Date(0).toISOString(),
|
||||
value: {
|
||||
showStrongsAsModal: false,
|
||||
appendCardToBottom: true,
|
||||
insertCardNextToItem: true,
|
||||
clearSearchAfterQuery: true,
|
||||
cardFontSize: 12,
|
||||
cardFontFamily: 'PT Serif',
|
||||
showVersesOnNewLine: false,
|
||||
showVerseNumbers: false,
|
||||
showParagraphs: true,
|
||||
showParagraphHeadings: true,
|
||||
syncCardsAcrossDevices: false,
|
||||
},
|
||||
},
|
||||
cardIcons: {
|
||||
words: 'font_download',
|
||||
@ -88,7 +96,7 @@ type AppAction =
|
||||
}
|
||||
| {
|
||||
type: 'UPDATE_SAVED_PAGES';
|
||||
savedPages: SavedPage[];
|
||||
savedPages: IStorable<readonly SavedPage[]>;
|
||||
}
|
||||
| {
|
||||
type: 'ADD_CARD_TO_SAVED_PAGE';
|
||||
@ -115,11 +123,11 @@ type AppAction =
|
||||
}
|
||||
| {
|
||||
type: 'UPDATE_FONT_SIZE';
|
||||
size: number;
|
||||
cardFontSize: number;
|
||||
}
|
||||
| {
|
||||
type: 'UPDATE_FONT_FAMILY';
|
||||
cardFont: string;
|
||||
cardFontFamily: string;
|
||||
}
|
||||
| {
|
||||
type: 'UPDATE_AUTOCOMPLETE';
|
||||
@ -127,13 +135,28 @@ type AppAction =
|
||||
}
|
||||
| {
|
||||
type: 'UPDATE_DISPLAY_SETTINGS';
|
||||
settings: DisplaySettings;
|
||||
settings: IStorable<DisplaySettings>;
|
||||
}
|
||||
| {
|
||||
type: 'SET_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 {
|
||||
// somtimes the state is null. lets not complain if that happens.
|
||||
if (state === undefined) {
|
||||
@ -141,12 +164,41 @@ function reducer(state: AppState, action: AppAction): AppState {
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
//#region Display Settings
|
||||
|
||||
case 'UPDATE_DISPLAY_SETTINGS': {
|
||||
return {
|
||||
...state,
|
||||
displaySettings: action.settings,
|
||||
};
|
||||
return maybeMutateStorable(state, action.settings, state.displaySettings, (item) => {
|
||||
return {
|
||||
...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': {
|
||||
return {
|
||||
...state,
|
||||
@ -154,49 +206,50 @@ function reducer(state: AppState, action: AppAction): AppState {
|
||||
};
|
||||
}
|
||||
case 'UPDATE_SAVED_PAGES': {
|
||||
return {
|
||||
...state,
|
||||
savedPagesLoaded: true,
|
||||
savedPages: action.savedPages,
|
||||
};
|
||||
return maybeMutateStorable(state, action.savedPages, state.savedPages, (item) => {
|
||||
return {
|
||||
...state,
|
||||
savedPagesLoaded: true,
|
||||
savedPages: item,
|
||||
};
|
||||
});
|
||||
}
|
||||
case 'UPDATE_CURRENT_PAGE': {
|
||||
const savedPages = [
|
||||
...state.savedPages.filter((o) => o.id === state.currentPage.id),
|
||||
const savedPages = new Storable<SavedPage[]>([
|
||||
...state.savedPages.value.filter((o) => o.id === state.currentPage.id),
|
||||
{
|
||||
id: state.currentPage.id,
|
||||
title: state.currentPage.title,
|
||||
queries: [...state.cards],
|
||||
},
|
||||
];
|
||||
]);
|
||||
|
||||
return {
|
||||
...state,
|
||||
savedPagesLoaded: true,
|
||||
return reducer(state, {
|
||||
type: 'UPDATE_SAVED_PAGES',
|
||||
savedPages,
|
||||
};
|
||||
});
|
||||
}
|
||||
case 'SAVE_PAGE': {
|
||||
const savedPages = [
|
||||
...state.savedPages,
|
||||
const savedPages = new Storable([
|
||||
...state.savedPages.value,
|
||||
{
|
||||
// create a new saved page object
|
||||
title: action.title,
|
||||
id: UUID.UUID().toString(),
|
||||
queries: [...state.cards],
|
||||
},
|
||||
];
|
||||
return {
|
||||
...state,
|
||||
savedPagesLoaded: true,
|
||||
]);
|
||||
|
||||
return reducer(state, {
|
||||
type: 'UPDATE_SAVED_PAGES',
|
||||
savedPages,
|
||||
};
|
||||
});
|
||||
}
|
||||
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) {
|
||||
return;
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
@ -206,34 +259,36 @@ function reducer(state: AppState, action: AppAction): AppState {
|
||||
};
|
||||
}
|
||||
case 'ADD_CARD_TO_SAVED_PAGE': {
|
||||
return {
|
||||
...state,
|
||||
savedPages: [
|
||||
...state.savedPages.map((o) => {
|
||||
if (o.id.toString() === action.pageId) {
|
||||
let cards = [];
|
||||
if (state.displaySettings.appendCardToBottom) {
|
||||
cards = [...o.queries, action.card];
|
||||
} else {
|
||||
cards = [action.card, ...o.queries];
|
||||
}
|
||||
return {
|
||||
...o,
|
||||
queries: cards,
|
||||
};
|
||||
const savedPages = new Storable([
|
||||
...state.savedPages.value.map((o) => {
|
||||
if (o.id.toString() === action.pageId) {
|
||||
let cards = [];
|
||||
if (state.displaySettings.value.appendCardToBottom) {
|
||||
cards = [...o.queries, action.card];
|
||||
} else {
|
||||
cards = [action.card, ...o.queries];
|
||||
}
|
||||
return o;
|
||||
}),
|
||||
],
|
||||
};
|
||||
return {
|
||||
...o,
|
||||
queries: cards,
|
||||
};
|
||||
}
|
||||
return o;
|
||||
}),
|
||||
]);
|
||||
|
||||
return reducer(state, {
|
||||
type: 'UPDATE_SAVED_PAGES',
|
||||
savedPages,
|
||||
});
|
||||
}
|
||||
case 'ADD_CARD': {
|
||||
let cards = [];
|
||||
|
||||
if (action.nextToItem && state.displaySettings.insertCardNextToItem) {
|
||||
if (action.nextToItem && state.displaySettings.value.insertCardNextToItem) {
|
||||
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 after = state.cards.slice(idx + 1);
|
||||
cards = [...before, action.card, ...after];
|
||||
@ -243,7 +298,7 @@ function reducer(state: AppState, action: AppAction): AppState {
|
||||
cards = [...before, action.card, ...after];
|
||||
}
|
||||
} else {
|
||||
if (state.displaySettings.appendCardToBottom) {
|
||||
if (state.displaySettings.value.appendCardToBottom) {
|
||||
cards = [...state.cards, action.card];
|
||||
} else {
|
||||
cards = [action.card, ...state.cards];
|
||||
@ -271,24 +326,6 @@ function reducer(state: AppState, action: AppAction): AppState {
|
||||
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': {
|
||||
return {
|
||||
...state,
|
||||
@ -309,7 +346,7 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
|
||||
private readonly dataPath = 'assets/data';
|
||||
|
||||
constructor(private http: HttpClient, private localStorageService: StorageMap) {
|
||||
constructor(private http: HttpClient, private localStorageService: StorageMap, private db: AngularFireDatabase) {
|
||||
super();
|
||||
|
||||
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({
|
||||
type: 'UPDATE_ERROR',
|
||||
error: {
|
||||
@ -341,19 +378,6 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
|
||||
//#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) {
|
||||
this.dispatch({
|
||||
type: 'GET_SAVED_PAGE',
|
||||
@ -368,30 +392,19 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
});
|
||||
}
|
||||
|
||||
savePagesApi(savedPages: readonly SavedPage[]) {
|
||||
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() {
|
||||
updateSavedPage() {
|
||||
this.dispatch({
|
||||
type: 'UPDATE_CURRENT_PAGE',
|
||||
});
|
||||
}
|
||||
|
||||
updateSavedPages(savedPages: IStorable<readonly SavedPage[]>) {
|
||||
this.dispatch({
|
||||
type: 'UPDATE_SAVED_PAGES',
|
||||
savedPages,
|
||||
});
|
||||
}
|
||||
|
||||
addCardToSavedPage(pageId: string, card: CardItem) {
|
||||
this.dispatch({
|
||||
type: 'ADD_CARD_TO_SAVED_PAGE',
|
||||
@ -407,45 +420,24 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
changeCardFontFamily(cardFont: string) {
|
||||
this.dispatch({
|
||||
type: 'UPDATE_FONT_FAMILY',
|
||||
cardFont,
|
||||
cardFontFamily: cardFont,
|
||||
});
|
||||
}
|
||||
|
||||
changeCardFontSize(size: number) {
|
||||
this.dispatch({
|
||||
type: 'UPDATE_FONT_SIZE',
|
||||
size,
|
||||
cardFontSize: size,
|
||||
});
|
||||
}
|
||||
|
||||
updateDisplaySettings(settings: DisplaySettings) {
|
||||
updateDisplaySettings(settings: IStorable<DisplaySettings>) {
|
||||
this.dispatch({
|
||||
type: 'UPDATE_DISPLAY_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
|
||||
|
||||
//#region Notes
|
||||
@ -581,13 +573,17 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
if (dict === 'grk') {
|
||||
result.prefix = 'G';
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
result.prefix = 'H';
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -788,7 +784,11 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
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.
|
||||
|
||||
// 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.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -883,7 +885,9 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
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 (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
|
||||
@ -1290,7 +1294,8 @@ export class AppService extends createStateService(reducer, initialState) {
|
||||
for (const item of BibleReference.Books) {
|
||||
if (
|
||||
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);
|
||||
if (words.length > 2) {
|
||||
|
131
app/db/src/app/services/storage.service.ts
Normal file
131
app/db/src/app/services/storage.service.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user