/*
* Copyright 2015. Appsi Mobile
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.appsimobile.appsii;
import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.v4.util.CircularArray;
import android.support.v4.util.LongSparseArray;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import com.appsimobile.appsii.SidebarHotspot.SidebarGestureCallback;
import com.appsimobile.appsii.permissions.PermissionUtils;
import com.crashlytics.android.Crashlytics;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class HotspotHelperImpl extends AbstractHotspotHelper
implements OnClickListener, View.OnLongClickListener, SidebarGestureCallback,
SidebarHotspot.SwipeListener {
private static final String TAG = "HotspotHelperImpl";
final int[] mOffsetInt = new int[2];
final PopupLayer mPopupLayer;
final LayoutInflater mLayoutInflater;
final View mFullScreenWatcher;
final WindowManager mWindowManager;
final PermissionUtils mPermissionUtils;
final SharedPreferences mSharedPreferences;
private final Context mContext;
private final LongSparseArray<HotspotContainerHelper> mSidebarHotspots =
new LongSparseArray<>();
HotspotHelperListener mCallback;
boolean mDraggingHotspot;
int mDragLocalX;
int mRawStartDragY;
int mDragLocalY;
boolean mIsLeftHotspot;
int mHotspotX;
int mHotspotY;
boolean mFullScreenWatcherAttached;
private boolean mVibrateOnTouch;
private boolean mHotspotsActive;
private CircularArray<HotspotItem> mHotspotItems;
@Inject
public HotspotHelperImpl(Context context, SharedPreferences sharedPreferences, PermissionUtils permissionUtils,
WindowManager windowManager, PopupLayer popupLayer
) {
super(context, windowManager);
mWindowManager = windowManager;
mSharedPreferences = sharedPreferences;
mPermissionUtils = permissionUtils;
mLayoutInflater = LayoutInflater.from(context);
mPopupLayer = popupLayer;
mContext = context;
mVibrateOnTouch = mSharedPreferences.getBoolean("pref_sidebar_haptic_feedback", false);
mFullScreenWatcher = new View(context) {
{
setFitsSystemWindows(true);
}
};
}
public static boolean isPageGesture(String stringUri) {
if (stringUri == null) return false;
Uri uri = Uri.parse(stringUri);
return isPageGesture(uri);
}
public static boolean isPageGesture(Uri uri) {
if (uri == null) return false;
return true;
}
@Override
public void setCallback(HotspotHelperListener callback) {
mCallback = callback;
}
@Override
public void onOrientationChanged() {
if (mHotspotsActive) {
updateHotspotLayoutParams();
}
}
@Override
public void onDestroy() {
removeHotspots();
}
@Override
public void setVibrate(boolean vibrate) {
int count = mSidebarHotspots.size();
mVibrateOnTouch = vibrate;
for (int i = 0; i < count; i++) {
HotspotContainerHelper sidebarHotspot = mSidebarHotspots.valueAt(i);
sidebarHotspot.setVibrateOnTouch(vibrate);
}
}
@Override
public void addHotspots() throws PermissionDeniedException {
Log.d(TAG, "addHotspots() called with: " + "");
try {
removeHotspots();
mHotspotsActive = true;
if (mHotspotItems != null) {
int count = mHotspotItems.size();
SharedPreferences prefs = mSharedPreferences;
for (int i = 0; i < count; i++) {
HotspotItem conf = mHotspotItems.get(i);
HotspotContainerHelper hotspotContainerHelper = mSidebarHotspots.get(conf.mId);
boolean isAdded = hotspotContainerHelper != null;
if (!isAdded) {
hotspotContainerHelper = createSidebarHotspot();
}
hotspotContainerHelper.bind(conf);
mSidebarHotspots.put(conf.mId, hotspotContainerHelper);
if (!isAdded) {
WindowManager.LayoutParams lp =
configureHotspot(hotspotContainerHelper, conf, prefs);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
!Settings.canDrawOverlays(mContext)) {
throw new PermissionDeniedException(
Manifest.permission.SYSTEM_ALERT_WINDOW);
}
mWindowManager.addView(hotspotContainerHelper.mHotspotParent, lp);
} catch (PermissionDeniedException e) {
throw e;
} catch (Exception e) {
Log.w("HotspotHelperImpl", "error adding hotspot", e);
Crashlytics.logException(e);
}
}
}
}
addScreenWatcher();
} catch (PermissionDeniedException e) {
mHotspotsActive = false;
}
}
private HotspotContainerHelper createSidebarHotspot() {
View result = mLayoutInflater.inflate(R.layout.hotspot, null);
HotspotContainerHelper helper = new HotspotContainerHelper(result,
(SidebarHotspot) result.findViewById(R.id.sidebar_hotspot));
helper.setOnClickListener(this);
helper.setOnLongClickListener(this);
helper.setVibrateOnTouch(mVibrateOnTouch);
helper.setCallback(this);
return helper;
}
private void addScreenWatcher() throws PermissionDeniedException {
if (!mPermissionUtils.canDrawOverlays(mContext)) {
throw new PermissionDeniedException(
Manifest.permission.SYSTEM_ALERT_WINDOW);
}
mWindowManager.addView(mFullScreenWatcher, createInsetParams());
mFullScreenWatcherAttached = true;
}
@Override
public void removeHotspots() {
int count = mSidebarHotspots.size();
for (int i = count - 1; i >= 0; i--) {
HotspotContainerHelper hotspotContainerHelper = mSidebarHotspots.valueAt(i);
SidebarHotspot sidebarHotspot = hotspotContainerHelper.mSidebarHotspot;
View sidebarParent = hotspotContainerHelper.mHotspotParent;
if (!sidebarHotspot.mIsDragOpening) {
if (sidebarParent.getParent() != null) {
mWindowManager.removeView(sidebarParent);
}
hotspotContainerHelper.setOnClickListener(null);
hotspotContainerHelper.setOnLongClickListener(null);
hotspotContainerHelper.setCallback(null);
long id = sidebarHotspot.getConfiguration().mId;
mSidebarHotspots.remove(id);
}
}
removeScreenWatcher();
mHotspotsActive = false;
}
@Override
public void onHotspotsLoaded(CircularArray<HotspotItem> configurations) {
mHotspotItems = configurations;
}
@Override
public int getTopOffset() {
mOffsetInt[1] = -1;
mFullScreenWatcher.getLocationOnScreen(mOffsetInt);
return mOffsetInt[1];
}
private void removeScreenWatcher() {
if (mFullScreenWatcherAttached) {
mWindowManager.removeView(mFullScreenWatcher);
mFullScreenWatcherAttached = false;
}
}
public void updateHotspotLayoutParams() {
if (!mHotspotsActive) return;
if (mHotspotItems != null) {
int count = mHotspotItems.size();
SharedPreferences prefs = mSharedPreferences;
for (int i = 0; i < count; i++) {
HotspotItem conf = mHotspotItems.get(i);
HotspotContainerHelper hotspotContainerHelper = mSidebarHotspots.get(conf.mId);
boolean isAdded = hotspotContainerHelper != null;
if (!isAdded) {
continue;
}
WindowManager.LayoutParams lp =
configureHotspot(hotspotContainerHelper, conf, prefs);
try {
mWindowManager.updateViewLayout(hotspotContainerHelper.mHotspotParent, lp);
} catch (Exception e) {
Log.w("HotspotHelperImpl", "error adding hotspot", e);
}
}
}
}
private WindowManager.LayoutParams configureHotspot(HotspotContainerHelper hotspot,
HotspotItem hotspotItem,
SharedPreferences prefs) {
WindowManager.LayoutParams lp = createHotspotParams(hotspotItem, prefs);
hotspot.mSidebarHotspot.setPosition(hotspotItem.mLeft, -lp.width, lp.y);
return lp;
}
@Override
public void onClick(View v) {
// We can implement some feature here !
}
public boolean onLongClick(View v) {
return true;
}
@Override
public SidebarHotspot.SwipeListener open(SidebarHotspot hotspot, SidebarHotspot.Gesture action,
int x, int y) {
mIsLeftHotspot = hotspot.isLeft();
mHotspotX = hotspot.getHPos();
mHotspotY = hotspot.getVPos();
HotspotItem conf = hotspot.getConfiguration();
if (action == SidebarHotspot.Gesture.TAP) {
//return mCallback.openSidebar(conf, null, 0);
return null;
} else {
CircularArray<HotspotPageEntry> entries = hotspot.getHotspotPageEntries();
return mCallback.openSidebar(conf, entries, Appsi.OPEN_FLAG_LIKE_NOTIFICATION_BAR);
}
}
@Override
public void cancelVisualHints(SidebarHotspot sidebarHotspot) {
mCallback.cancelVisualHints();
}
@Override
public SidebarHotspot.SwipeListener longPressGesturePerformed(SidebarHotspot hotspot,
int startX, int startY,
int rawStartY) {
return null;
}
@Override
public void removeIfNeeded(SidebarHotspot hotspot) {
if (!mHotspotsActive) {
HotspotItem configuration = hotspot.getConfiguration();
HotspotContainerHelper added = mSidebarHotspots.get(configuration.mId);
if (added.isHotspot(hotspot)) {
removeHotspots();
}
}
}
@Override
public void setSwipeLocation(SidebarHotspot hotspot, int localX, int localY, int rawX,
int rawY) {
WindowManager wm = mWindowManager;
Display display = wm.getDefaultDisplay();
int width = display.getWidth();
if (mDraggingHotspot) {
boolean left = rawX < width / 2;
int deltaY = mRawStartDragY - rawY;
setSwipeLocationForHotspotDrag(hotspot, localX, deltaY, left);
}
}
@Override
public void onSwipeEnd(SidebarHotspot hotspot, int screenX, int screenY, boolean cancelled,
VelocityTracker velocityTracker) {
}
private void setSwipeLocationForHotspotDrag(SidebarHotspot hotspot, int localX, int deltaY,
boolean left) {
long id = hotspot.getHotspotId();
HotspotContainerHelper helper = mSidebarHotspots.get(id);
WindowManager wm = mWindowManager;
WindowManager.LayoutParams params =
(WindowManager.LayoutParams) helper.mHotspotParent.getLayoutParams();
int y = mHotspotY - deltaY;
params = updateLayoutParams(left, y, params);
wm.updateViewLayout(helper.mHotspotParent, params);
}
static class HotspotContainerHelper {
final View mHotspotParent;
final SidebarHotspot mSidebarHotspot;
HotspotContainerHelper(View hotspotParent, SidebarHotspot sidebarHotspot) {
mHotspotParent = hotspotParent;
mSidebarHotspot = sidebarHotspot;
}
public boolean isHotspot(SidebarHotspot hotspot) {
return hotspot == mSidebarHotspot;
}
public void setVibrateOnTouch(boolean vibrate) {
mSidebarHotspot.setVibrateOnTouch(vibrate);
}
public void setOnClickListener(HotspotHelperImpl appsiHotspotHelper) {
mSidebarHotspot.setOnClickListener(appsiHotspotHelper);
}
public void setOnLongClickListener(HotspotHelperImpl appsiHotspotHelper) {
mSidebarHotspot.setOnLongClickListener(appsiHotspotHelper);
}
public void setCallback(HotspotHelperImpl appsiHotspotHelper) {
mSidebarHotspot.setCallback(appsiHotspotHelper);
}
public void bind(HotspotItem conf) {
mSidebarHotspot.bind(conf);
}
}
}