mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-25 00:09:54 -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/bin
|
||||
DynamicBibleIonic/.vscode
|
||||
DynamicBibleIonic/www/assets/
|
||||
DynamicBibleUtility/.vs
|
||||
DynamicBibleIonic/platforms/android/release-signing.properties
|
||||
DynamicBibleIonic/platforms/android/build
|
||||
|
@ -42,18 +42,18 @@ export class MyApp
|
||||
{
|
||||
// close the menu when clicking a link from the menu
|
||||
this.menu.close('pages');
|
||||
|
||||
// because the actions menu is on a Page component, and you swap the SearchPage out,
|
||||
// the menu get registered multiple times. to avoid some pages not opening the menu because
|
||||
// multiple menus with the same id exist and the first one in the list is returned (which happens
|
||||
// be disabled when another of the same id is added) it won't show. because not enabled.
|
||||
// ---
|
||||
// unregistering the actions menu whenever a new page is opened fixes the problem, because the menu
|
||||
// will get reregistered when SearchPage loads. Also, if you go to a non SearchPage, the actions
|
||||
// menu won't be there, but the unregister function doesn't fail if a non existent id is given,
|
||||
|
||||
// because the actions menu is on a Page component, and you swap the SearchPage out,
|
||||
// the menu get registered multiple times. to avoid some pages not opening the menu because
|
||||
// multiple menus with the same id exist and the first one in the list is returned (which happens
|
||||
// be disabled when another of the same id is added) it won't show. because not enabled.
|
||||
// ---
|
||||
// unregistering the actions menu whenever a new page is opened fixes the problem, because the menu
|
||||
// will get reregistered when SearchPage loads. Also, if you go to a non SearchPage, the actions
|
||||
// menu won't be there, but the unregister function doesn't fail if a non existent id is given,
|
||||
// so thats ok.
|
||||
this.menu._unregister(this.menu.get('actions'));
|
||||
|
||||
|
||||
// navigate to the new page if it is not the current page
|
||||
this.nav.setRoot(page.component, page.params);
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { ProfileService } from './../services/profile-service';
|
||||
import { NgModule, ErrorHandler } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
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 {AngularFireModule } from 'angularfire2';
|
||||
import { AngularFireAuthModule } from 'angularfire2/auth';
|
||||
import { AngularFireDatabaseModule } from 'angularfire2/database';
|
||||
|
||||
export const firebaseConfig = {
|
||||
apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8',
|
||||
@ -55,7 +58,9 @@ export const firebaseConfig = {
|
||||
IonicStorageModule.forRoot(),
|
||||
BrowserModule,
|
||||
HttpModule,
|
||||
AngularFireModule.initializeApp(firebaseConfig)
|
||||
AngularFireModule.initializeApp(firebaseConfig),
|
||||
AngularFireAuthModule,
|
||||
AngularFireDatabaseModule,
|
||||
],
|
||||
bootstrap: [IonicApp],
|
||||
entryComponents: [
|
||||
@ -71,6 +76,6 @@ export const firebaseConfig = {
|
||||
Error,
|
||||
ErrorMessage
|
||||
],
|
||||
providers: [{ provide: ErrorHandler, useClass: IonicErrorHandler }, StatusBar, SplashScreen]
|
||||
providers: [{ provide: ErrorHandler, useClass: IonicErrorHandler }, StatusBar, SplashScreen, ProfileService]
|
||||
})
|
||||
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-item>
|
||||
<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-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-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-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-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-list-header>Adjust Text</ion-list-header>
|
||||
<ion-list>
|
||||
<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-right>A</ion-label>
|
||||
</ion-range>
|
||||
@ -70,10 +70,10 @@
|
||||
</ion-header>
|
||||
|
||||
<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)"
|
||||
[cardItem]="item"
|
||||
[versesOnNewLine]="userProfile.user.verses_on_new_line"
|
||||
[versesOnNewLine]="this.profileService.profile().verses_on_new_line"
|
||||
(onClose)="removeItem($event)"
|
||||
(onItemClicked)="getItemsNextToCard($event)"></passage>
|
||||
<strongs *ngIf="isStrongs(item.type)"
|
||||
@ -88,4 +88,4 @@
|
||||
[cardItem]="item"
|
||||
(onClose)="removeItem($event)"></error>
|
||||
</ion-card>
|
||||
</ion-content>
|
||||
</ion-content>
|
||||
|
@ -5,7 +5,7 @@ import { Storage } from '@ionic/storage';
|
||||
import { StrongsModal } from '../../components/strongs-modal/strongs-modal';
|
||||
import { PagesService } from '../../services/pages-service';
|
||||
|
||||
import { UserProfile } from '../../libs/UserProfile';
|
||||
import { ProfileService, User } from './../../services/profile-service';
|
||||
import { Reference } from '../../libs/Reference';
|
||||
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
|
||||
{
|
||||
searchQuery = '';
|
||||
userProfile: UserProfile;
|
||||
last: CardItem;
|
||||
loader: Loading;
|
||||
title: string;
|
||||
@ -26,57 +25,44 @@ export class SearchPage implements OnInit
|
||||
, private menu: MenuController
|
||||
, public loadingCtrl: LoadingController
|
||||
, public modalCtrl: ModalController
|
||||
, public local: Storage
|
||||
, public profileService: ProfileService
|
||||
, 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
|
||||
this.local.get('profile').then(profile =>
|
||||
{
|
||||
let t = this.userProfile;
|
||||
this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
|
||||
this.loader.present().then(() =>
|
||||
{
|
||||
this.initializeItems(t);
|
||||
|
||||
if (profile !== null)
|
||||
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)
|
||||
this.loader.dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
initializeItems(u: User)
|
||||
{
|
||||
// migrate old way of storing card items to the new.
|
||||
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'].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)
|
||||
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)
|
||||
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)
|
||||
u.user.items[i] = {
|
||||
u.items[i] = {
|
||||
qry: ci['data'].sn,
|
||||
dict: ci['prefix'] === 'G' ? 'grk' : 'heb',
|
||||
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)
|
||||
{
|
||||
@ -116,32 +102,33 @@ export class SearchPage implements OnInit
|
||||
}
|
||||
|
||||
// initialize the pages.
|
||||
this.pagesService.initializePages(u.user.saved_pages);
|
||||
|
||||
if (this.params.data.queries !== undefined)
|
||||
this.userProfile.user.items = this.params.data.queries.slice();
|
||||
|
||||
if (this.params.data.title === undefined)
|
||||
this.title = 'Search';
|
||||
else
|
||||
this.title = this.params.data.title;
|
||||
this.pagesService.initializePages(u.saved_pages);
|
||||
|
||||
if (has_migrated)
|
||||
this.userProfile.save(this.local);
|
||||
if (this.params.data.queries !== undefined)
|
||||
this.profileService.profile().items = this.params.data.queries.slice();
|
||||
|
||||
if (this.params.data.title === undefined)
|
||||
this.title = 'Search';
|
||||
else
|
||||
this.title = this.params.data.title;
|
||||
|
||||
if (has_migrated)
|
||||
this.profileService.save();
|
||||
}
|
||||
|
||||
save()
|
||||
{
|
||||
this.userProfile.save(this.local);
|
||||
this.profileService.save();
|
||||
}
|
||||
textSizeChanged()
|
||||
{
|
||||
this.userProfile.textSizeChanged();
|
||||
this.profileService.textSizeChanged();
|
||||
this.save();
|
||||
}
|
||||
actionsMenu()
|
||||
{
|
||||
this.menu.open('actions');
|
||||
}
|
||||
|
||||
actionsMenu()
|
||||
{
|
||||
this.menu.open('actions');
|
||||
}
|
||||
|
||||
addPage()
|
||||
@ -167,9 +154,9 @@ export class SearchPage implements OnInit
|
||||
text: 'Save',
|
||||
handler: data =>
|
||||
{
|
||||
const p = { queries: this.userProfile.user.items.slice(), title: data.title };
|
||||
this.userProfile.user.saved_pages.push(p);
|
||||
this.userProfile.save(this.local);
|
||||
const p = { queries: this.profileService.profile().items.slice(), title: data.title };
|
||||
this.profileService.profile().saved_pages.push(p);
|
||||
this.profileService.save();
|
||||
this.pagesService.addPage(p);
|
||||
}
|
||||
}
|
||||
@ -178,14 +165,14 @@ export class SearchPage implements OnInit
|
||||
alert.present();
|
||||
}
|
||||
|
||||
updatePage()
|
||||
updatePage()
|
||||
{
|
||||
const page = this.userProfile.user.saved_pages.find(
|
||||
const page = this.profileService.profile().saved_pages.find(
|
||||
i =>
|
||||
i.title === this.params.data.title
|
||||
);
|
||||
page.queries = this.userProfile.user.items.slice();
|
||||
this.userProfile.save(this.local);
|
||||
page.queries = this.profileService.profile().items.slice();
|
||||
this.profileService.save();
|
||||
}
|
||||
|
||||
setQuery(searchbar)
|
||||
@ -222,31 +209,31 @@ export class SearchPage implements OnInit
|
||||
|
||||
removeItem(item)
|
||||
{
|
||||
const idx = this.userProfile.user.items.indexOf(item);
|
||||
this.userProfile.user.items.splice(idx, 1);
|
||||
const idx = this.profileService.profile().items.indexOf(item);
|
||||
this.profileService.profile().items.splice(idx, 1);
|
||||
|
||||
// save the users settings.
|
||||
this.userProfile.save(this.local);
|
||||
this.profileService.save();
|
||||
}
|
||||
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);
|
||||
this.userProfile.user.items.splice(idx + 1, 0, item);
|
||||
const idx = this.profileService.profile().items.indexOf(this.last);
|
||||
this.profileService.profile().items.splice(idx + 1, 0, item);
|
||||
} else
|
||||
this.userProfile.user.items.push(item);
|
||||
this.profileService.profile().items.push(item);
|
||||
}
|
||||
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);
|
||||
this.userProfile.user.items.splice(idx, 0, item);
|
||||
const idx = this.profileService.profile().items.indexOf(this.last);
|
||||
this.profileService.profile().items.splice(idx, 0, item);
|
||||
} else
|
||||
this.userProfile.user.items.unshift(item);
|
||||
this.profileService.profile().items.unshift(item);
|
||||
}
|
||||
this.last = null;
|
||||
}
|
||||
@ -258,7 +245,7 @@ export class SearchPage implements OnInit
|
||||
|
||||
getItemList(search: string): Promise<CardItem[]>
|
||||
{
|
||||
return new Promise((resolve) =>
|
||||
return new Promise((resolve) =>
|
||||
{
|
||||
const list: CardItem[] = [];
|
||||
|
||||
@ -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('');
|
||||
|
||||
this.userProfile.save(this.local);
|
||||
this.profileService.save();
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
@ -317,7 +304,7 @@ export class SearchPage implements OnInit
|
||||
|
||||
updateUIwithItems(search: string, from_search_bar: boolean)
|
||||
{
|
||||
this.getItemList(search).then(lst =>
|
||||
this.getItemList(search).then(lst =>
|
||||
{
|
||||
this.loader = this.loadingCtrl.create({ content: 'Looking up Query...' });
|
||||
this.loader.present().then(
|
||||
@ -325,7 +312,7 @@ export class SearchPage implements OnInit
|
||||
{
|
||||
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 });
|
||||
modal.present();
|
||||
@ -340,7 +327,7 @@ export class SearchPage implements OnInit
|
||||
}
|
||||
|
||||
export type OpenData = { card: CardItem, qry: string, from_search_bar: boolean }
|
||||
|
||||
|
||||
export type CardItem = { qry: string, type: string, dict: string }
|
||||
|
||||
class Item
|
||||
|
@ -7,37 +7,47 @@
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
<ng-template [ngIf]="userProfile.user">
|
||||
<ng-template [ngIf]="profileService.profile()">
|
||||
<h4>Search Settings</h4>
|
||||
<ion-item>
|
||||
<button ion-button (click)="reset()">Reset Settings</button>
|
||||
<button ion-button (click)="profileService.reset()">Reset Settings</button>
|
||||
</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-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-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-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-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-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>
|
||||
|
||||
<h4>Adjust Text</h4>
|
||||
<ion-list>
|
||||
<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-right>A</ion-label>
|
||||
</ion-range>
|
||||
@ -46,7 +56,7 @@
|
||||
|
||||
<h4>Manage Pages</h4>
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let p of userProfile.user.saved_pages">
|
||||
<ion-item *ngFor="let p of profileService.profile().saved_pages">
|
||||
{{p.title}}
|
||||
<button ion-button item-end outline icon-end (click)="removePage(p)">
|
||||
Delete Page <ion-icon name="trash"></ion-icon>
|
||||
@ -54,4 +64,4 @@
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ng-template>
|
||||
</ion-content>
|
||||
</ion-content>
|
||||
|
@ -2,53 +2,35 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { NavController, AlertController } from 'ionic-angular';
|
||||
import { Storage } from '@ionic/storage';
|
||||
import { SavedPage, UserProfile } from '../../libs/UserProfile';
|
||||
|
||||
import { ProfileService, SavedPage } from '../../services/profile-service';
|
||||
|
||||
@Component({
|
||||
selector: 'settings',
|
||||
templateUrl: 'settings.html'
|
||||
templateUrl: 'settings.html',
|
||||
})
|
||||
export class SettingsPage
|
||||
{
|
||||
textSize = 0;
|
||||
userProfile: UserProfile;
|
||||
|
||||
constructor(
|
||||
public navCtrl: NavController
|
||||
, public local: Storage
|
||||
, private alertCtrl: AlertController)
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
, private alertCtrl: AlertController
|
||||
, public profileService: ProfileService
|
||||
) {}
|
||||
|
||||
textSizeChanged()
|
||||
{
|
||||
this.userProfile.textSizeChanged();
|
||||
this.profileService.textSizeChanged();
|
||||
this.save();
|
||||
}
|
||||
|
||||
save()
|
||||
{
|
||||
this.userProfile.save(this.local);
|
||||
this.profileService.save()
|
||||
}
|
||||
|
||||
reset()
|
||||
{
|
||||
this.userProfile.reset(this.local);
|
||||
this.profileService.reset()
|
||||
}
|
||||
|
||||
removePage(page: SavedPage)
|
||||
@ -69,15 +51,11 @@ export class SettingsPage
|
||||
text: 'Ok',
|
||||
handler: () =>
|
||||
{
|
||||
let idx = this.userProfile.user.saved_pages.indexOf(page);
|
||||
this.userProfile.user.saved_pages.splice(idx, 1);
|
||||
|
||||
// save the users settings.
|
||||
this.userProfile.save(this.local);
|
||||
this.profileService.removePage(page);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
alert.present();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Storage } from '@ionic/storage';
|
||||
import { SearchPage } from '../pages/search/search';
|
||||
import { SearchPage } from '../pages/search/search';
|
||||
import { SettingsPage } from '../pages/settings/settings';
|
||||
import { HelpPage } from '../pages/help/help';
|
||||
|
||||
import { SavedPage } from '../libs/UserProfile';
|
||||
import { SavedPage } from './profile-service';
|
||||
|
||||
@Injectable()
|
||||
export class PagesService
|
||||
@ -14,10 +14,10 @@ export class PagesService
|
||||
|
||||
constructor(public local: Storage)
|
||||
{
|
||||
this.pages = [
|
||||
{ title: 'Search', component: SearchPage, params: { queries: [], title: 'Search' }, icon: 'search' },
|
||||
{ title: 'Settings', component: SettingsPage, params: {}, icon: 'settings' },
|
||||
{ title: 'Help', component: HelpPage, params: {}, icon: 'help-circle' }
|
||||
this.pages = [
|
||||
{ title: 'Search', component: SearchPage, params: { queries: [], title: 'Search' }, icon: 'search' },
|
||||
{ title: 'Settings', component: SettingsPage, params: {}, icon: 'settings' },
|
||||
{ title: 'Help', component: HelpPage, params: {}, icon: 'help-circle' }
|
||||
];
|
||||
this.savedPages = [];
|
||||
}
|
||||
@ -46,4 +46,4 @@ export class PagesService
|
||||
this.savedPages.push({ title: p.title, component: SearchPage, params: { queries: p.queries, title: p.title } });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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