/*
* Copyright © 2016 TIBCO Software,Inc.All rights reserved.
* http://community.jaspersoft.com/project/jaspermobile-android
*
* Unless you have purchased a commercial license agreement from TIBCO Jaspersoft,
* the following license terms apply:
*
* This program is part of TIBCO Jaspersoft Mobile for Android.
*
* TIBCO Jaspersoft Mobile is free software:you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation,either version 3of the License,or
* (at your option)any later version.
*
* TIBCO Jaspersoft Mobile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY;without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with TIBCO Jaspersoft Mobile for Android.If not,see
* <http://www.gnu.org/licenses/lgpl>.
*/
package com.jaspersoft.android.jaspermobile.activities.viewer.html.dashboard;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.jaspersoft.android.jaspermobile.Analytics;
import com.jaspersoft.android.jaspermobile.GraphObject;
import com.jaspersoft.android.jaspermobile.R;
import com.jaspersoft.android.jaspermobile.activities.inputcontrols.InputControlsActivity_;
import com.jaspersoft.android.jaspermobile.activities.share.AnnotationActivity_;
import com.jaspersoft.android.jaspermobile.dialog.ProgressDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.SimpleDialogFragment;
import com.jaspersoft.android.jaspermobile.domain.ErrorSubscriber;
import com.jaspersoft.android.jaspermobile.domain.JasperServer;
import com.jaspersoft.android.jaspermobile.domain.ScreenCapture;
import com.jaspersoft.android.jaspermobile.domain.SimpleSubscriber;
import com.jaspersoft.android.jaspermobile.domain.interactor.profile.AuthorizeSessionUseCase;
import com.jaspersoft.android.jaspermobile.domain.interactor.resource.SaveScreenCaptureCase;
import com.jaspersoft.android.jaspermobile.internal.di.components.DashboardActivityComponent;
import com.jaspersoft.android.jaspermobile.internal.di.modules.activity.ActivityModule;
import com.jaspersoft.android.jaspermobile.internal.di.modules.activity.DashboardModule;
import com.jaspersoft.android.jaspermobile.network.RequestExceptionHandler;
import com.jaspersoft.android.jaspermobile.ui.view.activity.ToolbarActivity;
import com.jaspersoft.android.jaspermobile.util.FavoritesHelper;
import com.jaspersoft.android.jaspermobile.util.ScrollableTitleHelper;
import com.jaspersoft.android.jaspermobile.util.print.ResourcePrintJob;
import com.jaspersoft.android.jaspermobile.webview.DefaultUrlPolicy;
import com.jaspersoft.android.jaspermobile.webview.JasperChromeClientListenerImpl;
import com.jaspersoft.android.jaspermobile.webview.JasperWebViewClientListener;
import com.jaspersoft.android.jaspermobile.webview.SystemChromeClient;
import com.jaspersoft.android.jaspermobile.webview.SystemWebViewClient;
import com.jaspersoft.android.jaspermobile.webview.UrlPolicy;
import com.jaspersoft.android.jaspermobile.webview.WebViewEnvironment;
import com.jaspersoft.android.jaspermobile.webview.dashboard.InjectionRequestInterceptor;
import com.jaspersoft.android.jaspermobile.webview.dashboard.script.ScriptTagFactory;
import com.jaspersoft.android.jaspermobile.webview.intercept.VisualizeResourcesInterceptRule;
import com.jaspersoft.android.jaspermobile.webview.intercept.WebResourceInterceptor;
import com.jaspersoft.android.jaspermobile.webview.intercept.okhttp.OkHttpWebResourceInterceptor;
import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookup;
import com.squareup.okhttp.OkHttpClient;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.androidannotations.annotations.OptionsItem;
import org.androidannotations.annotations.OptionsMenu;
import org.androidannotations.annotations.OptionsMenuItem;
import java.io.File;
import javax.inject.Inject;
import javax.inject.Named;
import timber.log.Timber;
/**
* Activity that performs dashboard viewing in HTML format through native component.
*
* @author Tom Koptel
* @since 2.0
*/
@OptionsMenu(R.menu.dashboard_menu)
@EActivity
public abstract class BaseDashboardActivity extends ToolbarActivity
implements JasperWebViewClientListener, DefaultUrlPolicy.SessionListener {
@Extra
protected ResourceLookup resource;
protected WebView webView;
protected TextView emptyView;
protected ProgressBar progressBar;
private JasperChromeClientListenerImpl chromeClientListener;
@OptionsMenuItem(R.id.favoriteAction)
protected MenuItem favoriteActionButton;
@Bean
protected ScrollableTitleHelper scrollableTitleHelper;
@Inject
Analytics analytics;
@Inject
ResourcePrintJob mResourcePrintJob;
@Inject
JasperServer mServer;
@Inject
ScriptTagFactory mScriptTagFactory;
@Inject
FavoritesHelper favoritesHelper;
@Inject
AuthorizeSessionUseCase mAuthorizeSessionUseCase;
@Inject
SaveScreenCaptureCase mSaveScreenCaptureCase;
@Inject
@Named("webview_client")
OkHttpClient webViewResourceClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard_viewer);
webView = (WebView) findViewById(R.id.webView);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
emptyView = (TextView) findViewById(android.R.id.empty);
getComponent().inject(this);
initWebView();
scrollableTitleHelper.injectTitle(resource.getLabel());
}
public DashboardActivityComponent getComponent() {
return GraphObject.Factory.from(this)
.getProfileComponent()
.plusDashboardPage(
new ActivityModule(this),
new DashboardModule(webView, String.valueOf(resource.getResourceType()))
);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
favoritesHelper.updateFavoriteIconState(favoriteActionButton, resource.getUri());
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onDestroy() {
super.onDestroy();
if (webView != null) {
((ViewGroup) webView.getParent()).removeView(webView);
webView.removeAllViews();
webView.destroy();
}
}
@OptionsItem(R.id.favoriteAction)
protected void favoriteAction() {
favoritesHelper.switchFavoriteState(resource, favoriteActionButton);
}
@OptionsItem(R.id.aboutAction)
protected void aboutAction() {
SimpleDialogFragment.createBuilder(this, getSupportFragmentManager())
.setTitle(resource.getLabel())
.setMessage(resource.getDescription())
.setNegativeButtonText(R.string.ok)
.show();
}
@OptionsItem(R.id.printAction)
protected void printAction() {
Bundle args = new Bundle();
args.putString(ResourcePrintJob.PRINT_NAME_KEY, resource.getLabel());
mResourcePrintJob.printResource(args);
}
@OptionsItem(R.id.shareAction)
protected void shareAction() {
ScreenCapture screenCapture = ScreenCapture.Factory.capture(webView);
mSaveScreenCaptureCase.execute(screenCapture, new SimpleSubscriber<File>() {
@Override
public void onStart() {
showLoading();
}
@Override
public void onError(Throwable e) {
RequestExceptionHandler.showAuthErrorIfExists(BaseDashboardActivity.this, e);
}
@Override
public void onNext(File item) {
hideLoading();
navigateToAnnotationPage(item);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onHomeAsUpCalled();
return true;
}
return super.onOptionsItemSelected(item);
}
//---------------------------------------------------------------------
// Protected Util method
//---------------------------------------------------------------------
protected void resetZoom() {
while (webView.zoomOut()) ;
}
protected void showMessage(CharSequence message) {
if (!TextUtils.isEmpty(message) && emptyView != null) {
emptyView.setVisibility(View.VISIBLE);
emptyView.setText(message);
}
}
//---------------------------------------------------------------------
// JasperWebViewClientListener callbacks
//---------------------------------------------------------------------
@Override
public void onPageStarted(String newUrl) {
}
@Override
public void onReceivedError(int errorCode, String description, String failingUrl) {
}
@Override
public void onPageFinishedLoading(String url) {
onPageFinished();
}
//---------------------------------------------------------------------
// DefaultUrlPolicy.SessionListener callback
//---------------------------------------------------------------------
@Override
public void onSessionExpired() {
mAuthorizeSessionUseCase.execute(new GenericSubscriber<>(new SimpleSubscriber<Void>() {
@Override
public void onStart() {
Toast.makeText(BaseDashboardActivity.this, R.string.da_session_expired, Toast.LENGTH_SHORT).show();
}
@Override
public void onCompleted() {
onSessionRefreshed();
}
@Override
public void onError(Throwable e) {
RequestExceptionHandler.showAuthErrorIfExists(BaseDashboardActivity.this, e);
}
}));
}
protected void showLoading() {
ProgressDialogFragment.builder(getSupportFragmentManager())
.setLoadingMessage(R.string.da_loading)
.show();
}
protected void hideLoading() {
ProgressDialogFragment.dismiss(getSupportFragmentManager());
}
protected void showWebView(boolean visibility) {
webView.setVisibility(visibility ? View.VISIBLE : View.GONE);
}
//---------------------------------------------------------------------
// Abstract methods
//---------------------------------------------------------------------
public abstract void onWebViewConfigured(WebView webView);
public abstract void onPageFinished();
@OptionsItem(R.id.refreshAction)
protected abstract void onRefresh();
protected abstract void onHomeAsUpCalled();
public abstract void onSessionRefreshed();
//---------------------------------------------------------------------
// Helper methods
//---------------------------------------------------------------------
private void initWebView() {
chromeClientListener = new JasperChromeClientListenerImpl(progressBar);
UrlPolicy defaultPolicy = new DefaultUrlPolicy(mServer.getBaseUrl())
.withSessionListener(this);
SystemChromeClient systemChromeClient = new SystemChromeClient.Builder(this)
.withDelegateListener(chromeClientListener)
.build();
WebResourceInterceptor.Rule reportResourcesRule = VisualizeResourcesInterceptRule.getInstance();
WebResourceInterceptor cacheResourceInterceptor = new OkHttpWebResourceInterceptor.Builder()
.withClient(webViewResourceClient)
.registerRule(reportResourcesRule)
.build();
WebResourceInterceptor injectionRequestInterceptor = InjectionRequestInterceptor.getInstance();
SystemWebViewClient systemWebViewClient = new SystemWebViewClient.Builder()
.withDelegateListener(this)
.registerInterceptor(injectionRequestInterceptor)
.registerInterceptor(cacheResourceInterceptor)
.registerUrlPolicy(defaultPolicy)
.build();
WebViewEnvironment.configure(webView)
.withDefaultSettings()
.withChromeClient(systemChromeClient)
.withWebClient(systemWebViewClient);
onWebViewConfigured(webView);
}
private void navigateToAnnotationPage(File file) {
AnnotationActivity_.intent(this)
.imageUri(Uri.fromFile(file))
.start();
}
protected final class GenericSubscriber<R> extends ErrorSubscriber<R> {
protected GenericSubscriber(SimpleSubscriber<R> delegate) {
super(delegate);
}
@Override
public void onStart() {
showLoading();
super.onStart();
}
@Override
public void onCompleted() {
hideLoading();
super.onCompleted();
}
@Override
public void onError(Throwable e) {
Timber.e(e, "Dashboard thrown error");
hideLoading();
super.onError(e);
}
}
}