mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-25 16:29:49 -04:00
FIX: Fixed performanc bug in paragraph support.
* apparently, if you do an ngFor on the result of function call that returns a new array each time its called, it will screw up the template watching code such that every action will necessitate a rerendering of the information even if it hasn't changed.
This commit is contained in:
parent
5a54a1a803
commit
7a0bc2f2b2
File diff suppressed because one or more lines are too long
@ -67,35 +67,35 @@
|
||||
<feature name="SplashScreen">
|
||||
<param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" />
|
||||
</feature>
|
||||
<plugin name="cordova-plugin-console" spec="^1.0.5" />
|
||||
<plugin name="cordova-plugin-crosswalk-webview" spec="^2.3.0">
|
||||
<variable name="XWALK_VERSION" value="23+" />
|
||||
<variable name="XWALK_LITEVERSION" value="xwalk_core_library_canary:17+" />
|
||||
<variable name="XWALK_COMMANDLINE" value="--disable-pull-to-refresh-effect" />
|
||||
<variable name="XWALK_MODE" value="embedded" />
|
||||
<variable name="XWALK_MULTIPLEAPK" value="true" />
|
||||
</plugin>
|
||||
<plugin name="cordova-plugin-device" spec="^1.1.4" />
|
||||
<plugin name="cordova-plugin-splashscreen" spec="^4.0.3" />
|
||||
<plugin name="cordova-plugin-statusbar" spec="^2.2.3" />
|
||||
<plugin name="cordova-plugin-whitelist" spec="^1.3.1" />
|
||||
<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
|
||||
<universal-links>
|
||||
<host name="bhgx5.app.goo.gl/XktS" scheme="https" />
|
||||
<host name="dynamicbible-7c6cf.firebaseapp.com" scheme="https">
|
||||
<path url="/__/auth/callback" />
|
||||
</host>
|
||||
</universal-links>
|
||||
<preference name="AndroidLaunchMode" value="singleTask" />
|
||||
<plugin name="cordova-plugin-console" spec="^1.1.0" />
|
||||
<plugin name="cordova-plugin-crosswalk-webview" spec="^2.4.0">
|
||||
<variable name="XWALK_VERSION" value="23+" />
|
||||
<variable name="XWALK_LITEVERSION" value="xwalk_core_library_canary:17+" />
|
||||
<variable name="XWALK_COMMANDLINE" value="--disable-pull-to-refresh-effect" />
|
||||
<variable name="XWALK_MODE" value="embedded" />
|
||||
<variable name="XWALK_MULTIPLEAPK" value="true" />
|
||||
</plugin>
|
||||
<plugin name="cordova-plugin-device" spec="^1.1.7" />
|
||||
<plugin name="cordova-plugin-splashscreen" spec="^4.1.0" />
|
||||
<plugin name="cordova-plugin-statusbar" spec="^2.4.1" />
|
||||
<plugin name="cordova-plugin-whitelist" spec="^1.3.3" />
|
||||
<plugin name="ionic-plugin-keyboard" spec="^2.2.1" />
|
||||
<plugin name="cordova-universal-links-plugin" spec="^1.2.1" />
|
||||
<plugin name="cordova-plugin-buildinfo" spec="^2.0.1" />
|
||||
<plugin name="cordova-plugin-browsertab" spec="^0.2.0" />
|
||||
<plugin name="cordova-plugin-inappbrowser" spec="^2.0.1" />
|
||||
<plugin name="cordova-plugin-inappbrowser" spec="^2.0.2" />
|
||||
<plugin name="cordova-plugin-customurlscheme" spec="^4.3.0">
|
||||
<variable name="URL_SCHEME" value="com.firebase.cordova" />
|
||||
<variable name="ANDROID_SCHEME" value=" " />
|
||||
<variable name="ANDROID_HOST" value=" " />
|
||||
<variable name="ANDROID_PATHPREFIX" value="/" />
|
||||
</plugin>
|
||||
<preference name="AndroidLaunchMode" value="singleTask" />
|
||||
<engine name="android" spec="6.2.3" />
|
||||
</widget>
|
||||
|
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var rootdir = process.argv[2];
|
||||
|
||||
if (rootdir)
|
||||
{
|
||||
console.log("Root: " + rootdir);
|
||||
|
||||
// go through each of the platform directories that have been prepared
|
||||
var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
|
||||
|
||||
for (var x = 0; x < platforms.length; x++)
|
||||
{
|
||||
// // open up the index.html file at the www root
|
||||
// try
|
||||
// {
|
||||
// var platform = platforms[x].trim().toLowerCase();
|
||||
// var testBuildPath;
|
||||
|
||||
// if (platform === 'android')
|
||||
// {
|
||||
// testBuildPath = path.join(rootdir, 'platforms', platform, 'app', 'assets', 'www', 'build');
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// testBuildPath = path.join(rootdir, 'platforms', platform, 'app', 'www', 'build');
|
||||
// }
|
||||
|
||||
// if (fs.existsSync(testBuildPath))
|
||||
// {
|
||||
// console.log('Removing map files from assets after prepare: ' + testBuildPath);
|
||||
// fs.unlinkSync(testBuildPath + '/vendor.js.map');
|
||||
// fs.unlinkSync(testBuildPath + '/main.js.map');
|
||||
// fs.unlinkSync(testBuildPath + '/main.css.map');
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// console.log('Build dir @ ' + testBuildPath + ' does not exist for removal');
|
||||
// }
|
||||
// } catch (e)
|
||||
// {
|
||||
// process.stdout.write(e);
|
||||
// }
|
||||
}
|
||||
}
|
1578
DynamicBibleIonic/package-lock.json
generated
1578
DynamicBibleIonic/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,6 @@
|
||||
"test-coverage": "ng test --code-coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/cli": "1.6.3",
|
||||
"@angular/common": "5.0.0",
|
||||
"@angular/compiler": "5.0.0",
|
||||
"@angular/compiler-cli": "5.0.0",
|
||||
@ -38,10 +37,10 @@
|
||||
"cordova-plugin-buildinfo": "^2.0.1",
|
||||
"cordova-plugin-compat": "^1.2.0",
|
||||
"cordova-plugin-console": "^1.1.0",
|
||||
"cordova-plugin-crosswalk-webview": "^2.3.0",
|
||||
"cordova-plugin-crosswalk-webview": "^2.4.0",
|
||||
"cordova-plugin-customurlscheme": "^4.3.0",
|
||||
"cordova-plugin-device": "^1.1.7",
|
||||
"cordova-plugin-inappbrowser": "^2.0.1",
|
||||
"cordova-plugin-inappbrowser": "^2.0.2",
|
||||
"cordova-plugin-splashscreen": "^4.1.0",
|
||||
"cordova-plugin-statusbar": "^2.4.1",
|
||||
"cordova-plugin-whitelist": "^1.3.3",
|
||||
@ -56,7 +55,7 @@
|
||||
"zone.js": "0.8.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.1.2",
|
||||
"@angular/cli": "1.6.3",
|
||||
"@ionic/app-scripts": "3.1.0",
|
||||
"@types/jasmine": "2.5.41",
|
||||
"@types/node": "7.0.4",
|
||||
|
@ -237,10 +237,10 @@
|
||||
"cordova-plugin-browsertab": "0.2.0",
|
||||
"cordova-plugin-buildinfo": "2.0.1",
|
||||
"cordova-plugin-console": "1.1.0",
|
||||
"cordova-plugin-crosswalk-webview": "2.3.0",
|
||||
"cordova-plugin-crosswalk-webview": "2.4.0",
|
||||
"cordova-plugin-customurlscheme": "4.3.0",
|
||||
"cordova-plugin-device": "1.1.7",
|
||||
"cordova-plugin-inappbrowser": "2.0.1",
|
||||
"cordova-plugin-inappbrowser": "2.0.2",
|
||||
"cordova-plugin-splashscreen": "4.1.0",
|
||||
"cordova-plugin-statusbar": "2.4.1",
|
||||
"cordova-plugin-whitelist": "1.3.3",
|
||||
|
@ -29,7 +29,17 @@ def DEFAULT_MIN_SDK_VERSION = 14
|
||||
|
||||
def getConfigPreference(name) {
|
||||
name = name.toLowerCase()
|
||||
def xml = file("res/xml/config.xml").getText()
|
||||
|
||||
def xml
|
||||
|
||||
if (file("src/main/res/xml/config.xml").exists()) {
|
||||
// cordova-android >= 7.0.0
|
||||
xml = file("src/main/res/xml/config.xml").getText()
|
||||
} else {
|
||||
// cordova-android < 7.0.0
|
||||
xml = file("res/xml/config.xml").getText()
|
||||
}
|
||||
|
||||
// Disable namespace awareness since Cordova doesn't use them properly
|
||||
def root = new XmlParser(false, false).parseText(xml)
|
||||
|
||||
|
@ -82,10 +82,10 @@ module.exports.metadata =
|
||||
"cordova-plugin-browsertab": "0.2.0",
|
||||
"cordova-plugin-buildinfo": "2.0.1",
|
||||
"cordova-plugin-console": "1.1.0",
|
||||
"cordova-plugin-crosswalk-webview": "2.3.0",
|
||||
"cordova-plugin-crosswalk-webview": "2.4.0",
|
||||
"cordova-plugin-customurlscheme": "4.3.0",
|
||||
"cordova-plugin-device": "1.1.7",
|
||||
"cordova-plugin-inappbrowser": "2.0.1",
|
||||
"cordova-plugin-inappbrowser": "2.0.2",
|
||||
"cordova-plugin-splashscreen": "4.1.0",
|
||||
"cordova-plugin-statusbar": "2.4.1",
|
||||
"cordova-plugin-whitelist": "1.3.3",
|
||||
|
@ -25,6 +25,9 @@ import android.provider.Browser;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@ -51,6 +54,7 @@ import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.cordova.CallbackContext;
|
||||
import org.apache.cordova.Config;
|
||||
@ -67,6 +71,8 @@ import org.json.JSONObject;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@ -91,6 +97,16 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
private static final String SHOULD_PAUSE = "shouldPauseOnSuspend";
|
||||
private static final Boolean DEFAULT_HARDWARE_BACK = true;
|
||||
private static final String USER_WIDE_VIEW_PORT = "useWideViewPort";
|
||||
private static final String TOOLBAR_COLOR = "toolbarcolor";
|
||||
private static final String CLOSE_BUTTON_CAPTION = "closebuttoncaption";
|
||||
private static final String CLOSE_BUTTON_COLOR = "closebuttoncolor";
|
||||
private static final String HIDE_NAVIGATION = "hidenavigationbuttons";
|
||||
private static final String NAVIGATION_COLOR = "navigationbuttoncolor";
|
||||
private static final String HIDE_URL = "hideurlbar";
|
||||
private static final String FOOTER = "footer";
|
||||
private static final String FOOTER_COLOR = "footercolor";
|
||||
|
||||
private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
|
||||
|
||||
private InAppBrowserDialog dialog;
|
||||
private WebView inAppWebView;
|
||||
@ -109,6 +125,14 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
private ValueCallback<Uri[]> mUploadCallbackLollipop;
|
||||
private final static int FILECHOOSER_REQUESTCODE = 1;
|
||||
private final static int FILECHOOSER_REQUESTCODE_LOLLIPOP = 2;
|
||||
private String closeButtonCaption = "";
|
||||
private String closeButtonColor = "";
|
||||
private int toolbarColor = android.graphics.Color.LTGRAY;
|
||||
private boolean hideNavigationButtons = false;
|
||||
private String navigationButtonColor = "";
|
||||
private boolean hideUrlBar = false;
|
||||
private boolean showFooter = false;
|
||||
private String footerColor = "";
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
@ -127,7 +151,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
t = SELF;
|
||||
}
|
||||
final String target = t;
|
||||
final HashMap<String, Boolean> features = parseFeature(args.optString(2));
|
||||
final HashMap<String, String> features = parseFeature(args.optString(2));
|
||||
|
||||
LOG.d(LOG_TAG, "target = " + target);
|
||||
|
||||
@ -366,18 +390,21 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
* @param optString
|
||||
* @return
|
||||
*/
|
||||
private HashMap<String, Boolean> parseFeature(String optString) {
|
||||
private HashMap<String, String> parseFeature(String optString) {
|
||||
if (optString.equals(NULL)) {
|
||||
return null;
|
||||
} else {
|
||||
HashMap<String, Boolean> map = new HashMap<String, Boolean>();
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
StringTokenizer features = new StringTokenizer(optString, ",");
|
||||
StringTokenizer option;
|
||||
while(features.hasMoreElements()) {
|
||||
option = new StringTokenizer(features.nextToken(), "=");
|
||||
if (option.hasMoreElements()) {
|
||||
String key = option.nextToken();
|
||||
Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
|
||||
String value = option.nextToken();
|
||||
if (!customizableOptions.contains(key)){
|
||||
value = value.equals("yes") || value.equals("no") ? value : "yes";
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
@ -406,7 +433,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, cordova.getActivity().getPackageName());
|
||||
this.cordova.getActivity().startActivity(intent);
|
||||
return "";
|
||||
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
|
||||
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
|
||||
} catch (java.lang.RuntimeException e) {
|
||||
LOG.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
|
||||
return e.toString();
|
||||
@ -523,7 +550,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
* @param url the url to load.
|
||||
* @param features jsonObject
|
||||
*/
|
||||
public String showWebPage(final String url, HashMap<String, Boolean> features) {
|
||||
public String showWebPage(final String url, HashMap<String, String> features) {
|
||||
// Determine if we should hide the location bar.
|
||||
showLocationBar = true;
|
||||
showZoomControls = true;
|
||||
@ -531,44 +558,74 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
mediaPlaybackRequiresUserGesture = false;
|
||||
|
||||
if (features != null) {
|
||||
Boolean show = features.get(LOCATION);
|
||||
String show = features.get(LOCATION);
|
||||
if (show != null) {
|
||||
showLocationBar = show.booleanValue();
|
||||
showLocationBar = show.equals("yes") ? true : false;
|
||||
}
|
||||
Boolean zoom = features.get(ZOOM);
|
||||
if(showLocationBar) {
|
||||
String hideNavigation = features.get(HIDE_NAVIGATION);
|
||||
String hideUrl = features.get(HIDE_URL);
|
||||
if(hideNavigation != null) hideNavigationButtons = hideNavigation.equals("yes") ? true : false;
|
||||
if(hideUrl != null) hideUrlBar = hideUrl.equals("yes") ? true : false;
|
||||
}
|
||||
String zoom = features.get(ZOOM);
|
||||
if (zoom != null) {
|
||||
showZoomControls = zoom.booleanValue();
|
||||
showZoomControls = zoom.equals("yes") ? true : false;
|
||||
}
|
||||
Boolean hidden = features.get(HIDDEN);
|
||||
String hidden = features.get(HIDDEN);
|
||||
if (hidden != null) {
|
||||
openWindowHidden = hidden.booleanValue();
|
||||
openWindowHidden = hidden.equals("yes") ? true : false;
|
||||
}
|
||||
Boolean hardwareBack = features.get(HARDWARE_BACK_BUTTON);
|
||||
String hardwareBack = features.get(HARDWARE_BACK_BUTTON);
|
||||
if (hardwareBack != null) {
|
||||
hadwareBackButton = hardwareBack.booleanValue();
|
||||
hadwareBackButton = hardwareBack.equals("yes") ? true : false;
|
||||
} else {
|
||||
hadwareBackButton = DEFAULT_HARDWARE_BACK;
|
||||
}
|
||||
Boolean mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION);
|
||||
String mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION);
|
||||
if (mediaPlayback != null) {
|
||||
mediaPlaybackRequiresUserGesture = mediaPlayback.booleanValue();
|
||||
mediaPlaybackRequiresUserGesture = mediaPlayback.equals("yes") ? true : false;
|
||||
}
|
||||
Boolean cache = features.get(CLEAR_ALL_CACHE);
|
||||
String cache = features.get(CLEAR_ALL_CACHE);
|
||||
if (cache != null) {
|
||||
clearAllCache = cache.booleanValue();
|
||||
clearAllCache = cache.equals("yes") ? true : false;
|
||||
} else {
|
||||
cache = features.get(CLEAR_SESSION_CACHE);
|
||||
if (cache != null) {
|
||||
clearSessionCache = cache.booleanValue();
|
||||
clearSessionCache = cache.equals("yes") ? true : false;
|
||||
}
|
||||
}
|
||||
Boolean shouldPause = features.get(SHOULD_PAUSE);
|
||||
String shouldPause = features.get(SHOULD_PAUSE);
|
||||
if (shouldPause != null) {
|
||||
shouldPauseInAppBrowser = shouldPause.booleanValue();
|
||||
shouldPauseInAppBrowser = shouldPause.equals("yes") ? true : false;
|
||||
}
|
||||
Boolean wideViewPort = features.get(USER_WIDE_VIEW_PORT);
|
||||
String wideViewPort = features.get(USER_WIDE_VIEW_PORT);
|
||||
if (wideViewPort != null ) {
|
||||
useWideViewPort = wideViewPort.booleanValue();
|
||||
useWideViewPort = wideViewPort.equals("yes") ? true : false;
|
||||
}
|
||||
String closeButtonCaptionSet = features.get(CLOSE_BUTTON_CAPTION);
|
||||
if (closeButtonCaptionSet != null) {
|
||||
closeButtonCaption = closeButtonCaptionSet;
|
||||
}
|
||||
String closeButtonColorSet = features.get(CLOSE_BUTTON_COLOR);
|
||||
if (closeButtonColorSet != null) {
|
||||
closeButtonColor = closeButtonColorSet;
|
||||
}
|
||||
String toolbarColorSet = features.get(TOOLBAR_COLOR);
|
||||
if (toolbarColorSet != null) {
|
||||
toolbarColor = android.graphics.Color.parseColor(toolbarColorSet);
|
||||
}
|
||||
String navigationButtonColorSet = features.get(NAVIGATION_COLOR);
|
||||
if (navigationButtonColorSet != null) {
|
||||
navigationButtonColor = navigationButtonColorSet;
|
||||
}
|
||||
String showFooterSet = features.get(FOOTER);
|
||||
if (showFooterSet != null) {
|
||||
showFooter = showFooterSet.equals("yes") ? true : false;
|
||||
}
|
||||
String footerColorSet = features.get(FOOTER_COLOR);
|
||||
if (footerColorSet != null) {
|
||||
footerColor = footerColorSet;
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,13 +640,60 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
*/
|
||||
private int dpToPixels(int dipValue) {
|
||||
int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
|
||||
(float) dipValue,
|
||||
cordova.getActivity().getResources().getDisplayMetrics()
|
||||
(float) dipValue,
|
||||
cordova.getActivity().getResources().getDisplayMetrics()
|
||||
);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private View createCloseButton(int id){
|
||||
View _close;
|
||||
Resources activityRes = cordova.getActivity().getResources();
|
||||
|
||||
if (closeButtonCaption != "") {
|
||||
// Use TextView for text
|
||||
TextView close = new TextView(cordova.getActivity());
|
||||
close.setText(closeButtonCaption);
|
||||
close.setTextSize(20);
|
||||
if (closeButtonColor != "") close.setTextColor(android.graphics.Color.parseColor(closeButtonColor));
|
||||
close.setGravity(android.view.Gravity.CENTER_VERTICAL);
|
||||
close.setPadding(this.dpToPixels(10), 0, this.dpToPixels(10), 0);
|
||||
_close = close;
|
||||
}
|
||||
else {
|
||||
ImageButton close = new ImageButton(cordova.getActivity());
|
||||
int closeResId = activityRes.getIdentifier("ic_action_remove", "drawable", cordova.getActivity().getPackageName());
|
||||
Drawable closeIcon = activityRes.getDrawable(closeResId);
|
||||
if (closeButtonColor != "") close.setColorFilter(android.graphics.Color.parseColor(closeButtonColor));
|
||||
close.setImageDrawable(closeIcon);
|
||||
close.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
close.getAdjustViewBounds();
|
||||
|
||||
_close = close;
|
||||
}
|
||||
|
||||
RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
|
||||
closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
_close.setLayoutParams(closeLayoutParams);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
_close.setBackground(null);
|
||||
else
|
||||
_close.setBackgroundDrawable(null);
|
||||
|
||||
_close.setContentDescription("Close Button");
|
||||
_close.setId(Integer.valueOf(id));
|
||||
_close.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
closeDialog();
|
||||
}
|
||||
});
|
||||
|
||||
return _close;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public void run() {
|
||||
|
||||
@ -612,7 +716,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
// Toolbar layout
|
||||
RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
|
||||
//Please, no more black!
|
||||
toolbar.setBackgroundColor(android.graphics.Color.LTGRAY);
|
||||
toolbar.setBackgroundColor(toolbarColor);
|
||||
toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, this.dpToPixels(44)));
|
||||
toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
|
||||
toolbar.setHorizontalGravity(Gravity.LEFT);
|
||||
@ -635,6 +739,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
Resources activityRes = cordova.getActivity().getResources();
|
||||
int backResId = activityRes.getIdentifier("ic_action_previous_item", "drawable", cordova.getActivity().getPackageName());
|
||||
Drawable backIcon = activityRes.getDrawable(backResId);
|
||||
if (navigationButtonColor != "") back.setColorFilter(android.graphics.Color.parseColor(navigationButtonColor));
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
back.setBackground(null);
|
||||
else
|
||||
@ -660,6 +765,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
forward.setId(Integer.valueOf(3));
|
||||
int fwdResId = activityRes.getIdentifier("ic_action_next_item", "drawable", cordova.getActivity().getPackageName());
|
||||
Drawable fwdIcon = activityRes.getDrawable(fwdResId);
|
||||
if (navigationButtonColor != "") forward.setColorFilter(android.graphics.Color.parseColor(navigationButtonColor));
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
forward.setBackground(null);
|
||||
else
|
||||
@ -692,37 +798,37 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
// If the event is a key-down event on the "enter" button
|
||||
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
|
||||
navigate(edittext.getText().toString());
|
||||
return true;
|
||||
navigate(edittext.getText().toString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Close/Done button
|
||||
ImageButton close = new ImageButton(cordova.getActivity());
|
||||
RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
|
||||
closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
close.setLayoutParams(closeLayoutParams);
|
||||
close.setContentDescription("Close Button");
|
||||
close.setId(Integer.valueOf(5));
|
||||
int closeResId = activityRes.getIdentifier("ic_action_remove", "drawable", cordova.getActivity().getPackageName());
|
||||
Drawable closeIcon = activityRes.getDrawable(closeResId);
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
close.setBackground(null);
|
||||
else
|
||||
close.setBackgroundDrawable(null);
|
||||
close.setImageDrawable(closeIcon);
|
||||
close.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
back.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10));
|
||||
if (Build.VERSION.SDK_INT >= 16)
|
||||
close.getAdjustViewBounds();
|
||||
|
||||
close.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
closeDialog();
|
||||
}
|
||||
});
|
||||
// Header Close/Done button
|
||||
View close = createCloseButton(5);
|
||||
toolbar.addView(close);
|
||||
|
||||
// Footer
|
||||
RelativeLayout footer = new RelativeLayout(cordova.getActivity());
|
||||
int _footerColor;
|
||||
if(footerColor != ""){
|
||||
_footerColor = Color.parseColor(footerColor);
|
||||
}else{
|
||||
_footerColor = android.graphics.Color.LTGRAY;
|
||||
}
|
||||
footer.setBackgroundColor(_footerColor);
|
||||
RelativeLayout.LayoutParams footerLayout = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, this.dpToPixels(44));
|
||||
footerLayout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
|
||||
footer.setLayoutParams(footerLayout);
|
||||
if (closeButtonCaption != "") footer.setPadding(this.dpToPixels(8), this.dpToPixels(8), this.dpToPixels(8), this.dpToPixels(8));
|
||||
footer.setHorizontalGravity(Gravity.LEFT);
|
||||
footer.setVerticalGravity(Gravity.BOTTOM);
|
||||
|
||||
View footerClose = createCloseButton(7);
|
||||
footer.addView(footerClose);
|
||||
|
||||
|
||||
// WebView
|
||||
inAppWebView = new WebView(cordova.getActivity());
|
||||
@ -825,10 +931,9 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
actionButtonContainer.addView(back);
|
||||
actionButtonContainer.addView(forward);
|
||||
|
||||
// Add the views to our toolbar
|
||||
toolbar.addView(actionButtonContainer);
|
||||
toolbar.addView(edittext);
|
||||
toolbar.addView(close);
|
||||
// Add the views to our toolbar if they haven't been disabled
|
||||
if (!hideNavigationButtons) toolbar.addView(actionButtonContainer);
|
||||
if (!hideUrlBar) toolbar.addView(edittext);
|
||||
|
||||
// Don't add the toolbar if its been disabled
|
||||
if (getShowLocationBar()) {
|
||||
@ -837,7 +942,14 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
}
|
||||
|
||||
// Add our webview to our main view/layout
|
||||
main.addView(inAppWebView);
|
||||
RelativeLayout webViewLayout = new RelativeLayout(cordova.getActivity());
|
||||
webViewLayout.addView(inAppWebView);
|
||||
main.addView(webViewLayout);
|
||||
|
||||
// Don't add the footer unless it's been enabled
|
||||
if (showFooter) {
|
||||
webViewLayout.addView(footer);
|
||||
}
|
||||
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||
lp.copyFrom(dialog.getWindow().getAttributes());
|
||||
@ -1027,7 +1139,7 @@ public class InAppBrowser extends CordovaPlugin {
|
||||
// Update the UI if we haven't already
|
||||
if (!newloc.equals(edittext.getText().toString())) {
|
||||
edittext.setText(newloc);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
@ -6,22 +6,33 @@
|
||||
</ion-item>
|
||||
<ion-card-content *ngIf="data !== undefined && data.status === 0">
|
||||
<br>
|
||||
<div class="passage-text" *ngFor="let ch of data.cs">
|
||||
<ng-template [ngIf]="this.profileService.profile().show_paragraphs"><div class="passage-text" *ngFor="let ch of withParas">
|
||||
<h2 *ngIf="data.cs.length > 1">
|
||||
<b>Chapter {{ch.ch}}</b>
|
||||
</h2>
|
||||
<div *ngFor="let para of getParas(ch)">
|
||||
<div *ngFor="let para of ch.paras">
|
||||
<h3 *ngIf="hasHeader(para.p)">{{para.p.h}}</h3>
|
||||
<p>
|
||||
<span *ngFor="let vs of para.vss">
|
||||
<b *ngIf="showVerseNumbers">{{vs.v}}.</b> <span *ngFor="let w of vs.w">
|
||||
<ng-template ngFor let-vs [ngForOf]="para.vss">
|
||||
<b *ngIf="this.profileService.profile().show_verse_numbers">{{vs.v}}.</b> <ng-template ngFor let-w [ngForOf]="vs.w">
|
||||
<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>
|
||||
</ng-template><br *ngIf="this.profileService.profile().verses_on_new_line">
|
||||
</ng-template>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div></ng-template>
|
||||
<ng-template [ngIf]="!this.profileService.profile().show_paragraphs"><div class="passage-text" *ngFor="let ch of data.cs">
|
||||
<h2 *ngIf="data.cs.length > 1">
|
||||
<b>Chapter {{ch.ch}}</b>
|
||||
</h2>
|
||||
<ng-template ngFor let-vs [ngForOf]="ch.vss">
|
||||
<b *ngIf="this.profileService.profile().show_verse_numbers">{{vs.v}}.</b> <ng-template ngFor let-w [ngForOf]="vs.w">
|
||||
<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>
|
||||
</ng-template><br *ngIf="this.profileService.profile().verses_on_new_line">
|
||||
</ng-template>
|
||||
</div></ng-template>
|
||||
</ion-card-content>
|
||||
<ion-card-content *ngIf="data !== undefined && data.status === -1">
|
||||
<error-message [msg]="data.msg"></error-message>
|
||||
|
@ -19,13 +19,8 @@ export class Passage implements OnInit
|
||||
@Input()
|
||||
cardItem: CardItem;
|
||||
|
||||
@Input()
|
||||
versesOnNewLine: boolean;
|
||||
|
||||
@Input()
|
||||
showVerseNumbers: boolean;
|
||||
|
||||
data: BiblePassageResult;
|
||||
withParas: BibleParaPassage[];
|
||||
ref: Reference;
|
||||
|
||||
constructor(private bibleService: BibleService, private elementRef: ElementRef, private profileService: ProfileService)
|
||||
@ -35,7 +30,17 @@ export class Passage implements OnInit
|
||||
ngOnInit(): void
|
||||
{
|
||||
this.ref = new Reference(this.cardItem.qry);
|
||||
this.bibleService.getResultAsPromise(this.ref.Section).then(data => this.data = data);
|
||||
this.bibleService.getResultAsPromise(this.ref.Section).then(data =>
|
||||
{
|
||||
this.setData(data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
setData(data: BiblePassageResult)
|
||||
{
|
||||
this.data = data;
|
||||
this.withParas = this.getParaPassages(data.cs);
|
||||
}
|
||||
|
||||
close()
|
||||
@ -70,7 +75,7 @@ export class Passage implements OnInit
|
||||
|
||||
this.bibleService.getResultAsPromise(this.ref.Section).then(data =>
|
||||
{
|
||||
this.data = data;
|
||||
this.setData(data);
|
||||
this.cardItem.qry = data.ref;
|
||||
this.ref = new Reference(data.ref);
|
||||
});
|
||||
@ -89,7 +94,7 @@ export class Passage implements OnInit
|
||||
|
||||
this.bibleService.getResultAsPromise(this.ref.Section).then(data =>
|
||||
{
|
||||
this.data = data;
|
||||
this.setData(data);
|
||||
this.cardItem.qry = data.ref;
|
||||
this.ref = new Reference(data.ref);
|
||||
});
|
||||
@ -136,7 +141,7 @@ export class Passage implements OnInit
|
||||
|
||||
this.bibleService.getResultAsPromise(this.ref.Section).then(data =>
|
||||
{
|
||||
this.data = data;
|
||||
this.setData(data);
|
||||
this.cardItem.qry = data.ref;
|
||||
this.ref = new Reference(data.ref);
|
||||
});
|
||||
@ -174,22 +179,29 @@ export class Passage implements OnInit
|
||||
return this.ref.Section.start.book.book_number + ';' + this.ref.Section.start.chapter + ';' + vs.v;
|
||||
}
|
||||
|
||||
getParaPassages(chapters: BiblePassage[])
|
||||
{
|
||||
let passages: BibleParaPassage[] = [];
|
||||
for (let ch of chapters)
|
||||
{
|
||||
let para = {
|
||||
ch: ch.ch,
|
||||
paras: this.getParas(ch)
|
||||
};
|
||||
|
||||
passages.push(para);
|
||||
}
|
||||
return passages;
|
||||
}
|
||||
|
||||
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[] = [];
|
||||
|
||||
// if you aren't showing paragraphs, stick em all in the same paragraph.
|
||||
if (!this.profileService.profile().show_paragraphs)
|
||||
{
|
||||
para.vss = ch.vss;
|
||||
paras.push(para);
|
||||
return paras;
|
||||
}
|
||||
|
||||
// for each verse in the chapter, break them into paragraphs.
|
||||
for (let v of ch.vss)
|
||||
{
|
||||
@ -218,3 +230,8 @@ type BiblePara = {
|
||||
p: Paragraph,
|
||||
vss: BibleVerse[],
|
||||
}
|
||||
|
||||
type BibleParaPassage = {
|
||||
ch: number;
|
||||
paras: BiblePara[];
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
verse-picker {
|
||||
|
||||
.button {
|
||||
color: #fff;
|
||||
font-size: 1em;
|
||||
@ -7,7 +8,7 @@ verse-picker {
|
||||
background-color: #1c2e4c;
|
||||
margin: .3em;
|
||||
text-align: center;
|
||||
width: 75px;
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
.backbutton {
|
||||
|
@ -22,35 +22,35 @@
|
||||
<ion-list-header>Search Settings</ion-list-header>
|
||||
<ion-item>
|
||||
<ion-label>Show Strongs as Modal</ion-label>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().strongs_modal" (ionChange)="save()"></ion-toggle>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().strongs_modal" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Clear Search after Query</ion-label>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().clear_search_after_query" (ionChange)="save()"></ion-toggle>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().clear_search_after_query" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Append Results Below</ion-label>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().append_to_bottom" (ionChange)="save()"></ion-toggle>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().append_to_bottom" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Insert Result Next to Item</ion-label>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().insert_next_to_item" (ionChange)="save()"></ion-toggle>
|
||||
<ion-toggle color="dark" [(ngModel)]="this.profileService.profile().insert_next_to_item" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<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)="this.profileService.localSave()"></ion-toggle>
|
||||
</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-toggle color="dark" [(ngModel)]="this.profileService.profile().show_verse_numbers" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Show Paragraphs</ion-label>
|
||||
<ion-toggle color="dark" [(ngModel)]="profileService.profile().show_paragraphs" (ionChange)="save()"></ion-toggle>
|
||||
<ion-toggle color="dark" [(ngModel)]="profileService.profile().show_paragraphs" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Show Paragraph Headings</ion-label>
|
||||
<ion-toggle color="dark" [(ngModel)]="profileService.profile().show_paragraph_headings" (ionChange)="save()"></ion-toggle>
|
||||
<ion-toggle color="dark" [(ngModel)]="profileService.profile().show_paragraph_headings" (ionChange)="this.profileService.localSave()"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-list-header>Adjust Text</ion-list-header>
|
||||
@ -97,8 +97,7 @@
|
||||
|
||||
<ion-content #searchcontent padding class="search-card">
|
||||
<ion-card *ngFor="let item of this.profileService.profile().items">
|
||||
<passage *ngIf="isPassage(item.type)" [cardItem]="item" [versesOnNewLine]="this.profileService.profile().verses_on_new_line"
|
||||
[showVerseNumbers]="this.profileService.profile().show_verse_numbers" (onClose)="removeItem($event)" (onItemClicked)="getItemsNextToCard($event)"></passage>
|
||||
<passage *ngIf="isPassage(item.type)" [cardItem]="item" (onClose)="removeItem($event)" (onItemClicked)="getItemsNextToCard($event)"></passage>
|
||||
<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>
|
||||
|
@ -12,8 +12,7 @@ import { VersePickerModal } from '../../components/verse-picker/verse-picker';
|
||||
@Component({
|
||||
templateUrl: 'search.html'
|
||||
})
|
||||
export class SearchPage implements OnInit
|
||||
{
|
||||
export class SearchPage implements OnInit {
|
||||
searchQuery = '';
|
||||
last: CardItem;
|
||||
loader: Loading;
|
||||
@ -27,34 +26,43 @@ export class SearchPage implements OnInit
|
||||
, public modalCtrl: ModalController
|
||||
, public profileService: ProfileService
|
||||
, public params: NavParams
|
||||
)
|
||||
{
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void
|
||||
{
|
||||
let t = this.profileService.profile();
|
||||
// Check if there is a profile saved in local storage
|
||||
this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
|
||||
this.loader.present().then(() =>
|
||||
{
|
||||
this.initializeItems(t);
|
||||
ngOnInit(): void {
|
||||
|
||||
if (this.profileService.localIsLoaded) {
|
||||
this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
|
||||
this.loader.present().then(() => {
|
||||
let t = this.profileService.profile();
|
||||
this.initializeItems(t);
|
||||
this.loader.dismiss();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.profileService.onLocalStorageLoaded.subscribe(t => {
|
||||
// Check if there is a profile saved in local storage
|
||||
this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
|
||||
this.loader.present().then(() => {
|
||||
this.initializeItems(t);
|
||||
this.loader.dismiss();
|
||||
});
|
||||
|
||||
});
|
||||
this.profileService.onSavedPagesChanged.subscribe(sp => {
|
||||
this.pagesService.initializePages(sp);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
initializeItems(u: User)
|
||||
{
|
||||
|
||||
initializeItems(u: User) {
|
||||
// migrate old way of storing card items to the new.
|
||||
let has_migrated = false;
|
||||
for (let i in u.items)
|
||||
{
|
||||
if (u.items.hasOwnProperty(i))
|
||||
{
|
||||
for (let i in u.items) {
|
||||
if (u.items.hasOwnProperty(i)) {
|
||||
let ci = u.items[i];
|
||||
if (ci['data'] !== undefined)
|
||||
{
|
||||
if (ci['data'] !== undefined) {
|
||||
if (ci['data'].qry !== undefined)
|
||||
u.items[i] = { qry: ci['data'].qry, dict: ci.dict, type: ci.type };
|
||||
else if (ci['data'].ref !== undefined)
|
||||
@ -73,15 +81,11 @@ export class SearchPage implements OnInit
|
||||
}
|
||||
}
|
||||
|
||||
for (let pg of u.saved_pages)
|
||||
{
|
||||
for (let i in pg.queries)
|
||||
{
|
||||
if (pg.queries.hasOwnProperty(i))
|
||||
{
|
||||
for (let pg of u.saved_pages) {
|
||||
for (let i in pg.queries) {
|
||||
if (pg.queries.hasOwnProperty(i)) {
|
||||
let ci = pg.queries[i];
|
||||
if (ci['data'] !== undefined)
|
||||
{
|
||||
if (ci['data'] !== undefined) {
|
||||
if (ci['data'].qry !== undefined)
|
||||
pg.queries[i] = { qry: ci['data'].qry, dict: ci.dict, type: ci.type };
|
||||
else if (ci['data'].ref !== undefined)
|
||||
@ -105,7 +109,7 @@ export class SearchPage implements OnInit
|
||||
this.pagesService.initializePages(u.saved_pages);
|
||||
|
||||
if (this.params.data.queries !== undefined)
|
||||
this.profileService.profile().items = this.params.data.queries.slice();
|
||||
this.profileService.profile().items = JSON.parse(JSON.stringify(this.params.data.queries));
|
||||
|
||||
if (this.params.data.title === undefined)
|
||||
this.title = 'Search';
|
||||
@ -114,25 +118,19 @@ export class SearchPage implements OnInit
|
||||
|
||||
if (has_migrated)
|
||||
this.profileService.save();
|
||||
|
||||
}
|
||||
|
||||
save()
|
||||
{
|
||||
this.profileService.save();
|
||||
}
|
||||
textSizeChanged()
|
||||
{
|
||||
textSizeChanged() {
|
||||
this.profileService.textSizeChanged();
|
||||
this.save();
|
||||
this.profileService.localSave();
|
||||
}
|
||||
|
||||
actionsMenu()
|
||||
{
|
||||
actionsMenu() {
|
||||
this.menu.open('actions');
|
||||
}
|
||||
|
||||
addPage()
|
||||
{
|
||||
addPage() {
|
||||
const alert = this.alertCtrl.create({
|
||||
title: 'Save Search as Page',
|
||||
inputs: [
|
||||
@ -145,15 +143,13 @@ export class SearchPage implements OnInit
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
handler: (): void =>
|
||||
{
|
||||
handler: (): void => {
|
||||
console.log('Cancel clicked');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Save',
|
||||
handler: data =>
|
||||
{
|
||||
handler: data => {
|
||||
const p = { queries: this.profileService.profile().items.slice(), title: data.title };
|
||||
this.profileService.profile().saved_pages.push(p);
|
||||
this.profileService.save();
|
||||
@ -165,71 +161,58 @@ export class SearchPage implements OnInit
|
||||
alert.present();
|
||||
}
|
||||
|
||||
updatePage()
|
||||
{
|
||||
updatePage() {
|
||||
const page = this.profileService.profile().saved_pages.find(
|
||||
i =>
|
||||
i.title === this.params.data.title
|
||||
i.title === this.params.data.title
|
||||
);
|
||||
page.queries = this.profileService.profile().items.slice();
|
||||
this.profileService.save();
|
||||
}
|
||||
|
||||
setQuery(searchbar)
|
||||
{
|
||||
setQuery(searchbar) {
|
||||
this.searchQuery = searchbar.target.value;
|
||||
}
|
||||
getQuery(searchbar)
|
||||
{
|
||||
getQuery(searchbar) {
|
||||
this.updateUIwithItems(this.searchQuery, true);
|
||||
}
|
||||
|
||||
isError(t: string)
|
||||
{
|
||||
isError(t: string) {
|
||||
return t === 'Error';
|
||||
}
|
||||
isPassage(t: string)
|
||||
{
|
||||
isPassage(t: string) {
|
||||
return t === 'Passage';
|
||||
}
|
||||
isStrongs(t: string)
|
||||
{
|
||||
isStrongs(t: string) {
|
||||
return t === 'Strongs';
|
||||
}
|
||||
isWords(t: string)
|
||||
{
|
||||
isWords(t: string) {
|
||||
return t === 'Words';
|
||||
}
|
||||
|
||||
versePicker()
|
||||
{
|
||||
versePicker() {
|
||||
const modal = this.modalCtrl.create(VersePickerModal, { onItemClicked: this });
|
||||
modal.present();
|
||||
}
|
||||
|
||||
removeItem(item)
|
||||
{
|
||||
removeItem(item) {
|
||||
const idx = this.profileService.profile().items.indexOf(item);
|
||||
this.profileService.profile().items.splice(idx, 1);
|
||||
|
||||
// save the users settings.
|
||||
this.profileService.save();
|
||||
this.profileService.localSave();
|
||||
}
|
||||
addItemToList(item: CardItem)
|
||||
{
|
||||
if (this.profileService.profile().append_to_bottom)
|
||||
{
|
||||
if (this.last != null && this.profileService.profile().insert_next_to_item)
|
||||
{
|
||||
|
||||
addItemToList(item: CardItem) {
|
||||
if (this.profileService.profile().append_to_bottom) {
|
||||
if (this.last != null && this.profileService.profile().insert_next_to_item) {
|
||||
const idx = this.profileService.profile().items.indexOf(this.last);
|
||||
this.profileService.profile().items.splice(idx + 1, 0, item);
|
||||
} else
|
||||
this.profileService.profile().items.push(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.last != null && this.profileService.profile().insert_next_to_item)
|
||||
{
|
||||
else {
|
||||
if (this.last != null && this.profileService.profile().insert_next_to_item) {
|
||||
const idx = this.profileService.profile().items.indexOf(this.last);
|
||||
this.profileService.profile().items.splice(idx, 0, item);
|
||||
} else
|
||||
@ -237,33 +220,25 @@ export class SearchPage implements OnInit
|
||||
}
|
||||
this.last = null;
|
||||
}
|
||||
getItemsNextToCard(data: OpenData)
|
||||
{
|
||||
getItemsNextToCard(data: OpenData) {
|
||||
this.last = data.card;
|
||||
this.updateUIwithItems(data.qry, data.from_search_bar);
|
||||
}
|
||||
|
||||
getItemList(search: string): Promise<CardItem[]>
|
||||
{
|
||||
return new Promise((resolve) =>
|
||||
{
|
||||
|
||||
getItemList(search: string): Promise<CardItem[]> {
|
||||
return new Promise((resolve) => {
|
||||
const list: CardItem[] = [];
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
const qs = search.split(';');
|
||||
for (let x in qs)
|
||||
{
|
||||
if (qs.hasOwnProperty(x))
|
||||
{
|
||||
for (let x in qs) {
|
||||
if (qs.hasOwnProperty(x)) {
|
||||
let q = qs[x].trim();
|
||||
if (q !== '')
|
||||
{
|
||||
if (q !== '') {
|
||||
// its a search term.
|
||||
if (q.search(/[0-9]/i) === -1)
|
||||
list.push({ qry: q, dict: 'na', type: 'Words' });
|
||||
else if (q.search(/(H|G)[0-9]/i) !== -1)
|
||||
{
|
||||
else if (q.search(/(H|G)[0-9]/i) !== -1) {
|
||||
// its a strongs lookup
|
||||
let dict = q.substring(0, 1);
|
||||
|
||||
@ -275,11 +250,9 @@ export class SearchPage implements OnInit
|
||||
q = q.substring(1, q.length);
|
||||
list.push({ qry: q, dict: dict, type: 'Strongs' });
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// its a verse reference.
|
||||
if (q.trim() !== '')
|
||||
{
|
||||
if (q.trim() !== '') {
|
||||
const myref = new Reference(q.trim());
|
||||
list.push({ qry: myref.toString(), dict: myref.Section.start.book.book_number > 39 ? 'G' : 'H', type: 'Passage' });
|
||||
}
|
||||
@ -292,8 +265,7 @@ export class SearchPage implements OnInit
|
||||
|
||||
this.profileService.save();
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
catch (error) {
|
||||
list.push({ qry: error, type: 'Error', dict: 'na' });
|
||||
console.log(error);
|
||||
}
|
||||
@ -302,18 +274,13 @@ export class SearchPage implements OnInit
|
||||
});
|
||||
}
|
||||
|
||||
updateUIwithItems(search: string, from_search_bar: boolean)
|
||||
{
|
||||
this.getItemList(search).then(lst =>
|
||||
{
|
||||
updateUIwithItems(search: string, from_search_bar: boolean) {
|
||||
this.getItemList(search).then(lst => {
|
||||
this.loader = this.loadingCtrl.create({ content: 'Looking up Query...' });
|
||||
this.loader.present().then(
|
||||
() =>
|
||||
{
|
||||
for (let item of lst)
|
||||
{
|
||||
if (item.type === 'Strongs' && this.profileService.profile().strongs_modal && !from_search_bar)
|
||||
{
|
||||
() => {
|
||||
for (let item of lst) {
|
||||
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();
|
||||
} else
|
||||
@ -330,8 +297,7 @@ export type OpenData = { card: CardItem, qry: string, from_search_bar: boolean }
|
||||
|
||||
export type CardItem = { qry: string, type: string, dict: string }
|
||||
|
||||
class Item
|
||||
{
|
||||
class Item {
|
||||
id: number;
|
||||
data: any;
|
||||
type: Type<any>;
|
||||
|
@ -9,7 +9,7 @@
|
||||
<ion-content padding>
|
||||
<ng-template [ngIf]="profileService.profile()">
|
||||
<h4>Search Settings</h4>
|
||||
|
||||
{{profileService.isWeb}} : {{profileService.url}}
|
||||
<ng-template [ngIf]="!profileService.currentUser()">
|
||||
<ion-item>
|
||||
<button ion-button (click)="profileService.authenticate()">Login With Google</button>
|
||||
|
@ -20,12 +20,7 @@ export class SettingsPage
|
||||
textSizeChanged()
|
||||
{
|
||||
this.profileService.textSizeChanged();
|
||||
this.save();
|
||||
}
|
||||
|
||||
save()
|
||||
{
|
||||
this.profileService.save()
|
||||
this.profileService.localSave();
|
||||
}
|
||||
|
||||
reset()
|
||||
|
@ -11,45 +11,36 @@ import { CardItem } from '../pages/search/search';
|
||||
import { Promise } from 'q';
|
||||
import { setTimeout } from 'timers';
|
||||
|
||||
type fbObject<T> = {
|
||||
ref: AngularFireObject<T>,
|
||||
stream: Observable<T>,
|
||||
};
|
||||
import { Output, EventEmitter } from '@angular/core';
|
||||
|
||||
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,
|
||||
show_verse_numbers: boolean,
|
||||
show_paragraphs: boolean,
|
||||
show_paragraph_headings: boolean,
|
||||
}
|
||||
|
||||
export type SavedPage = {
|
||||
queries: CardItem[],
|
||||
title: string,
|
||||
}
|
||||
@Injectable()
|
||||
export class ProfileService
|
||||
{
|
||||
@Output()
|
||||
onSavedPagesChanged = new EventEmitter<SavedPage[]>();
|
||||
@Output()
|
||||
onLocalStorageLoaded = new EventEmitter<User>();
|
||||
|
||||
localProfile: User;
|
||||
remoteProfile: fbObject<User> | null;
|
||||
remoteLoggedIn: boolean;
|
||||
isWeb: boolean;
|
||||
url: string;
|
||||
needsSync = false;
|
||||
firebaseUser: firebase.User;
|
||||
remoteLoggedIn: boolean;
|
||||
localIsLoaded: boolean;
|
||||
|
||||
constructor(private local: Storage, private db: AngularFireDatabase, public firebaseAuth: AngularFireAuth)
|
||||
constructor(
|
||||
private local: Storage,
|
||||
private db: AngularFireDatabase,
|
||||
public firebaseAuth: AngularFireAuth
|
||||
)
|
||||
{
|
||||
this.isWeb = (document.URL.startsWith('http') || !document.URL.startsWith('http://localhost:8080'));
|
||||
this.url = document.URL;
|
||||
this.isWeb = (document.URL.startsWith('http') && !document.URL.startsWith('http://localhost:8080'));
|
||||
this.localIsLoaded = false;
|
||||
|
||||
// asyncrounosly kick off a poller that does the work of syncing remotely when the
|
||||
// profile needs to be synced.
|
||||
@ -66,36 +57,29 @@ export class ProfileService
|
||||
{
|
||||
let st = new Date(); console.log('Saving the remote profile...');
|
||||
self.remoteProfile.ref.set(self.localProfile);
|
||||
console.log('Finished saving remote profile. ' + self.elapsed(st, new Date) + 'ms');
|
||||
console.log(' Finished saving remote profile. ' + self.elapsed(st, new Date) + 'ms');
|
||||
}
|
||||
self.needsSync = false;
|
||||
}
|
||||
|
||||
poll(self);
|
||||
}, 3000);
|
||||
}, 10000);
|
||||
})(this);
|
||||
|
||||
let localObserver = this.userObserver().subscribe(
|
||||
user =>
|
||||
{
|
||||
this.update(user);
|
||||
this.localProfile = user;
|
||||
},
|
||||
error => console.log(error)
|
||||
);
|
||||
|
||||
this.firebaseAuth.authState.subscribe(state => this.subscribeToRemoteProfile(this.db, state));
|
||||
|
||||
}
|
||||
|
||||
userObserver(): Observable<User>
|
||||
{
|
||||
return Observable.fromPromise(this.local.get('profile')).map(json_profile =>
|
||||
this.local.get('profile').then(json_profile =>
|
||||
{
|
||||
let t = this.profile();
|
||||
|
||||
if (json_profile !== null) t = JSON.parse(json_profile);
|
||||
return t;
|
||||
if (json_profile !== null)
|
||||
t = JSON.parse(json_profile);
|
||||
|
||||
this.localProfile = t;
|
||||
this.localIsLoaded = true;
|
||||
this.onLocalStorageLoaded.emit(this.localProfile);
|
||||
});
|
||||
|
||||
this.firebaseAuth.authState.subscribe(state => this.subscribeToRemoteProfile(this.db, state));
|
||||
|
||||
}
|
||||
|
||||
profile(): User
|
||||
@ -105,50 +89,141 @@ export class ProfileService
|
||||
this.localProfile = ProfileService.createDefaultUser();
|
||||
}
|
||||
|
||||
return this.localProfile
|
||||
return this.localProfile;
|
||||
}
|
||||
|
||||
subscribeToRemoteProfile(db: AngularFireDatabase, user: firebase.User)
|
||||
{
|
||||
if (!user) return;
|
||||
|
||||
console.log('subscribeToRemoteProfile');
|
||||
if (!user || this.firebaseUser) return;
|
||||
console.log('You got the firebase user.');
|
||||
let obj = db.object('/settings/' + user.uid);
|
||||
this.remoteProfile = {
|
||||
ref: obj as AngularFireObject<User>,
|
||||
stream: obj.valueChanges() as Observable<User>,
|
||||
};
|
||||
this.firebaseUser = user;
|
||||
this.profile().username = user.displayName;
|
||||
this.profile().uid = user.uid;
|
||||
|
||||
this.save();
|
||||
this.remoteProfile.stream.subscribe(
|
||||
user => this.handleRemotePreferenceChange(user),
|
||||
error => console.log(error));
|
||||
}
|
||||
|
||||
|
||||
comparePage(a: SavedPage, b: SavedPage)
|
||||
{
|
||||
if (a.title > b.title)
|
||||
return 1;
|
||||
if (a.title === b.title)
|
||||
return 0;
|
||||
if (a.title < b.title)
|
||||
return -1;
|
||||
|
||||
}
|
||||
private returnYonly(a: SavedPage[], b: SavedPage[])
|
||||
{
|
||||
let r: SavedPage[] = [];
|
||||
if (b === undefined)
|
||||
return r;
|
||||
|
||||
if (a !== undefined && a.length === 0 && b !== undefined && b.length > 0)
|
||||
return [...b];
|
||||
|
||||
let x = [...a];
|
||||
let y = [...b];
|
||||
|
||||
/// <summary>
|
||||
/// Takes two javascript arrays and returns an array
|
||||
/// containing a set of values shared by arrays.
|
||||
/// </summary>
|
||||
// declare iterator
|
||||
let i = 0;
|
||||
// declare terminator
|
||||
let t = (x.length < y.length) ? x.length : y.length;
|
||||
// sort the arrays
|
||||
x.sort(this.comparePage);
|
||||
y.sort(this.comparePage);
|
||||
|
||||
// in this loop, we remove from the arrays, the
|
||||
// values that aren't shared between them.
|
||||
while (i < t)
|
||||
{
|
||||
if (x[i].title === y[i].title)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
if (x.length > i && y.length > i && x[i].title < y[i].title)
|
||||
x.splice(i, 1);
|
||||
|
||||
if (x.length > i && y.length > i && x[i].title > y[i].title)
|
||||
{
|
||||
r.unshift(y[i]);
|
||||
y.splice(i, 1);
|
||||
}
|
||||
|
||||
t = (x.length < y.length) ? x.length : y.length;
|
||||
|
||||
if (t === i && t < y.length)
|
||||
{
|
||||
r = r.concat(y);
|
||||
}
|
||||
}
|
||||
// we could return y, because at this time, both arrays
|
||||
// are identical.
|
||||
return r;
|
||||
}
|
||||
|
||||
handleRemotePreferenceChange(user: User)
|
||||
{
|
||||
console.log('handleRemotePreferenceChange');
|
||||
if (user)
|
||||
{
|
||||
if (!user.saved_pages) user.saved_pages = [];
|
||||
if (!user.items) user.items = [];
|
||||
let changed = false;
|
||||
let local_was_empty = this.profile().saved_pages.length === 0;
|
||||
|
||||
// merge the saved pages so you don't loose those either
|
||||
if (this.profile().saved_pages.length > 0)
|
||||
user.saved_pages.concat(this.localProfile.saved_pages);
|
||||
// don't add if they are the same.
|
||||
let ys = this.returnYonly(this.profile().saved_pages, user.saved_pages);
|
||||
|
||||
if (ys.length > 0)
|
||||
{
|
||||
this.localProfile.saved_pages = this.localProfile.saved_pages.concat(ys);
|
||||
this.onSavedPagesChanged.emit(this.localProfile.saved_pages);
|
||||
|
||||
if (!local_was_empty)
|
||||
{
|
||||
changed = true;
|
||||
this.needsSync = true;
|
||||
}
|
||||
}
|
||||
if (this.profile().saved_pages.length > 0 && user.saved_pages === undefined)
|
||||
{
|
||||
changed = true;
|
||||
this.needsSync = true;
|
||||
}
|
||||
|
||||
// don't sync things that don't make sense.
|
||||
this.profile().uid = user.uid;
|
||||
this.profile().username = user.username;
|
||||
this.profile().saved_pages = user.saved_pages;
|
||||
|
||||
if (this.profile().uid !== user.uid)
|
||||
{
|
||||
this.profile().uid = user.uid;
|
||||
changed = true;
|
||||
}
|
||||
if (this.profile().username !== user.username)
|
||||
{
|
||||
this.profile().username = user.username;
|
||||
changed = true;
|
||||
}
|
||||
// We only save the local change here since this is an update from our remote profile.
|
||||
this.localSave();
|
||||
if (changed)
|
||||
{
|
||||
this.localSave();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No user is there so we should save our local to the remote.
|
||||
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
@ -160,6 +235,8 @@ export class ProfileService
|
||||
|
||||
authenticate()
|
||||
{
|
||||
console.log('Authenticating to remote...');
|
||||
|
||||
let self = this;
|
||||
let provider = new firebase.auth.GoogleAuthProvider();
|
||||
if (this.isWeb)
|
||||
@ -184,12 +261,14 @@ export class ProfileService
|
||||
|
||||
refresh()
|
||||
{
|
||||
console.log('refresh');
|
||||
this.logout();
|
||||
this.authenticate();
|
||||
}
|
||||
|
||||
logout()
|
||||
{
|
||||
console.log('logout');
|
||||
this.firebaseAuth.auth.signOut(); // sign out
|
||||
this.remoteProfile = null; // inform the profile service not to bother
|
||||
this.remoteLoggedIn = false;
|
||||
@ -201,8 +280,9 @@ export class ProfileService
|
||||
this.needsSync = true;
|
||||
}
|
||||
|
||||
private localSave()
|
||||
localSave()
|
||||
{
|
||||
console.log('saving local');
|
||||
this.local.set('profile', JSON.stringify(this.profile()));
|
||||
}
|
||||
|
||||
@ -267,6 +347,7 @@ export class ProfileService
|
||||
{
|
||||
let idx = this.profile().saved_pages.indexOf(page);
|
||||
this.profile().saved_pages.splice(idx, 1);
|
||||
this.onSavedPagesChanged.emit(this.localProfile.saved_pages);
|
||||
|
||||
// Sync with remote
|
||||
this.save();
|
||||
@ -299,4 +380,31 @@ export class ProfileService
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type fbObject<T> = {
|
||||
ref: AngularFireObject<T>,
|
||||
stream: Observable<T>,
|
||||
};
|
||||
|
||||
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,
|
||||
show_verse_numbers: boolean,
|
||||
show_paragraphs: boolean,
|
||||
show_paragraph_headings: boolean,
|
||||
}
|
||||
|
||||
export type SavedPage = {
|
||||
queries: CardItem[],
|
||||
title: string,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user