mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-27 01:19:52 -04:00
FEATURE: Wire In Firebase support.
This commit is contained in:
parent
46099bbf32
commit
6a82a4e98a
@ -26,6 +26,7 @@ DynamicBibleIonic/nbproject
|
|||||||
DynamicBibleIonic/obj
|
DynamicBibleIonic/obj
|
||||||
DynamicBibleIonic/bin
|
DynamicBibleIonic/bin
|
||||||
DynamicBibleIonic/.vscode
|
DynamicBibleIonic/.vscode
|
||||||
|
DynamicBibleIonic/www/assets/
|
||||||
DynamicBibleUtility/.vs
|
DynamicBibleUtility/.vs
|
||||||
DynamicBibleIonic/platforms/android/release-signing.properties
|
DynamicBibleIonic/platforms/android/release-signing.properties
|
||||||
DynamicBibleIonic/platforms/android/build
|
DynamicBibleIonic/platforms/android/build
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ProfileService } from './../services/profile-service';
|
||||||
import { NgModule, ErrorHandler } from '@angular/core';
|
import { NgModule, ErrorHandler } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpModule } from '@angular/http';
|
||||||
@ -24,6 +25,8 @@ import { ErrorMessage } from '../components/error-message/error-message';
|
|||||||
import { VersePickerModal } from '../components/verse-picker/verse-picker';
|
import { VersePickerModal } from '../components/verse-picker/verse-picker';
|
||||||
|
|
||||||
import {AngularFireModule } from 'angularfire2';
|
import {AngularFireModule } from 'angularfire2';
|
||||||
|
import { AngularFireAuthModule } from 'angularfire2/auth';
|
||||||
|
import { AngularFireDatabaseModule } from 'angularfire2/database';
|
||||||
|
|
||||||
export const firebaseConfig = {
|
export const firebaseConfig = {
|
||||||
apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8',
|
apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8',
|
||||||
@ -55,7 +58,9 @@ export const firebaseConfig = {
|
|||||||
IonicStorageModule.forRoot(),
|
IonicStorageModule.forRoot(),
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HttpModule,
|
HttpModule,
|
||||||
AngularFireModule.initializeApp(firebaseConfig)
|
AngularFireModule.initializeApp(firebaseConfig),
|
||||||
|
AngularFireAuthModule,
|
||||||
|
AngularFireDatabaseModule,
|
||||||
],
|
],
|
||||||
bootstrap: [IonicApp],
|
bootstrap: [IonicApp],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
@ -71,6 +76,6 @@ export const firebaseConfig = {
|
|||||||
Error,
|
Error,
|
||||||
ErrorMessage
|
ErrorMessage
|
||||||
],
|
],
|
||||||
providers: [{ provide: ErrorHandler, useClass: IonicErrorHandler }, StatusBar, SplashScreen]
|
providers: [{ provide: ErrorHandler, useClass: IonicErrorHandler }, StatusBar, SplashScreen, ProfileService]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
/// <reference path="../../typings/globals/jquery/index.d.ts" />
|
|
||||||
import { Storage } from '@ionic/storage';
|
|
||||||
import { CardItem } from '../pages/search/search';
|
|
||||||
|
|
||||||
export class UserProfile
|
|
||||||
{
|
|
||||||
user: User;
|
|
||||||
|
|
||||||
constructor(u: User)
|
|
||||||
{
|
|
||||||
this.user = u;
|
|
||||||
}
|
|
||||||
|
|
||||||
public textSizeChanged()
|
|
||||||
{
|
|
||||||
$('html').css('font-size', this.user.font_size + 'px');
|
|
||||||
}
|
|
||||||
|
|
||||||
public update(t: UserProfile, local: Storage)
|
|
||||||
{
|
|
||||||
let updated = false;
|
|
||||||
let k;
|
|
||||||
const user = this.user;
|
|
||||||
for (k in user)
|
|
||||||
{
|
|
||||||
if (user.hasOwnProperty(k))
|
|
||||||
{
|
|
||||||
if (t[k] === undefined)
|
|
||||||
{
|
|
||||||
t[k] = user[k];
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (k in user)
|
|
||||||
if (user.hasOwnProperty(k))
|
|
||||||
user[k] = t[k];
|
|
||||||
|
|
||||||
if (updated)
|
|
||||||
this.save(local);
|
|
||||||
|
|
||||||
this.textSizeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
save(local: Storage)
|
|
||||||
{
|
|
||||||
local.set('profile', JSON.stringify(this.user));
|
|
||||||
}
|
|
||||||
|
|
||||||
reset(local: Storage)
|
|
||||||
{
|
|
||||||
this.user.strongs_modal = true;
|
|
||||||
this.user.clear_search_after_query = false;
|
|
||||||
this.user.items = [];
|
|
||||||
this.user.append_to_bottom = false;
|
|
||||||
this.user.insert_next_to_item = false;
|
|
||||||
this.user.font_size = 10;
|
|
||||||
this.user.saved_pages = [];
|
|
||||||
this.user.verses_on_new_line = true;
|
|
||||||
this.save(local);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static createDefaultUser(): User
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
strongs_modal: true,
|
|
||||||
clear_search_after_query: false,
|
|
||||||
items: [],
|
|
||||||
append_to_bottom: false,
|
|
||||||
insert_next_to_item: false,
|
|
||||||
font_size: 10,
|
|
||||||
saved_pages: [],
|
|
||||||
verses_on_new_line: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type User = {
|
|
||||||
strongs_modal: boolean,
|
|
||||||
clear_search_after_query: boolean,
|
|
||||||
items: CardItem[],
|
|
||||||
append_to_bottom: boolean,
|
|
||||||
insert_next_to_item: boolean,
|
|
||||||
font_size: number,
|
|
||||||
saved_pages: SavedPage[],
|
|
||||||
verses_on_new_line: boolean,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SavedPage = {
|
|
||||||
queries: CardItem[],
|
|
||||||
title: string,
|
|
||||||
}
|
|
@ -22,28 +22,28 @@
|
|||||||
<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>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.strongs_modal" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().strongs_modal" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Clear Search after Query</ion-label>
|
<ion-label>Clear Search after Query</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.clear_search_after_query" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().clear_search_after_query" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Append Results Below</ion-label>
|
<ion-label>Append Results Below</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.append_to_bottom" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().append_to_bottom" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Insert Result Next to Item</ion-label>
|
<ion-label>Insert Result Next to Item</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.insert_next_to_item" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().insert_next_to_item" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Each Verse on New Line</ion-label>
|
<ion-label>Each Verse on New Line</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.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-list-header>Adjust Text</ion-list-header>
|
<ion-list-header>Adjust Text</ion-list-header>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-range min="6" max="20" step="1" snaps="true" [(ngModel)]="userProfile.user.font_size" (ionChange)="textSizeChanged()">
|
<ion-range min="6" max="20" step="1" snaps="true" [(ngModel)]="this.profileService.profile().font_size" (ionChange)="textSizeChanged()">
|
||||||
<ion-label range-left class="small-text">A</ion-label>
|
<ion-label range-left class="small-text">A</ion-label>
|
||||||
<ion-label range-right>A</ion-label>
|
<ion-label range-right>A</ion-label>
|
||||||
</ion-range>
|
</ion-range>
|
||||||
@ -70,10 +70,10 @@
|
|||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content #searchcontent padding class="search-card">
|
<ion-content #searchcontent padding class="search-card">
|
||||||
<ion-card *ngFor="let item of userProfile.user.items">
|
<ion-card *ngFor="let item of this.profileService.profile().items">
|
||||||
<passage *ngIf="isPassage(item.type)"
|
<passage *ngIf="isPassage(item.type)"
|
||||||
[cardItem]="item"
|
[cardItem]="item"
|
||||||
[versesOnNewLine]="userProfile.user.verses_on_new_line"
|
[versesOnNewLine]="this.profileService.profile().verses_on_new_line"
|
||||||
(onClose)="removeItem($event)"
|
(onClose)="removeItem($event)"
|
||||||
(onItemClicked)="getItemsNextToCard($event)"></passage>
|
(onItemClicked)="getItemsNextToCard($event)"></passage>
|
||||||
<strongs *ngIf="isStrongs(item.type)"
|
<strongs *ngIf="isStrongs(item.type)"
|
||||||
|
@ -5,7 +5,7 @@ import { Storage } from '@ionic/storage';
|
|||||||
import { StrongsModal } from '../../components/strongs-modal/strongs-modal';
|
import { StrongsModal } from '../../components/strongs-modal/strongs-modal';
|
||||||
import { PagesService } from '../../services/pages-service';
|
import { PagesService } from '../../services/pages-service';
|
||||||
|
|
||||||
import { UserProfile } from '../../libs/UserProfile';
|
import { ProfileService, User } from './../../services/profile-service';
|
||||||
import { Reference } from '../../libs/Reference';
|
import { Reference } from '../../libs/Reference';
|
||||||
import { VersePickerModal } from '../../components/verse-picker/verse-picker';
|
import { VersePickerModal } from '../../components/verse-picker/verse-picker';
|
||||||
|
|
||||||
@ -15,7 +15,6 @@ import { VersePickerModal } from '../../components/verse-picker/verse-picker';
|
|||||||
export class SearchPage implements OnInit
|
export class SearchPage implements OnInit
|
||||||
{
|
{
|
||||||
searchQuery = '';
|
searchQuery = '';
|
||||||
userProfile: UserProfile;
|
|
||||||
last: CardItem;
|
last: CardItem;
|
||||||
loader: Loading;
|
loader: Loading;
|
||||||
title: string;
|
title: string;
|
||||||
@ -26,57 +25,44 @@ export class SearchPage implements OnInit
|
|||||||
, private menu: MenuController
|
, private menu: MenuController
|
||||||
, public loadingCtrl: LoadingController
|
, public loadingCtrl: LoadingController
|
||||||
, public modalCtrl: ModalController
|
, public modalCtrl: ModalController
|
||||||
, public local: Storage
|
, public profileService: ProfileService
|
||||||
, public params: NavParams
|
, public params: NavParams
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.userProfile = new UserProfile(UserProfile.createDefaultUser());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void
|
ngOnInit(): void
|
||||||
{
|
{
|
||||||
|
let t = this.profileService.profile();
|
||||||
// Check if there is a profile saved in local storage
|
// Check if there is a profile saved in local storage
|
||||||
this.local.get('profile').then(profile =>
|
this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
|
||||||
{
|
this.loader.present().then(() =>
|
||||||
let t = this.userProfile;
|
{
|
||||||
|
this.initializeItems(t);
|
||||||
|
|
||||||
if (profile !== null)
|
this.loader.dismiss();
|
||||||
t = JSON.parse(profile);
|
});
|
||||||
|
|
||||||
this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
|
|
||||||
this.loader.present().then(
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
this.userProfile.update(t, this.local);
|
|
||||||
|
|
||||||
this.initializeItems(this.userProfile);
|
|
||||||
|
|
||||||
this.loader.dismiss();
|
|
||||||
});
|
|
||||||
}).catch(error =>
|
|
||||||
{
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
initializeItems(u: UserProfile)
|
|
||||||
|
initializeItems(u: User)
|
||||||
{
|
{
|
||||||
// migrate old way of storing card items to the new.
|
// migrate old way of storing card items to the new.
|
||||||
let has_migrated = false;
|
let has_migrated = false;
|
||||||
for (let i in u.user.items)
|
for (let i in u.items)
|
||||||
{
|
{
|
||||||
if (u.user.items.hasOwnProperty(i))
|
if (u.items.hasOwnProperty(i))
|
||||||
{
|
{
|
||||||
let ci = u.user.items[i];
|
let ci = u.items[i];
|
||||||
if (ci['data'] !== undefined)
|
if (ci['data'] !== undefined)
|
||||||
{
|
{
|
||||||
if (ci['data'].qry !== undefined)
|
if (ci['data'].qry !== undefined)
|
||||||
u.user.items[i] = { qry: ci['data'].qry, dict: ci.dict, type: ci.type };
|
u.items[i] = { qry: ci['data'].qry, dict: ci.dict, type: ci.type };
|
||||||
else if (ci['data'].ref !== undefined)
|
else if (ci['data'].ref !== undefined)
|
||||||
u.user.items[i] = { qry: ci['data'].ref, dict: ci.dict, type: ci.type };
|
u.items[i] = { qry: ci['data'].ref, dict: ci.dict, type: ci.type };
|
||||||
else if (ci['data'].word !== undefined)
|
else if (ci['data'].word !== undefined)
|
||||||
u.user.items[i] = { qry: ci['data'].word, dict: ci.dict, type: ci.type };
|
u.items[i] = { qry: ci['data'].word, dict: ci.dict, type: ci.type };
|
||||||
else if (ci['data'].sn !== undefined)
|
else if (ci['data'].sn !== undefined)
|
||||||
u.user.items[i] = {
|
u.items[i] = {
|
||||||
qry: ci['data'].sn,
|
qry: ci['data'].sn,
|
||||||
dict: ci['prefix'] === 'G' ? 'grk' : 'heb',
|
dict: ci['prefix'] === 'G' ? 'grk' : 'heb',
|
||||||
type: ci.type
|
type: ci.type
|
||||||
@ -87,7 +73,7 @@ export class SearchPage implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let pg of u.user.saved_pages)
|
for (let pg of u.saved_pages)
|
||||||
{
|
{
|
||||||
for (let i in pg.queries)
|
for (let i in pg.queries)
|
||||||
{
|
{
|
||||||
@ -116,10 +102,10 @@ export class SearchPage implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initialize the pages.
|
// initialize the pages.
|
||||||
this.pagesService.initializePages(u.user.saved_pages);
|
this.pagesService.initializePages(u.saved_pages);
|
||||||
|
|
||||||
if (this.params.data.queries !== undefined)
|
if (this.params.data.queries !== undefined)
|
||||||
this.userProfile.user.items = this.params.data.queries.slice();
|
this.profileService.profile().items = this.params.data.queries.slice();
|
||||||
|
|
||||||
if (this.params.data.title === undefined)
|
if (this.params.data.title === undefined)
|
||||||
this.title = 'Search';
|
this.title = 'Search';
|
||||||
@ -127,18 +113,19 @@ export class SearchPage implements OnInit
|
|||||||
this.title = this.params.data.title;
|
this.title = this.params.data.title;
|
||||||
|
|
||||||
if (has_migrated)
|
if (has_migrated)
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
save()
|
save()
|
||||||
{
|
{
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save();
|
||||||
}
|
}
|
||||||
textSizeChanged()
|
textSizeChanged()
|
||||||
{
|
{
|
||||||
this.userProfile.textSizeChanged();
|
this.profileService.textSizeChanged();
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsMenu()
|
actionsMenu()
|
||||||
{
|
{
|
||||||
this.menu.open('actions');
|
this.menu.open('actions');
|
||||||
@ -167,9 +154,9 @@ export class SearchPage implements OnInit
|
|||||||
text: 'Save',
|
text: 'Save',
|
||||||
handler: data =>
|
handler: data =>
|
||||||
{
|
{
|
||||||
const p = { queries: this.userProfile.user.items.slice(), title: data.title };
|
const p = { queries: this.profileService.profile().items.slice(), title: data.title };
|
||||||
this.userProfile.user.saved_pages.push(p);
|
this.profileService.profile().saved_pages.push(p);
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save();
|
||||||
this.pagesService.addPage(p);
|
this.pagesService.addPage(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,12 +167,12 @@ export class SearchPage implements OnInit
|
|||||||
|
|
||||||
updatePage()
|
updatePage()
|
||||||
{
|
{
|
||||||
const page = this.userProfile.user.saved_pages.find(
|
const page = this.profileService.profile().saved_pages.find(
|
||||||
i =>
|
i =>
|
||||||
i.title === this.params.data.title
|
i.title === this.params.data.title
|
||||||
);
|
);
|
||||||
page.queries = this.userProfile.user.items.slice();
|
page.queries = this.profileService.profile().items.slice();
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuery(searchbar)
|
setQuery(searchbar)
|
||||||
@ -222,31 +209,31 @@ export class SearchPage implements OnInit
|
|||||||
|
|
||||||
removeItem(item)
|
removeItem(item)
|
||||||
{
|
{
|
||||||
const idx = this.userProfile.user.items.indexOf(item);
|
const idx = this.profileService.profile().items.indexOf(item);
|
||||||
this.userProfile.user.items.splice(idx, 1);
|
this.profileService.profile().items.splice(idx, 1);
|
||||||
|
|
||||||
// save the users settings.
|
// save the users settings.
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save();
|
||||||
}
|
}
|
||||||
addItemToList(item: CardItem)
|
addItemToList(item: CardItem)
|
||||||
{
|
{
|
||||||
if (this.userProfile.user.append_to_bottom)
|
if (this.profileService.profile().append_to_bottom)
|
||||||
{
|
{
|
||||||
if (this.last != null && this.userProfile.user.insert_next_to_item)
|
if (this.last != null && this.profileService.profile().insert_next_to_item)
|
||||||
{
|
{
|
||||||
const idx = this.userProfile.user.items.indexOf(this.last);
|
const idx = this.profileService.profile().items.indexOf(this.last);
|
||||||
this.userProfile.user.items.splice(idx + 1, 0, item);
|
this.profileService.profile().items.splice(idx + 1, 0, item);
|
||||||
} else
|
} else
|
||||||
this.userProfile.user.items.push(item);
|
this.profileService.profile().items.push(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (this.last != null && this.userProfile.user.insert_next_to_item)
|
if (this.last != null && this.profileService.profile().insert_next_to_item)
|
||||||
{
|
{
|
||||||
const idx = this.userProfile.user.items.indexOf(this.last);
|
const idx = this.profileService.profile().items.indexOf(this.last);
|
||||||
this.userProfile.user.items.splice(idx, 0, item);
|
this.profileService.profile().items.splice(idx, 0, item);
|
||||||
} else
|
} else
|
||||||
this.userProfile.user.items.unshift(item);
|
this.profileService.profile().items.unshift(item);
|
||||||
}
|
}
|
||||||
this.last = null;
|
this.last = null;
|
||||||
}
|
}
|
||||||
@ -300,10 +287,10 @@ export class SearchPage implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.userProfile.user.clear_search_after_query)
|
if (this.profileService.profile().clear_search_after_query)
|
||||||
$('.searchbar-input').val('');
|
$('.searchbar-input').val('');
|
||||||
|
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save();
|
||||||
}
|
}
|
||||||
catch (error)
|
catch (error)
|
||||||
{
|
{
|
||||||
@ -325,7 +312,7 @@ export class SearchPage implements OnInit
|
|||||||
{
|
{
|
||||||
for (let item of lst)
|
for (let item of lst)
|
||||||
{
|
{
|
||||||
if (item.type === 'Strongs' && this.userProfile.user.strongs_modal && !from_search_bar)
|
if (item.type === 'Strongs' && this.profileService.profile().strongs_modal && !from_search_bar)
|
||||||
{
|
{
|
||||||
const modal = this.modalCtrl.create(StrongsModal, { sn: parseInt(item.qry), dict: item.dict, onItemClicked: this });
|
const modal = this.modalCtrl.create(StrongsModal, { sn: parseInt(item.qry), dict: item.dict, onItemClicked: this });
|
||||||
modal.present();
|
modal.present();
|
||||||
|
@ -7,37 +7,47 @@
|
|||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content padding>
|
<ion-content padding>
|
||||||
<ng-template [ngIf]="userProfile.user">
|
<ng-template [ngIf]="profileService.profile()">
|
||||||
<h4>Search Settings</h4>
|
<h4>Search Settings</h4>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<button ion-button (click)="reset()">Reset Settings</button>
|
<button ion-button (click)="profileService.reset()">Reset Settings</button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
|
<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-item>
|
<ion-item>
|
||||||
<ion-label>Show Strongs as Modal</ion-label>
|
<ion-label>Show Strongs as Modal</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.strongs_modal" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="profileService.profile().strongs_modal" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Clear Search after Query</ion-label>
|
<ion-label>Clear Search after Query</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.clear_search_after_query" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="profileService.profile().clear_search_after_query" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Append Results Below</ion-label>
|
<ion-label>Append Results Below</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.append_to_bottom" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="profileService.profile().append_to_bottom" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Insert Result Next to Item</ion-label>
|
<ion-label>Insert Result Next to Item</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.insert_next_to_item" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="profileService.profile().insert_next_to_item" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Each Verse on New Line</ion-label>
|
<ion-label>Each Verse on New Line</ion-label>
|
||||||
<ion-toggle color="dark" [(ngModel)]="userProfile.user.verses_on_new_line" (ionChange)="save()"></ion-toggle>
|
<ion-toggle color="dark" [(ngModel)]="profileService.profile().verses_on_new_line" (ionChange)="save()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<h4>Adjust Text</h4>
|
<h4>Adjust Text</h4>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-range min="6" max="20" step="1" snaps="true" [(ngModel)]="userProfile.user.font_size" (ionChange)="textSizeChanged()">
|
<ion-range min="6" max="20" step="1" snaps="true" [(ngModel)]="profileService.profile().font_size" (ionChange)="textSizeChanged()">
|
||||||
<ion-label range-left class="small-text">A</ion-label>
|
<ion-label range-left class="small-text">A</ion-label>
|
||||||
<ion-label range-right>A</ion-label>
|
<ion-label range-right>A</ion-label>
|
||||||
</ion-range>
|
</ion-range>
|
||||||
@ -46,7 +56,7 @@
|
|||||||
|
|
||||||
<h4>Manage Pages</h4>
|
<h4>Manage Pages</h4>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item *ngFor="let p of userProfile.user.saved_pages">
|
<ion-item *ngFor="let p of profileService.profile().saved_pages">
|
||||||
{{p.title}}
|
{{p.title}}
|
||||||
<button ion-button item-end outline icon-end (click)="removePage(p)">
|
<button ion-button item-end outline icon-end (click)="removePage(p)">
|
||||||
Delete Page <ion-icon name="trash"></ion-icon>
|
Delete Page <ion-icon name="trash"></ion-icon>
|
||||||
|
@ -2,53 +2,35 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { NavController, AlertController } from 'ionic-angular';
|
import { NavController, AlertController } from 'ionic-angular';
|
||||||
import { Storage } from '@ionic/storage';
|
import { Storage } from '@ionic/storage';
|
||||||
import { SavedPage, UserProfile } from '../../libs/UserProfile';
|
|
||||||
|
import { ProfileService, SavedPage } from '../../services/profile-service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'settings',
|
selector: 'settings',
|
||||||
templateUrl: 'settings.html'
|
templateUrl: 'settings.html',
|
||||||
})
|
})
|
||||||
export class SettingsPage
|
export class SettingsPage
|
||||||
{
|
{
|
||||||
textSize = 0;
|
|
||||||
userProfile: UserProfile;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public navCtrl: NavController
|
public navCtrl: NavController
|
||||||
, public local: Storage
|
, private alertCtrl: AlertController
|
||||||
, private alertCtrl: AlertController)
|
, public profileService: ProfileService
|
||||||
{
|
) {}
|
||||||
this.userProfile = new UserProfile(UserProfile.createDefaultUser());
|
|
||||||
|
|
||||||
// Check if there is a profile saved in local storage
|
|
||||||
this.local.get('profile').then(profile =>
|
|
||||||
{
|
|
||||||
let t = this.userProfile;
|
|
||||||
|
|
||||||
if (profile !== null)
|
|
||||||
t = JSON.parse(profile);
|
|
||||||
|
|
||||||
this.userProfile.update(t, local);
|
|
||||||
}).catch(error =>
|
|
||||||
{
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
textSizeChanged()
|
textSizeChanged()
|
||||||
{
|
{
|
||||||
this.userProfile.textSizeChanged();
|
this.profileService.textSizeChanged();
|
||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
save()
|
save()
|
||||||
{
|
{
|
||||||
this.userProfile.save(this.local);
|
this.profileService.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
{
|
{
|
||||||
this.userProfile.reset(this.local);
|
this.profileService.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
removePage(page: SavedPage)
|
removePage(page: SavedPage)
|
||||||
@ -69,11 +51,7 @@ export class SettingsPage
|
|||||||
text: 'Ok',
|
text: 'Ok',
|
||||||
handler: () =>
|
handler: () =>
|
||||||
{
|
{
|
||||||
let idx = this.userProfile.user.saved_pages.indexOf(page);
|
this.profileService.removePage(page);
|
||||||
this.userProfile.user.saved_pages.splice(idx, 1);
|
|
||||||
|
|
||||||
// save the users settings.
|
|
||||||
this.userProfile.save(this.local);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -4,7 +4,7 @@ import { SearchPage } from '../pages/search/search';
|
|||||||
import { SettingsPage } from '../pages/settings/settings';
|
import { SettingsPage } from '../pages/settings/settings';
|
||||||
import { HelpPage } from '../pages/help/help';
|
import { HelpPage } from '../pages/help/help';
|
||||||
|
|
||||||
import { SavedPage } from '../libs/UserProfile';
|
import { SavedPage } from './profile-service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PagesService
|
export class PagesService
|
||||||
|
218
DynamicBibleIonic/src/services/profile-service.ts
Normal file
218
DynamicBibleIonic/src/services/profile-service.ts
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/// <reference path="../../typings/globals/jquery/index.d.ts" />
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
|
||||||
|
import { AngularFireAuth } from 'angularfire2/auth';
|
||||||
|
import * as firebase from 'firebase/app';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Catch } from 'rxjs/add/operator';
|
||||||
|
import { Storage } from '@ionic/storage';
|
||||||
|
|
||||||
|
import { CardItem } from '../pages/search/search';
|
||||||
|
|
||||||
|
type fbObject<T> = {
|
||||||
|
ref: AngularFireObject<T>,
|
||||||
|
stream: Observable<T>,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_USER_NAME = 'john_doe';
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
username: string,
|
||||||
|
uid: string|null,
|
||||||
|
strongs_modal: boolean,
|
||||||
|
clear_search_after_query: boolean,
|
||||||
|
items: CardItem[],
|
||||||
|
append_to_bottom: boolean,
|
||||||
|
insert_next_to_item: boolean,
|
||||||
|
font_size: number,
|
||||||
|
saved_pages: SavedPage[],
|
||||||
|
verses_on_new_line: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SavedPage = {
|
||||||
|
queries: CardItem[],
|
||||||
|
title: string,
|
||||||
|
}
|
||||||
|
@Injectable()
|
||||||
|
export class ProfileService {
|
||||||
|
localProfile: User;
|
||||||
|
remoteProfile: fbObject<User> | null;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private local: Storage
|
||||||
|
, private db: AngularFireDatabase
|
||||||
|
, public fbAuth: AngularFireAuth
|
||||||
|
)
|
||||||
|
{
|
||||||
|
console.log("Setting up default user initially");
|
||||||
|
this.fbAuth.authState.subscribe(state => this.subscribeToRemoteProfile(db, state));
|
||||||
|
let localObserver = this.userObserver().subscribe(
|
||||||
|
user => {
|
||||||
|
this.update(user);
|
||||||
|
this.localProfile = user;
|
||||||
|
},
|
||||||
|
error => console.log(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
userObserver(): Observable<User> {
|
||||||
|
return Observable.fromPromise(this.local.get('profile')).map(json_profile => {
|
||||||
|
let t = this.profile();
|
||||||
|
|
||||||
|
if (json_profile !== null) t = JSON.parse(json_profile);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile(): User {
|
||||||
|
if (!this.localProfile)
|
||||||
|
{
|
||||||
|
console.log("Initializing default user");
|
||||||
|
this.localProfile = ProfileService.createDefaultUser();
|
||||||
|
}
|
||||||
|
console.log("Returning Profile with user: " + this.localProfile);
|
||||||
|
return this.localProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToRemoteProfile(db: AngularFireDatabase, user: firebase.User)
|
||||||
|
{
|
||||||
|
if (!user) return;
|
||||||
|
console.log("Subscribing to remote settings for user id%s", user.uid);
|
||||||
|
let obj = db.object(
|
||||||
|
'/settings/' + user.uid);
|
||||||
|
this.remoteProfile = {
|
||||||
|
ref: obj,
|
||||||
|
stream: obj.valueChanges(),
|
||||||
|
};
|
||||||
|
this.profile().username = user.displayName;
|
||||||
|
this.save();
|
||||||
|
this.remoteProfile.stream.subscribe(
|
||||||
|
user => this.handleRemotePreferenceChange(user),
|
||||||
|
error => console.log(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRemotePreferenceChange(user: User)
|
||||||
|
{
|
||||||
|
if (user) {
|
||||||
|
console.log("handling remote settings for user %s", user.username);
|
||||||
|
if (!user.saved_pages) user.saved_pages = [];
|
||||||
|
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.
|
||||||
|
this.localSave();
|
||||||
|
console.log("Saved remote changes locally");
|
||||||
|
} else {
|
||||||
|
// 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()
|
||||||
|
console.log("Saved remote for user %s", user.username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentUser(): firebase.User
|
||||||
|
{
|
||||||
|
return this.fbAuth.auth.currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate()
|
||||||
|
{
|
||||||
|
this.fbAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
logout()
|
||||||
|
{
|
||||||
|
this.fbAuth.auth.signOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
private localSave()
|
||||||
|
{
|
||||||
|
this.local.set('profile', JSON.stringify(this.profile()));
|
||||||
|
}
|
||||||
|
|
||||||
|
save()
|
||||||
|
{
|
||||||
|
// First we save our local copy of the settings.
|
||||||
|
this.localSave();
|
||||||
|
// If we have a remote profile then save it there too
|
||||||
|
if (this.remoteProfile) {
|
||||||
|
console.log("Saving remote settings profile for remote user id " + this.profile().uid);
|
||||||
|
this.remoteProfile.ref.set(this.profile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(t: User): boolean
|
||||||
|
{
|
||||||
|
let updated = false;
|
||||||
|
let k;
|
||||||
|
const user = this.localProfile;
|
||||||
|
for (k in user)
|
||||||
|
{
|
||||||
|
if (user.hasOwnProperty(k))
|
||||||
|
{
|
||||||
|
if (t[k] === undefined)
|
||||||
|
{
|
||||||
|
t[k] = user[k];
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k in user)
|
||||||
|
if (user.hasOwnProperty(k))
|
||||||
|
user[k] = t[k];
|
||||||
|
|
||||||
|
this.textSizeChanged();
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private resetUser()
|
||||||
|
{
|
||||||
|
this.localProfile.strongs_modal = true;
|
||||||
|
this.localProfile.clear_search_after_query = false;
|
||||||
|
this.localProfile.items = [];
|
||||||
|
this.localProfile.append_to_bottom = false;
|
||||||
|
this.localProfile.insert_next_to_item = false;
|
||||||
|
this.localProfile.font_size = 10;
|
||||||
|
this.localProfile.saved_pages = [];
|
||||||
|
this.localProfile.verses_on_new_line = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset()
|
||||||
|
{
|
||||||
|
this.resetUser();
|
||||||
|
this.remoteProfile.ref.set(this.localProfile)
|
||||||
|
this.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
removePage(page: SavedPage)
|
||||||
|
{
|
||||||
|
let idx = this.localProfile.saved_pages.indexOf(page);
|
||||||
|
this.localProfile.saved_pages.splice(idx, 1);
|
||||||
|
|
||||||
|
// save the users settings.
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jwall): This belongs somewhere else.
|
||||||
|
public textSizeChanged()
|
||||||
|
{
|
||||||
|
$('html').css('font-size', this.localProfile.font_size + 'px');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createDefaultUser(): User
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
username: DEFAULT_USER_NAME,
|
||||||
|
uid: null,
|
||||||
|
strongs_modal: true,
|
||||||
|
clear_search_after_query: false,
|
||||||
|
items: [],
|
||||||
|
append_to_bottom: false,
|
||||||
|
insert_next_to_item: false,
|
||||||
|
font_size: 10,
|
||||||
|
saved_pages: [],
|
||||||
|
verses_on_new_line: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user