217 lines
6.1 KiB
TypeScript

/// <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 as AngularFireObject<User>,
stream: obj.valueChanges() as Observable<User>,
};
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
};
}
}