FEATURE: Toggle showing the verse numbers

This commit is contained in:
walljm 2018-01-06 01:30:06 -05:00
parent 1156b32c28
commit 5b621dda80
10 changed files with 29661 additions and 95 deletions

File diff suppressed because one or more lines are too long

View File

@ -10,12 +10,17 @@
<h2 *ngIf="data.cs.length > 1"> <h2 *ngIf="data.cs.length > 1">
<b>Chapter {{ch.ch}}</b> <b>Chapter {{ch.ch}}</b>
</h2> </h2>
<span *ngFor="let vs of ch.vss"> <div *ngFor="let para of getParas(ch)">
<b>{{vs.v}}.</b> <span *ngFor="let w of vs.w"> <h3 *ngIf="hasHeader(para.p)">{{para.p.h}}</h3>
<ng-template [ngIf]="!isPunct(w.t)"> </ng-template><a *ngIf="w.s != null" (click)="openStrongs(w.s)" (press)="openMenu(w.s)">{{w.t}}</a> <p>
<ng-template [ngIf]="w.s == null">{{w.t}}</ng-template> <span *ngFor="let vs of para.vss">
</span><br *ngIf="versesOnNewLine"> <b *ngIf="showVerseNumbers">{{vs.v}}.</b> <span *ngFor="let w of vs.w">
</span> <ng-template [ngIf]="!isPunct(w.t)"> </ng-template><a *ngIf="w.s != null" (click)="openStrongs(w.s)" (press)="openMenu(w.s)">{{w.t}}</a>
<ng-template [ngIf]="w.s == null">{{w.t}}</ng-template>
</span><br *ngIf="versesOnNewLine">
</span>
</p>
</div>
</div> </div>
</ion-card-content> </ion-card-content>
<ion-card-content *ngIf="data !== undefined && data.status === -1"> <ion-card-content *ngIf="data !== undefined && data.status === -1">

View File

@ -1,6 +1,7 @@
passage { passage {
a { a {
user-select: text !important; user-select: text !important;
cursor: pointer;
} }
} }
@ -14,6 +15,15 @@ passage .button {
passage .passage-text { passage .passage-text {
padding-bottom: 12px; padding-bottom: 12px;
h3 {
font-size: 1.6rem;
font-weight: bold;
}
p {
text-indent: 1em;
}
} }
.passage-text + .passage-text { .passage-text + .passage-text {

View File

@ -1,6 +1,6 @@
import { Component, EventEmitter, Output, Input, OnInit, ElementRef } from '@angular/core'; import { Component, EventEmitter, Output, Input, OnInit, ElementRef } from '@angular/core';
import { OpenData, CardItem } from '../../pages/search/search'; import { OpenData, CardItem } from '../../pages/search/search';
import { BiblePassageResult, BibleService } from '../../services/bible-service'; import { BiblePassageResult, BibleService, BiblePassage, BibleVerse, HashTable, Paragraph } from '../../services/bible-service';
import { Reference } from '../../libs/Reference'; import { Reference } from '../../libs/Reference';
@Component({ @Component({
@ -21,6 +21,9 @@ export class Passage implements OnInit
@Input() @Input()
versesOnNewLine: boolean; versesOnNewLine: boolean;
@Input()
showVerseNumbers: boolean;
data: BiblePassageResult; data: BiblePassageResult;
ref: Reference; ref: Reference;
@ -151,4 +154,58 @@ export class Passage implements OnInit
{ {
return new RegExp('^[\.\,\;\:\?\!]$').test(c); return new RegExp('^[\.\,\;\:\?\!]$').test(c);
} }
hasHeader(p: Paragraph)
{
if (p === undefined)
return false;
return p.h.length > 0;
}
isPara(vs: BibleVerse)
{
return this.getRefKey(vs) in BibleService.paragraphs;
}
getRefKey(vs: BibleVerse)
{
return this.ref.Section.start.book.book_number + ';' + this.ref.Section.start.chapter + ';' + vs.v;
}
getParas(ch: BiblePassage)
{
// group the verses into paragraphs.
// create an initial paragraph to hold verses that might come before a paragraph.
let para: BiblePara = { p: { h: '', p: 0 }, vss: [] };
let paras: BiblePara[] = [];
// for each verse in the chapter, break them into paragraphs.
for (let v of ch.vss)
{
if (this.isPara(v))
{
paras.push(para);
para = { p: BibleService.paragraphs[this.getRefKey(v)], vss: [v] };
if (para.p === undefined)
para.p = { h: '', p: 0 }; // just in case you can't find a paragraph.
}
else
{
para.vss.push(v);
}
}
// add the final paragraph if it has verses.
if (para.vss.length > 0)
paras.push(para);
return paras;
}
}
type BiblePara = {
p: Paragraph,
vss: BibleVerse[],
} }

View File

@ -19,17 +19,6 @@
</button> </button>
</ion-list> </ion-list>
<ng-template [ngIf]="!profileService.currentUser()">
<ion-item>
<button ion-button (click)="profileService.authenticate()">Login With Google</button>
</ion-item>
</ng-template>
<ng-template [ngIf]="profileService.currentUser()">
<ion-item>
<button ion-button (click)="profileService.logout()">Logout</button>
</ion-item>
</ng-template>
<ion-list-header>Search Settings</ion-list-header> <ion-list-header>Search Settings</ion-list-header>
<ion-item> <ion-item>
<ion-label>Show Strongs as Modal</ion-label> <ion-label>Show Strongs as Modal</ion-label>
@ -51,6 +40,10 @@
<ion-label>Each Verse on New Line</ion-label> <ion-label>Each Verse on New Line</ion-label>
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().verses_on_new_line" (ionChange)="save()"></ion-toggle> <ion-toggle color="dark" [(ngModel)]="this.profileService.profile().verses_on_new_line" (ionChange)="save()"></ion-toggle>
</ion-item> </ion-item>
<ion-item>
<ion-label>Show Verse #'s</ion-label>
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().show_verse_numbers" (ionChange)="save()"></ion-toggle>
</ion-item>
<ion-list-header>Adjust Text</ion-list-header> <ion-list-header>Adjust Text</ion-list-header>
<ion-list> <ion-list>
<ion-item> <ion-item>
@ -60,6 +53,22 @@
</ion-range> </ion-range>
</ion-item> </ion-item>
</ion-list> </ion-list>
<ion-list-header>Login/Logout</ion-list-header>
<ng-template [ngIf]="!profileService.currentUser()">
<ion-item>
<button ion-button (click)="profileService.authenticate()">Login With Google</button>
</ion-item>
</ng-template>
<ng-template [ngIf]="profileService.currentUser()">
<ion-item>
<button ion-button (click)="profileService.logout()">Logout</button>
</ion-item>
<ion-item>
<button ion-button (click)="profileService.Refresh()">Refresh</button>
</ion-item>
</ng-template>
</ion-content> </ion-content>
</ion-menu> </ion-menu>
@ -82,21 +91,10 @@
<ion-content #searchcontent padding class="search-card"> <ion-content #searchcontent padding class="search-card">
<ion-card *ngFor="let item of this.profileService.profile().items"> <ion-card *ngFor="let item of this.profileService.profile().items">
<passage *ngIf="isPassage(item.type)" <passage *ngIf="isPassage(item.type)" [cardItem]="item" [versesOnNewLine]="this.profileService.profile().verses_on_new_line"
[cardItem]="item" [showVerseNumbers]="this.profileService.profile().show_verse_numbers" (onClose)="removeItem($event)" (onItemClicked)="getItemsNextToCard($event)"></passage>
[versesOnNewLine]="this.profileService.profile().verses_on_new_line" <strongs *ngIf="isStrongs(item.type)" [cardItem]="item" (onClose)="removeItem($event)" (onItemClicked)="getItemsNextToCard($event)"></strongs>
(onClose)="removeItem($event)" <words *ngIf="isWords(item.type)" [cardItem]="item" (onClose)="removeItem($event)" (onItemClicked)="getItemsNextToCard($event)"></words>
(onItemClicked)="getItemsNextToCard($event)"></passage> <error *ngIf="isError(item.type)" [cardItem]="item" (onClose)="removeItem($event)"></error>
<strongs *ngIf="isStrongs(item.type)"
[cardItem]="item"
(onClose)="removeItem($event)"
(onItemClicked)="getItemsNextToCard($event)"></strongs>
<words *ngIf="isWords(item.type)"
[cardItem]="item"
(onClose)="removeItem($event)"
(onItemClicked)="getItemsNextToCard($event)"></words>
<error *ngIf="isError(item.type)"
[cardItem]="item"
(onClose)="removeItem($event)"></error>
</ion-card> </ion-card>
</ion-content> </ion-content>

View File

@ -3,17 +3,14 @@
margin: 1em 0; margin: 1em 0;
font-size: 1em; font-size: 1em;
} }
.button-large { .button-large {
height: 3.6rem !important; height: 3.6rem !important;
} }
.title { .title {
font-size: 1.3em; font-size: 1.3em;
font-family: 'Roboto', Helvetica, Arial, sans-serif; font-family: 'Roboto', Helvetica, Arial, sans-serif;
font-weight: 400; font-weight: 400;
} }
a { a {
color: black; color: black;
border-bottom: 1px dotted #b3bfd0; border-bottom: 1px dotted #b3bfd0;
@ -22,21 +19,25 @@
body { body {
-webkit-user-select: auto !important; -webkit-user-select: auto !important;
.scroll { .scroll {
-webkit-user-select: inherit; -webkit-user-select: inherit;
user-select: inherit;
} }
} }
.card h2 { .card {
font-size: 1.2em; h2 {
font-weight: bold; font-size: 1.2em;
font-weight: bold;
}
font-family: "Roboto", "Arial", "Helvetica", sans-serif;
} }
.item.item-block .item-inner { .item.item-block .item-inner {
padding: 0px; padding: 0px;
} }
.item ion-icon[item-left] + .item-inner { .item ion-icon[item-left]+.item-inner {
margin-left: 6px; margin-left: 6px;
} }

View File

@ -9,11 +9,53 @@ export class BibleService
{ {
chapters: BiblePassage[]; chapters: BiblePassage[];
result: BiblePassageResult; result: BiblePassageResult;
static paragraphs: HashTable<Paragraph>;
count = 0; count = 0;
$: any; $: any;
constructor(private http: Http) constructor(private http: Http)
{ {
this.getParagraphMarkersAsPromise()
}
getParagraphMarkersAsPromise(): Promise<HashTable<Paragraph>>
{
return new Promise((resolve) => { resolve(this.getParagraphMarkers()); });
}
getParagraphMarkers() : HashTable<Paragraph>
{
try
{
if (BibleService.paragraphs !== undefined && '1;1;1' in BibleService.paragraphs)
return BibleService.paragraphs;
const self = this;
const url = 'data/bibles/paras.json';
$.ajax({
async: false,
type: 'GET',
url: url,
dataType: 'json',
success(d: HashTable<Paragraph>)
{
BibleService.paragraphs = d;
},
error()
{
console.log('Unable to retrieve paragraphs.');
}
});
return BibleService.paragraphs;
}
catch (error)
{
console.log(error);
}
return null;
} }
getResultAsPromise(section: Section): Promise<BiblePassageResult> getResultAsPromise(section: Section): Promise<BiblePassageResult>
@ -33,7 +75,7 @@ export class BibleService
ref: Reference.toString(section), ref: Reference.toString(section),
status: 0, status: 0,
msg: ':)' msg: ':)'
}; };
if (Number(section.start.chapter) > section.start.book.last_chapter) if (Number(section.start.chapter) > section.start.book.last_chapter)
{ {
@ -146,12 +188,12 @@ export type BiblePassageResult = {
msg: string, msg: string,
} }
type BiblePassage = { export type BiblePassage = {
ch: number, ch: number,
vss: BibleVerse[], vss: BibleVerse[],
} }
type BibleVerse = { export type BibleVerse = {
v: number, v: number,
w: [ w: [
{ {
@ -159,3 +201,13 @@ type BibleVerse = {
} }
], ],
} }
export type Paragraph = {
h: string,
p: number
}
export interface HashTable<T>
{
[key: string]: T;
}

View File

@ -8,6 +8,7 @@ import { Catch } from 'rxjs/add/operator';
import { Storage } from '@ionic/storage'; import { Storage } from '@ionic/storage';
import { CardItem } from '../pages/search/search'; import { CardItem } from '../pages/search/search';
import { Promise } from 'q';
type fbObject<T> = { type fbObject<T> = {
ref: AngularFireObject<T>, ref: AngularFireObject<T>,
@ -27,6 +28,7 @@ export type User = {
font_size: number, font_size: number,
saved_pages: SavedPage[], saved_pages: SavedPage[],
verses_on_new_line: boolean, verses_on_new_line: boolean,
show_verse_numbers: boolean,
} }
export type SavedPage = { export type SavedPage = {
@ -49,7 +51,6 @@ export class ProfileService
{ {
this.isWeb = (document.URL.startsWith('http') || !document.URL.startsWith('http://localhost:8080')); this.isWeb = (document.URL.startsWith('http') || !document.URL.startsWith('http://localhost:8080'));
console.log('Setting up default user initially');
let localObserver = this.userObserver().subscribe( let localObserver = this.userObserver().subscribe(
user => user =>
{ {
@ -78,7 +79,6 @@ export class ProfileService
{ {
if (!this.localProfile) if (!this.localProfile)
{ {
console.log('Initializing default user');
this.localProfile = ProfileService.createDefaultUser(); this.localProfile = ProfileService.createDefaultUser();
} }
@ -88,7 +88,6 @@ export class ProfileService
subscribeToRemoteProfile(db: AngularFireDatabase, user: firebase.User) subscribeToRemoteProfile(db: AngularFireDatabase, user: firebase.User)
{ {
if (!user) return; if (!user) return;
console.log('Subscribing to remote settings for user id%s', user.uid);
let obj = db.object('/settings/' + user.uid); let obj = db.object('/settings/' + user.uid);
this.remoteProfile = { this.remoteProfile = {
ref: obj as AngularFireObject<User>, ref: obj as AngularFireObject<User>,
@ -105,7 +104,6 @@ export class ProfileService
{ {
if (user) if (user)
{ {
console.log('handling remote settings for user %s', user.username);
if (!user.saved_pages) user.saved_pages = []; if (!user.saved_pages) user.saved_pages = [];
if (!user.items) user.items = []; if (!user.items) user.items = [];
@ -117,17 +115,13 @@ export class ProfileService
user.saved_pages.concat(this.localProfile.saved_pages); user.saved_pages.concat(this.localProfile.saved_pages);
this.localProfile = user; this.localProfile = user;
console.log('Stashed remote changes locally');
// We only save the local change here since this is an update from our remote profile. // We only save the local change here since this is an update from our remote profile.
this.localSave(); this.localSave();
console.log('Saved remote changes locally');
} }
else else
{ {
// No user is there so we should save our local to the remote. // No user is there so we should save our local to the remote.
console.log('Saving local to remote for user %s', user.username);
this.save() this.save()
console.log('Saved remote for user %s', user.username);
} }
} }
@ -160,6 +154,12 @@ export class ProfileService
} }
Refresh()
{
this.logout();
this.authenticate();
}
logout() logout()
{ {
this.firebaseAuth.auth.signOut(); // sign out this.firebaseAuth.auth.signOut(); // sign out
@ -176,10 +176,10 @@ export class ProfileService
{ {
// First we save our local copy of the settings. // First we save our local copy of the settings.
this.localSave(); this.localSave();
// If we have a remote profile then save it there too // If we have a remote profile then save it there too
if (this.remoteProfile) if (this.remoteProfile)
{ {
console.log('Saving remote settings profile for remote user id ' + this.profile().uid);
this.remoteProfile.ref.set(this.profile()); this.remoteProfile.ref.set(this.profile());
} }
} }
@ -220,6 +220,7 @@ export class ProfileService
this.localProfile.font_size = 10; this.localProfile.font_size = 10;
this.localProfile.saved_pages = []; this.localProfile.saved_pages = [];
this.localProfile.verses_on_new_line = true; this.localProfile.verses_on_new_line = true;
this.localProfile.show_verse_numbers = true;
} }
reset() reset()
@ -256,7 +257,8 @@ export class ProfileService
insert_next_to_item: false, insert_next_to_item: false,
font_size: 10, font_size: 10,
saved_pages: [], saved_pages: [],
verses_on_new_line: true verses_on_new_line: true,
show_verse_numbers: true,
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" dir="ltr"> <html lang="en" dir="ltr">
<head> <head>
<script data-ionic="inject">
(function(w){var i=w.Ionic=w.Ionic||{};i.version='3.9.0';i.angular='5.0.0';i.staticDir='build/';})(window);
</script>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Dynamic Bible</title> <title>Dynamic Bible</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">