diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 8fc720b8..6a7ba75d 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -24,10 +24,10 @@ I have:
#### Expected result
+**What is the expected output?**
-What is the expected output?
+**What do you see instead?**
-What do you see instead?
Upload screenshots via drag&drop if needed and apply resizing:
`
`
diff --git a/.travis.yml b/.travis.yml
index 74b79b85..41f1aaaa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ android:
- tools
- tools # TODO https://github.com/travis-ci/travis-ci/issues/6193
- platform-tools
- - build-tools-24.0.1
+ - build-tools-24.0.2
- android-24
- extra-android-m2repository
before_cache:
diff --git a/README.md b/README.md
index a2696020..cc8704d6 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
[](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android)
-[](https://travis-ci.org/Diaspora-for-Android/diaspora-android)
+[](https://travis-ci.org/Diaspora-for-Android/diaspora-android)
[](https://crowdin.com/project/diaspora-for-android)
-[](https://gitter.im/Diaspora-for-Android/diaspora-android?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[](https://kiwiirc.com/client/irc.freenode.net/?nick=user-dfa|?#diaspora-for-android)
+[](https://gitter.im/Diaspora-for-Android/diaspora-android)
# Diaspora for Android
@@ -15,28 +16,28 @@ This is an unofficial webview based client for the community-run, distributed so
## Contributions
We are always open for any kind of contribution. (PR's, bug reports, feature requests, translations, ..)
-If you got any questions feel free to join our XMPP/Jabber conference at `diaspora-android@conference.jabberhead.tk` or [Gitter](https://gitter.im/Diaspora-for-Android/diaspora-android).
-Note that the main project members are mostly busy with their job/university/school and may not react or start coding immediately.
+If you got any questions feel free to contact us on IRC, XMPP or Gitter. You can start chatting by clicking on the [blue chat badges](#badgers) listed on top.
-We use Crowdin to translate Diaspora for Android. Join our project here:
-If your desired language is not listed please contact the maintainers/owner.
+We use Crowdin to translate Diaspora for Android. Join our project here: . If your desired language is not listed please contact the maintainers/owner.
+
+Note that the main project members are working on this project for free during leisure time, are mostly busy with their job/university/school, and may not react or start coding immediately.
### License
-It's released under GNU GENERAL PUBLIC LICENSE (see [LICENCE](https://github.com/Diaspora-for-Android/diaspora-android/blob/master/LICENSE.md)).
+Diaspora for Android is released under GNU GENERAL PUBLIC LICENSE (see [LICENCE](https://github.com/Diaspora-for-Android/diaspora-android/blob/master/LICENSE.md)).
### WebApp
-The app is developed as an WebApp because currently Diaspora doesn't have an API that can be used to create a native interface to retrieve the user's data, publications, direct messages and so on, that's why there are only WebApps for Diaspora out there.
+The app is developed as a WebApp because currently Diaspora doesn't have an API that can be used to create a native interface to retrieve the user's data, publications, direct messages and so on. That's why there are only WebApps for Diaspora out there.
[Stay tuned on Diaspora* Issues](https://github.com/diaspora/diaspora/labels/api) about API.
-Why a WebApp is better than using the mobile site on a browser?
+Why is a WebApp better than using the mobile site on a browser?
Basically it provides better integration with the system (events coming into and going out of the app), notifications, customized interface and functions and a nice little icon that takes you directly to your favorite social network :)
### Device Requirements
-The minimum version supported is Jelly Bean, Android v4.2.0 / API 17
+The minimum Android version supported is Jelly Bean, Android v4.2.0 / API 17
### App Permissions
-It requires access to the Internet and to external storage to be able to upload photos when creating a new post and for taking screenshots.
+Diaspora for Android requires access to the Internet and to external storage to be able to upload photos when creating a new post and for taking screenshots.
## Maintainers
-- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io))
-- vanitasvitae ([GitHub](https://github.com/vanitasvitae))
+- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c))
+- vanitasvitae ([GitHub](https://github.com/vanitasvitae), [Diaspora](https://pod.geraspora.de/people/bbd7af90fbec013213e34860008dbc6c))
diff --git a/SCREENSHOTS.md b/SCREENSHOTS.md
index 368da74a..8f443531 100644
--- a/SCREENSHOTS.md
+++ b/SCREENSHOTS.md
@@ -1,14 +1,24 @@
-  |
-  |
-  |
-  |
+  |
+  |
+  |
+  |
-  |
-  |
-  |
-  |
+  |
+  |
+  |
+  |
+
+
+  |
+  |
+  |
+  |
+
+
+  |
+  |
diff --git a/app/build.gradle b/app/build.gradle
index 4cb94656..0e7cceec 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -3,14 +3,14 @@ apply plugin: 'android-apt'
android {
compileSdkVersion 24
- buildToolsVersion "24.0.1"
+ buildToolsVersion "24.0.2"
defaultConfig {
applicationId "com.github.dfa.diaspora_android"
minSdkVersion 17
targetSdkVersion 24
versionCode 8
- versionName "0.1.6"
+ versionName "0.1.6-next"
}
buildTypes {
release {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2ef6cc59..3ee52fa8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,52 +12,40 @@
android:name="com.github.dfa.diaspora_android.App"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
+
-
-
-
-
-
-
-
-
+
+
-
+ android:label="@string/settings" />
-
-
+
+
+
+
+
+
@@ -255,9 +243,7 @@
-
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java
index f2c46bdd..cc9cf36d 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java
@@ -62,10 +62,10 @@ public class AboutActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
- @BindView(R.id.toolbar)
+ @BindView(R.id.main__topbar)
protected Toolbar toolbar;
- @BindView(R.id.linearlayout)
+ @BindView(R.id.appbar_linear_layout)
protected LinearLayout linearLayout;
@Override
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java
index c736489e..ca01035f 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java
@@ -18,33 +18,24 @@
*/
package com.github.dfa.diaspora_android.activity;
-import android.Manifest;
-import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.AlarmManager;
-import android.app.AlertDialog;
-import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
-import android.os.StrictMode;
-import android.provider.MediaStore;
import android.support.annotation.NonNull;
+import android.support.customtabs.CustomTabsSession;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
@@ -59,17 +50,10 @@ import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import android.webkit.JavascriptInterface;
-import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -77,43 +61,32 @@ import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.AppSettings;
import com.github.dfa.diaspora_android.data.PodUserProfile;
+import com.github.dfa.diaspora_android.fragment.BrowserFragment;
+import com.github.dfa.diaspora_android.fragment.CustomFragment;
+import com.github.dfa.diaspora_android.fragment.DiasporaStreamFragment;
+import com.github.dfa.diaspora_android.fragment.HashtagListFragment;
+import com.github.dfa.diaspora_android.fragment.PodSelectionFragment;
import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener;
-import com.github.dfa.diaspora_android.receivers.OpenExternalLinkReceiver;
-import com.github.dfa.diaspora_android.receivers.UpdateTitleReceiver;
+import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver;
+import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver;
import com.github.dfa.diaspora_android.ui.BadgeDrawable;
-import com.github.dfa.diaspora_android.ui.ContextMenuWebView;
-import com.github.dfa.diaspora_android.ui.CustomWebViewClient;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
-import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.util.WebHelper;
-import org.json.JSONException;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
-import info.guardianproject.netcipher.NetCipher;
-import info.guardianproject.netcipher.webkit.WebkitProxy;
public class MainActivity extends AppCompatActivity
- implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener {
+ implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener, CustomTabActivityHelper.ConnectionCallback {
- private static final int INPUT_FILE_REQUEST_CODE_NEW = 1;
- private static final int INPUT_FILE_REQUEST_CODE_OLD = 2;
- private static final int REQUEST_CODE_ASK_PERMISSIONS = 123;
+ public static final int REQUEST_CODE_ASK_PERMISSIONS = 123;
public static final int REQUEST_CODE__ACCESS_EXTERNAL_STORAGE = 124;
+ public static final int INPUT_FILE_REQUEST_CODE_NEW = 1;
+ public static final int INPUT_FILE_REQUEST_CODE_OLD = 2;
public static final String ACTION_OPEN_URL = "com.github.dfa.diaspora_android.MainActivity.open_url";
public static final String ACTION_OPEN_EXTERNAL_URL = "com.github.dfa.diaspora_android.MainActivity.open_external_url";
@@ -126,46 +99,34 @@ public class MainActivity extends AppCompatActivity
public static final String CONTENT_HASHTAG = "content://com.github.dfa.diaspora_android.mainactivity/";
private App app;
- private ValueCallback imageUploadFilePathCallbackNew;
- private ValueCallback imageUploadFilePathCallbackOld;
- private String mCameraPhotoPath;
private CustomTabActivityHelper customTabActivityHelper;
- private WebSettings webSettings;
private AppSettings appSettings;
private DiasporaUrlHelper urls;
private PodUserProfile podUserProfile;
private final Handler uiHandler = new Handler();
- private CustomWebViewClient webViewClient;
private OpenExternalLinkReceiver brOpenExternalLink;
private BroadcastReceiver brSetTitle;
private Snackbar snackbarExitApp;
private Snackbar snackbarNoInternet;
- private String textToBeShared = null;
+ private FragmentManager fm;
+ private CustomTabsSession customTabsSession;
/**
* UI Bindings
*/
- @BindView(R.id.content_layout)
- RelativeLayout contentLayout;
-
- @BindView(R.id.progressBar)
- ProgressBar progressBar;
-
- @BindView(R.id.toolbar)
+ @BindView(R.id.main__topbar)
Toolbar toolbarTop;
- @BindView(R.id.toolbar2)
+ @BindView(R.id.main__bottombar)
ActionMenuView toolbarBottom;
- @BindView(R.id.placeholder_webview)
- FrameLayout webviewPlaceholder;
-
- ContextMenuWebView webView;
+ @BindView(R.id.fragment_container)
+ FrameLayout fragmentContainer;
@BindView(R.id.main__navigaion_view)
NavigationView navView;
- @BindView(R.id.main__layout)
+ @BindView(R.id.main__navdrawer)
DrawerLayout navDrawer;
@@ -174,6 +135,8 @@ public class MainActivity extends AppCompatActivity
private TextView navheaderDescription;
private ImageView navheaderImage;
+ private String textToBeShared;
+
/**
* END UI Bindings
@@ -187,6 +150,7 @@ public class MainActivity extends AppCompatActivity
// Bind UI
setContentView(R.layout.main__activity);
+ ButterKnife.bind(this);
if ((app = (App) getApplication()) == null) AppLog.e(this, "App is null!");
if ((appSettings = app.getSettings()) == null) AppLog.e(this, "AppSettings is null!");
@@ -196,68 +160,65 @@ public class MainActivity extends AppCompatActivity
podUserProfile.setListener(this);
urls = new DiasporaUrlHelper(appSettings);
customTabActivityHelper = new CustomTabActivityHelper();
+ customTabActivityHelper.setConnectionCallback(this);
- setupUI(savedInstanceState);
-
- if (appSettings.isProxyEnabled()) {
- if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) {
- AppLog.e(this, "Could not enable Proxy");
- Toast.makeText(MainActivity.this, R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show();
- }
- } else if (appSettings.wasProxyEnabled()) {
- resetProxy();
- }
+ fm = getSupportFragmentManager();
+ setupUI();
brOpenExternalLink = new OpenExternalLinkReceiver(this);
brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() {
@Override
public void setTitle(int rId) {
- MainActivity.this.setTitle(rId);
+ CustomFragment top = getTopFragment();
+ if(top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) {
+ MainActivity.this.setTitle(rId);
+ }
}
@Override
public void setTitle(String title) {
- MainActivity.this.setTitle(title);
+ CustomFragment top = getTopFragment();
+ if(top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) {
+ MainActivity.this.setTitle(title);
+ }
}
});
+
+ if(!appSettings.hasPodDomain()) {
+ AppLog.d(this, "We have no pod. Show PodSelectionFragment");
+ showFragment(getFragment(PodSelectionFragment.TAG));
+ } else {
+ AppLog.d(this, "Pod found. Handle intents.");
+ //Handle intent
+ Intent intent = getIntent();
+ if (intent != null && intent.getAction() != null) {
+ handleIntent(intent);
+ } else {
+ openDiasporaUrl(urls.getStreamUrl());
+ }
+ }
}
- private void setupUI(Bundle savedInstanceState) {
+ /**
+ * Setup the user interface. Set up both toolbars and initialize the snackbars.
+ * Initialize the navigation drawer and apply intellihide settings.
+ */
+ private void setupUI() {
AppLog.i(this, "setupUI()");
- ButterKnife.bind(this);
- if (webviewPlaceholder.getChildCount() != 0) {
- AppLog.v(this, "remove child views from webViewPlaceholder");
- webviewPlaceholder.removeAllViews();
- } else {
- AppLog.v(this, "webViewPlaceholder had no child views");
- }
- boolean newWebView = (webView == null);
- if (newWebView) {
- AppLog.v(this, "WebView was null. Create new one.");
- View webviewHolder = getLayoutInflater().inflate(R.layout.ui__webview, this.contentLayout, false);
- this.webView = (ContextMenuWebView) webviewHolder.findViewById(R.id.webView);
- ((LinearLayout) webView.getParent()).removeView(webView);
- setupWebView(savedInstanceState);
- } else {
- AppLog.v(this, "Reuse old WebView to avoid reloading page");
- }
-
- AppLog.v(this, "Add WebView to placeholder");
- webviewPlaceholder.addView(webView);
// Setup toolbar
setSupportActionBar(toolbarTop);
- getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu());
toolbarBottom.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
- return MainActivity.this.onOptionsItemSelected(item);
+ CustomFragment top = getTopFragment();
+ return MainActivity.this.onOptionsItemSelected(item) || (top != null && top.onOptionsItemSelected(item));
}
});
setTitle(R.string.app_name);
//Setup snackbar
snackbarExitApp = Snackbar
- .make(contentLayout, R.string.confirm_exit, Snackbar.LENGTH_LONG)
+ .make(fragmentContainer, R.string.confirm_exit, Snackbar.LENGTH_LONG)
.setAction(android.R.string.yes, new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -265,24 +226,11 @@ public class MainActivity extends AppCompatActivity
moveTaskToBack(true);
}
});
- snackbarNoInternet = Snackbar.make(contentLayout, R.string.no_internet, Snackbar.LENGTH_LONG);
+ snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.no_internet, Snackbar.LENGTH_LONG);
// Load app settings
setupNavigationSlider();
- progressBar = (ProgressBar) findViewById(R.id.progressBar);
-
- String url = urls.getPodUrl();
- if (newWebView) {
- if (WebHelper.isOnline(MainActivity.this)) {
- AppLog.v(this, "setupUI: reload url");
- webView.loadData("", "text/html", null);
- webView.loadUrlNew(url);
- } else {
- snackbarNoInternet.show();
- }
- }
-
if (!appSettings.isIntellihideToolbars()) {
AppLog.v(this, "Disable intelligent hiding of toolbars");
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams();
@@ -290,183 +238,75 @@ public class MainActivity extends AppCompatActivity
}
AppLog.v(this, "UI successfully set up");
- handleIntent(getIntent());
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- AppLog.i(this, "onConfigurationChanged()");
- if (webView != null) {
- // Remove the WebView from the old placeholder
- AppLog.v(this, "removeView from placeholder in order to prevent recreation");
- webviewPlaceholder.removeView(webView);
- }
-
- super.onConfigurationChanged(newConfig);
-
- // Load the layout resource for the new configuration
- setContentView(R.layout.main__activity);
-
- // Reinitialize the UI
- AppLog.v(this, "Rebuild the UI");
- setupUI(null);
+ /**
+ * Show DiasporaStreamFragment if necessary and load URL url
+ * @param url URL to load in the DiasporaStreamFragment
+ */
+ public void openDiasporaUrl(String url) {
+ AppLog.v(this, "openDiasporaUrl()");
+ DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG);
+ showFragment(streamFragment);
+ streamFragment.loadUrl(url);
}
- private void setupWebView(Bundle savedInstanceState) {
-
- webSettings = webView.getSettings();
- webSettings.setJavaScriptEnabled(true);
- webSettings.setAllowFileAccess(false);
- webSettings.setUseWideViewPort(true);
- webSettings.setLoadWithOverviewMode(true);
- webSettings.setDomStorageEnabled(true);
- webSettings.setMinimumFontSize(appSettings.getMinimumFontSize());
- webSettings.setLoadsImagesAutomatically(appSettings.isLoadImages());
- webSettings.setAppCacheEnabled(true);
-
- if (savedInstanceState != null) {
- AppLog.v(this, "restore WebView state");
- webView.restoreState(savedInstanceState);
- }
-
- if (android.os.Build.VERSION.SDK_INT >= 21) {
- WebView.enableSlowWholeDocumentDraw();
- webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
- }
-
- this.registerForContextMenu(webView);
- webView.setParentActivity(this);
- webView.setOverScrollMode(WebView.OVER_SCROLL_ALWAYS);
-
- // Setup WebView
- webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge");
-
- //Set proxy
- if (appSettings.isProxyEnabled()) {
- if (!setProxy())
- Toast.makeText(this, R.string.toast_set_proxy_failed, Toast.LENGTH_LONG).show();
- }
-
- /*
- * WebViewClient
- */
- webViewClient = new CustomWebViewClient(app, webView);
- webView.setWebViewClient(webViewClient);
-
- /*
- * WebChromeClient
- */
- webView.setWebChromeClient(new WebChromeClient() {
-
- public void onProgressChanged(WebView wv, int progress) {
- progressBar.setProgress(progress);
-
- if (progress > 0 && progress <= 60) {
- WebHelper.getUserProfile(wv);
- WebHelper.optimizeMobileSiteLayout(wv);
- }
-
- if (progress > 60) {
- WebHelper.optimizeMobileSiteLayout(wv);
-
- if (textToBeShared != null) {
- WebHelper.shareTextIntoWebView(wv, textToBeShared);
- }
- }
-
- progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE);
+ /**
+ * Get an instance of the CustomFragment with the tag fragmentTag.
+ * If there was no instance so far, create a new one and add it to the FragmentManagers pool.
+ * If there is no Fragment with the corresponding Tag, return the top fragment.
+ * @param fragmentTag tag
+ * @return corresponding Fragment
+ */
+ protected CustomFragment getFragment(String fragmentTag) {
+ CustomFragment fragment = (CustomFragment) fm.findFragmentByTag(fragmentTag);
+ if(fragment != null) {
+ return fragment;
+ } else {
+ switch (fragmentTag) {
+ case DiasporaStreamFragment.TAG:
+ DiasporaStreamFragment dsf = new DiasporaStreamFragment();
+ fm.beginTransaction().add(dsf, fragmentTag).commit();
+ return dsf;
+ case BrowserFragment.TAG:
+ BrowserFragment bf = new BrowserFragment();
+ fm.beginTransaction().add(bf, fragmentTag).commit();
+ return bf;
+ case HashtagListFragment.TAG:
+ HashtagListFragment hlf = new HashtagListFragment();
+ fm.beginTransaction().add(hlf, fragmentTag).commit();
+ return hlf;
+ case PodSelectionFragment.TAG:
+ PodSelectionFragment psf = new PodSelectionFragment();
+ fm.beginTransaction().add(psf, fragmentTag).commit();
+ return psf;
+ default:
+ AppLog.e(this,"Invalid Fragment Tag: "+fragmentTag
+ +"\nAdd Fragments Tag to getFragment()'s switch case.");
+ return getTopFragment();
}
-
- //For Android 4.1/4.2 only. DO NOT REMOVE!
- @SuppressWarnings("unused")
- protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
- AppLog.v(this, "openFileChooser(ValCallback, String, String");
- imageUploadFilePathCallbackOld = uploadMsg;
- Intent intent = new Intent();
- intent.setType("image/*");
- intent.setAction(Intent.ACTION_GET_CONTENT);
- intent.putExtra("return-data", true);
- intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- AppLog.v(this, "startActivityForResult");
- startActivityForResult(Intent.createChooser(intent, "Select Picture"), INPUT_FILE_REQUEST_CODE_OLD);
- }
-
- @Override
- public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
- if (Build.VERSION.SDK_INT >= 23) {
- int hasWRITE_EXTERNAL_STORAGE = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
- if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
- if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
- new AlertDialog.Builder(MainActivity.this)
- .setMessage(R.string.permissions_image)
- .setNegativeButton(android.R.string.no, null)
- .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (android.os.Build.VERSION.SDK_INT >= 23)
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- REQUEST_CODE_ASK_PERMISSIONS);
- }
- })
- .show();
- return false;
- }
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- REQUEST_CODE_ASK_PERMISSIONS);
- return false;
- }
- }
-
- AppLog.v(MainActivity.this, "onOpenFileChooser");
- imageUploadFilePathCallbackNew = filePathCallback;
-
- Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
- // Create the File where the photo should go
- File photoFile;
- try {
- photoFile = Helpers.createImageFile();
- takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
- } catch (IOException ex) {
- AppLog.e(this, "ERROR creating temp file: " + ex.toString());
- // Error occurred while creating the File
- Snackbar.make(contentLayout, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show();
- return false;
- }
-
- // Continue only if the File was successfully created
- if (photoFile != null) {
- mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
- takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
- Uri.fromFile(photoFile));
- } else {
- takePictureIntent = null;
- }
- }
-
- Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
- contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
- contentSelectionIntent.setType("image/*");
-
- Intent[] intentArray;
- if (takePictureIntent != null) {
- intentArray = new Intent[]{takePictureIntent};
- } else {
- intentArray = new Intent[0];
- }
-
- Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
- chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
- chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
- chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
-
- AppLog.v(this, "startActivityForResult");
- startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE_NEW);
- return true;
- }
- });
+ }
}
+ /**
+ * Show the Fragment fragment in R.id.fragment_container. If the fragment was already visible, do nothing.
+ * @param fragment Fragment to show
+ */
+ protected void showFragment(CustomFragment fragment) {
+ AppLog.v(this, "showFragment()");
+ CustomFragment currentTop = (CustomFragment) fm.findFragmentById(R.id.fragment_container);
+ if(currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) {
+ AppLog.v(this, "Fragment was not visible. Replace it.");
+ fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit();
+ invalidateOptionsMenu();
+ } else {
+ AppLog.v(this, "Fragment was already visible. Do nothing.");
+ }
+ }
+
+ /**
+ * Initialize the navigation slider
+ */
private void setupNavigationSlider() {
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, navDrawer, toolbarTop, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
@@ -478,12 +318,13 @@ public class MainActivity extends AppCompatActivity
View navHeader = navView.getHeaderView(0);
LinearLayout navheaderProfileSection = ButterKnife.findById(navHeader, R.id.nav_profile_picture);
+ //Handle clicks on profile picture
navheaderProfileSection.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
navDrawer.closeDrawer(GravityCompat.START);
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getProfileUrl());
+ openDiasporaUrl(urls.getProfileUrl());
} else {
snackbarNoInternet.show();
}
@@ -523,26 +364,27 @@ public class MainActivity extends AppCompatActivity
navMenu.findItem(R.id.nav_aspects).setVisible(appSettings.isVisibleInNavAspects());
navMenu.findItem(R.id.nav_commented).setVisible(appSettings.isVisibleInNavCommented());
navMenu.findItem(R.id.nav_followed_tags).setVisible(appSettings.isVisibleInNavFollowed_tags());
- navMenu.findItem(R.id.nav_help_license).setVisible(appSettings.isVisibleInNavHelp_license());
+ navMenu.findItem(R.id.nav_about).setVisible(appSettings.isVisibleInNavHelp_license());
navMenu.findItem(R.id.nav_liked).setVisible(appSettings.isVisibleInNavLiked());
navMenu.findItem(R.id.nav_mentions).setVisible(appSettings.isVisibleInNavMentions());
navMenu.findItem(R.id.nav_profile).setVisible(appSettings.isVisibleInNavProfile());
navMenu.findItem(R.id.nav_public).setVisible(appSettings.isVisibleInNavPublic_activities());
}
-
- @OnClick(R.id.toolbar)
- public void onToolBarClicked(View view) {
- AppLog.i(this, "onToolBarClicked()");
- onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream));
- }
-
+
+ /**
+ * Forward incoming intents to handleIntent()
+ * @param intent incoming
+ */
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
-
handleIntent(intent);
}
+ /**
+ * Handle intents and execute intent specific actions
+ * @param intent intent to get handled
+ */
private void handleIntent(Intent intent) {
AppLog.i(this, "handleIntent()");
if (intent == null) {
@@ -554,7 +396,9 @@ public class MainActivity extends AppCompatActivity
String type = intent.getType();
String loadUrl = null;
AppLog.v(this, "Action: " + action + " Type: " + type);
- if (ACTION_OPEN_URL.equals(action)) {
+ if (Intent.ACTION_MAIN.equals(action)) {
+ loadUrl = urls.getStreamUrl();
+ } else if (ACTION_OPEN_URL.equals(action)) {
loadUrl = intent.getStringExtra(URL_MESSAGE);
} else if (Intent.ACTION_VIEW.equals(action) && intent.getDataString() != null) {
Uri data = intent.getData();
@@ -563,14 +407,15 @@ public class MainActivity extends AppCompatActivity
return;
} else {
loadUrl = intent.getDataString();
+ AppLog.v(this, "Intent has a delicious URL for us: "+loadUrl);
}
} else if (ACTION_CHANGE_ACCOUNT.equals(action)) {
- AppLog.v(this, "Reset pod data and animate to PodSelectionActivity");
- app.resetPodData(webView);
- Helpers.animateToActivity(MainActivity.this, PodSelectionActivity.class, true);
+ AppLog.v(this, "Reset pod data and show PodSelectionFragment");
+ app.resetPodData(((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView());
+ showFragment(getFragment(PodSelectionFragment.TAG));
} else if (ACTION_CLEAR_CACHE.equals(action)) {
AppLog.v(this, "Clear WebView cache");
- webView.clearCache(true);
+ ((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView().clearCache(true);
} else if (ACTION_RELOAD_ACTIVITY.equals(action)) {
AppLog.v(this, "Recreate activity");
recreate();
@@ -589,101 +434,43 @@ public class MainActivity extends AppCompatActivity
break;
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
- //TODO: Implement and add filter to manifest
+ /* TODO: Implement and add filter to manifest */
+ return;
}
if (loadUrl != null) {
- webView.stopLoading();
navDrawer.closeDrawers();
- webView.loadUrlNew(loadUrl);
+ openDiasporaUrl(loadUrl);
}
}
+ /**
+ * Handle activity results
+ * @param requestCode reqCode
+ * @param resultCode resCode
+ * @param data data
+ */
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- AppLog.v(this, "onActivityResult()");
- switch (requestCode) {
- case INPUT_FILE_REQUEST_CODE_NEW: {
- AppLog.v(this, "Upload image using recent method (Lollipop+)");
- if (imageUploadFilePathCallbackNew == null || resultCode != Activity.RESULT_OK) {
- AppLog.e(this, "Callback is null: " + (imageUploadFilePathCallbackNew == null)
- + " resultCode: " + resultCode);
- if(imageUploadFilePathCallbackNew != null)
- imageUploadFilePathCallbackNew.onReceiveValue(new Uri[]{});
- return;
- }
- Uri[] results = null;
- if (data == null) {
- if (mCameraPhotoPath != null) {
- AppLog.v(this, "Intent data is null. Try to parse cameraPhotoPath");
- results = new Uri[]{Uri.parse(mCameraPhotoPath)};
- } else {
- AppLog.w(this, "Intent data is null and cameraPhotoPath is null");
- }
- } else {
- String dataString = data.getDataString();
- if (dataString != null) {
- AppLog.v(this, "Intent has data. Try to parse dataString");
- results = new Uri[]{Uri.parse(dataString)};
- }
- AppLog.w(this, "dataString is null");
- }
- AppLog.v(this, "handle received result over to callback");
- imageUploadFilePathCallbackNew.onReceiveValue(results);
- imageUploadFilePathCallbackNew = null;
- return;
- }
- case INPUT_FILE_REQUEST_CODE_OLD: {
- AppLog.v(this, "Upload image using legacy method (Jelly Bean, Kitkat)");
- if (imageUploadFilePathCallbackOld == null || resultCode != Activity.RESULT_OK) {
- AppLog.e(this, "Callback is null: " + (imageUploadFilePathCallbackOld == null)
- + " resultCode: " + resultCode);
- if(imageUploadFilePathCallbackOld != null)
- imageUploadFilePathCallbackOld.onReceiveValue(null);
- return;
- }
- Uri results = null;
- if (data == null) {
- if (mCameraPhotoPath != null) {
- AppLog.v(this, "Intent has no data. Try to parse cameraPhotoPath");
- results = Uri.parse(mCameraPhotoPath);
- } else {
- AppLog.w(this, "Intent has no data and cameraPhotoPath is null");
- }
- } else {
- String dataString = data.getDataString();
- if (dataString != null) {
- AppLog.v(this, "Intent has data. Try to parse dataString");
- results = Uri.parse(dataString);
- } else {
- AppLog.w(this, "dataString is null");
- }
- }
- AppLog.v(this, "handle received result over to callback");
- imageUploadFilePathCallbackOld.onReceiveValue(results);
- imageUploadFilePathCallbackOld = null;
- return;
- }
- }
+ AppLog.v(this, "onActivityResult(): "+requestCode);
super.onActivityResult(requestCode, resultCode, data);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- AppLog.v(this, "onSaveInstanceState()");
- super.onSaveInstanceState(outState);
- AppLog.v(this, "Save WebView state");
- webView.saveState(outState);
- }
-
- @Override
- protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
- AppLog.v(this, "onRestoreInstanceState()");
- super.onRestoreInstanceState(savedInstanceState);
- AppLog.v(this, "Restore state of WebView");
- webView.restoreState(savedInstanceState);
+ /**
+ * Return the fragment which is currently displayed in R.id.fragment_container
+ * @return top fragment or null if there is none displayed
+ */
+ private CustomFragment getTopFragment() {
+ Fragment top = fm.findFragmentById(R.id.fragment_container);
+ if(top != null) {
+ return (CustomFragment) top;
+ }
+ return null;
}
+ /**
+ * Handle presses on the back button
+ */
@Override
public void onBackPressed() {
AppLog.v(this, "onBackPressed()");
@@ -691,10 +478,22 @@ public class MainActivity extends AppCompatActivity
navDrawer.closeDrawer(navView);
return;
}
-
- if (webView.canGoBack()) {
- webView.goBack();
- return;
+ CustomFragment top = getTopFragment();
+ if(top != null) {
+ AppLog.v(this, "Top Fragment is not null");
+ if(!top.onBackPressed()) {
+ AppLog.v(this, "Top Fragment.onBackPressed was false");
+ AppLog.v(this, "BackStackEntryCount: "+fm.getBackStackEntryCount());
+ if(fm.getBackStackEntryCount()>0) {
+ fm.popBackStack();
+ } else {
+ snackbarExitApp.show();
+ }
+ return;
+ } else {
+ AppLog.v(this, "Top Fragment.onBackPressed was true");
+ return;
+ }
}
if (!snackbarExitApp.isShown()) {
@@ -732,13 +531,42 @@ public class MainActivity extends AppCompatActivity
LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL));
}
+ /**
+ * Clear and repopulate top and bottom toolbar.
+ * Also add menu items of the displayed fragment
+ * @param menu top toolbar
+ * @return boolean
+ */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
AppLog.v(this, "onCreateOptionsMenu()");
- getMenuInflater().inflate(R.menu.main__menu_top, menu);
+ //Clear the menus
+ menu.clear();
+ toolbarBottom.getMenu().clear();
+ toolbarBottom.setVisibility(View.VISIBLE);
+
+ CustomFragment top = getTopFragment();
+ if(top != null) {
+ //Are we displaying a Fragment other than PodSelectionFragment?
+ if(!top.getFragmentTag().equals(PodSelectionFragment.TAG)) {
+ getMenuInflater().inflate(R.menu.main__menu_top, menu);
+ getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu());
+ top.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater());
+ }
+ //PodSelectionFragment
+ else {
+ //Hide bottom toolbar
+ toolbarBottom.setVisibility(View.GONE);
+ }
+ }
return true;
}
+ /**
+ * Set the notification and messages counter in the top toolbar
+ * @param menu menu
+ * @return boolean
+ */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item;
@@ -755,13 +583,18 @@ public class MainActivity extends AppCompatActivity
return super.onPrepareOptionsMenu(menu);
}
+ /**
+ * Handle clicks on the optionsmenu
+ * @param item item
+ * @return boolean
+ */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
AppLog.i(this, "onOptionsItemSelected()");
switch (item.getItemId()) {
case R.id.action_notifications: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getNotificationsUrl());
+ openDiasporaUrl(urls.getNotificationsUrl());
return true;
} else {
snackbarNoInternet.show();
@@ -771,17 +604,7 @@ public class MainActivity extends AppCompatActivity
case R.id.action_conversations: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getConversationsUrl());
- return true;
- } else {
- snackbarNoInternet.show();
- return false;
- }
- }
-
- case R.id.action_reload: {
- if (WebHelper.isOnline(MainActivity.this)) {
- webView.reload();
+ openDiasporaUrl(urls.getConversationsUrl());
return true;
} else {
snackbarNoInternet.show();
@@ -795,47 +618,15 @@ public class MainActivity extends AppCompatActivity
return true;
}
- case R.id.action_toggle_desktop_page: {
- webView.loadUrlNew(urls.getToggleMobileUrl());
- return true;
- }
-
case R.id.action_compose: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getNewPostUrl());
+ openDiasporaUrl(urls.getNewPostUrl());
} else {
snackbarNoInternet.show();
}
return true;
}
- case R.id.action_go_to_top: {
- // Scroll to top (animated)
- ObjectAnimator anim = ObjectAnimator.ofInt(webView, "scrollY", webView.getScrollY(), 0);
- anim.setDuration(400);
- anim.start();
- return true;
- }
-
- case R.id.action_share_link: {
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("text/plain");
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
- sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
- startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot)));
- return true;
- }
-
- case R.id.action_take_screenshot: {
- makeScreenshotOfWebView(false);
- return true;
- }
-
- case R.id.action_share_screenshot: {
- makeScreenshotOfWebView(true);
- return true;
- }
-
case R.id.action_search: {
if (WebHelper.isOnline(MainActivity.this)) {
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -847,9 +638,9 @@ public class MainActivity extends AppCompatActivity
public void onClick(DialogInterface dialogInterface, int which) {
String query = input.getText().toString().trim().replaceAll((which == DialogInterface.BUTTON_NEGATIVE ? "\\*" : "\\#"), "");
if (query.equals("")) {
- Snackbar.make(contentLayout, R.string.search_alert_bypeople_validate_needsomedata, Snackbar.LENGTH_LONG).show();
+ Snackbar.make(fragmentContainer, R.string.search_alert_bypeople_validate_needsomedata, Snackbar.LENGTH_LONG).show();
} else {
- webView.loadUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query));
+ openDiasporaUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query));
}
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
imm.hideSoftInputFromWindow(input.getWindowToken(), 0);
@@ -890,100 +681,30 @@ public class MainActivity extends AppCompatActivity
return super.onOptionsItemSelected(item);
}
- @SuppressWarnings("ResultOfMethodCallIgnored")
- private boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) {
- AppLog.i(this, "makeScreenshotOfWebView()");
- if (android.os.Build.VERSION.SDK_INT >= 23) {
- int hasWRITE_EXTERNAL_STORAGE = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
- if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
- if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
- new AlertDialog.Builder(MainActivity.this)
- .setMessage(R.string.permissions_screenshot)
- .setNegativeButton(android.R.string.no, null)
- .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (android.os.Build.VERSION.SDK_INT >= 23)
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- REQUEST_CODE_ASK_PERMISSIONS);
- }
- })
- .show();
- return false;
- }
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- REQUEST_CODE_ASK_PERMISSIONS);
- return false;
- }
- }
-
- Date dateNow = new Date();
- DateFormat dateFormat = new SimpleDateFormat("yy_MM_dd--HH_mm_ss", Locale.getDefault());
- File fileSaveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/Diaspora");
-
- String fileSaveName = hasToShareScreenshot ? ".DfA_share.jpg" : String.format("DfA_%s.jpg", dateFormat.format(dateNow));
- if (!fileSaveDirectory.exists()) {
- if (!fileSaveDirectory.mkdirs()) {
- AppLog.w(this, "Could not mkdir " + fileSaveDirectory.getAbsolutePath());
- }
- }
-
- if (!hasToShareScreenshot) {
- Snackbar.make(contentLayout, getString(R.string.share__toast_screenshot) + " " + fileSaveName, Snackbar.LENGTH_LONG).show();
- }
-
- Bitmap bitmap;
- webView.setDrawingCacheEnabled(true);
- bitmap = Bitmap.createBitmap(webView.getDrawingCache());
- webView.setDrawingCacheEnabled(false);
-
- OutputStream bitmapWriter = null;
- try {
- bitmapWriter = new FileOutputStream(new File(fileSaveDirectory, fileSaveName));
- bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bitmapWriter);
- bitmapWriter.flush();
- bitmap.recycle();
- } catch (Exception e) {
- return false;
- } finally {
- if (bitmapWriter != null) {
- try {
- bitmapWriter.close();
- } catch (IOException _ignSaveored) {/* Nothing */}
- }
- }
-
- // Only show share intent when Action Share Screenshot was selected
- if (hasToShareScreenshot) {
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/jpeg");
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
- sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
- Uri bmpUri = Uri.fromFile(new File(fileSaveDirectory, fileSaveName));
- sharingIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
- startActivity(Intent.createChooser(sharingIntent, getString(R.string.action_share_dotdotdot)));
- } else {
- // Broadcast that this file is indexable
- File file = new File(fileSaveDirectory, fileSaveName);
- Uri uri = Uri.fromFile(file);
- Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
- sendBroadcast(intent);
- }
- return true;
- }
-
+ /**
+ * Update the profile name in the navigation slider
+ * @param name name
+ */
@Override
public void onUserProfileNameChanged(String name) {
AppLog.i(this, "onUserProfileNameChanged()");
navheaderTitle.setText(name);
}
+ /**
+ * Update the profile picture in the navigation slider
+ * @param avatarUrl url of the new profile pic
+ */
@Override
public void onUserProfileAvatarChanged(String avatarUrl) {
AppLog.i(this, "onUserProfileAvatarChanged()");
app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl);
}
+ /**
+ * Handle hashtag clicks. Open the new-post-url and inject the clicked hashtag into the post-editor
+ * @param intent intent
+ */
private void handleHashtag(Intent intent) {
AppLog.v(this, "handleHashtag()");
try {
@@ -991,18 +712,21 @@ public class MainActivity extends AppCompatActivity
} catch (Exception e) {
AppLog.e(this, e.toString());
}
- webView.loadUrlNew(urls.getNewPostUrl());
+ openDiasporaUrl(urls.getNewPostUrl());
}
+ /**
+ * Open the new-post-url and inject text that was shared into the app into the post editors text field
+ * @param intent shareTextIntent
+ */
private void handleSendText(Intent intent) {
AppLog.v(this, "handleSendText()");
try {
setSharedTexts(null, intent.getStringExtra(Intent.EXTRA_TEXT));
+ openDiasporaUrl(urls.getNewPostUrl());
} catch (Exception e) {
AppLog.e(this, e.toString());
}
- webView.loadUrlNew(urls.getBlankUrl());
- webView.loadUrlNew(urls.getNewPostUrl());
}
/**
@@ -1014,14 +738,14 @@ public class MainActivity extends AppCompatActivity
AppLog.v(this, "handleSendSubject()");
try {
setSharedTexts(intent.getStringExtra(Intent.EXTRA_SUBJECT), intent.getStringExtra(Intent.EXTRA_TEXT));
+ openDiasporaUrl(urls.getNewPostUrl());
} catch (Exception e) {
AppLog.e(this, e.toString());
}
- webView.loadUrlNew(urls.getBlankUrl()); //TODO: Necessary?
- webView.loadUrlNew(urls.getNewPostUrl());
}
/**
+ * TODO: MOVE
* Set sharedText variable to escaped and formatted subject + body.
* If subject is null, only the body will be set. Else the subject will be set as header.
* Depending on whether the user has the setting isAppendSharedViaApp set, a reference to
@@ -1041,29 +765,34 @@ public class MainActivity extends AppCompatActivity
if (sharedSubject != null) {
AppLog.v(this, "Append subject to shared text");
String escapedSubject = WebHelper.escapeHtmlText(WebHelper.replaceUrlWithMarkdown(sharedSubject));
+ AppLog.v(this, "Set shared text; Subject: \"" + escapedSubject + "\" Body: \"" + escapedBody + "\"");
textToBeShared = "**" + escapedSubject + "** " + escapedBody;
} else {
AppLog.v(this, "Set shared text; Subject: \"" + sharedSubject + "\" Body: \"" + sharedBody + "\"");
textToBeShared = escapedBody;
}
-
-
}
- //TODO: Implement?
+ /**
+ * Share an image shared to the app via diaspora
+ * @param intent shareImageIntent
+ */
+ //TODO: Implement some day
private void handleSendImage(Intent intent) {
AppLog.i(this, "handleSendImage()");
final Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
AppLog.v(this, "imageUri is not null. Handle shared image");
- // TODO: Update UI to reflect text being shared
} else {
AppLog.w(this, "imageUri is null. Cannot precede.");
}
Toast.makeText(this, "Not yet implemented.", Toast.LENGTH_SHORT).show();
}
- // TODO: Move from Javascript interface
+ /**
+ * Invalidate the top toolbar to update the notification counter
+ * @param notificationCount new notification count
+ */
@Override
public void onNotificationCountChanged(int notificationCount) {
AppLog.i(this, "onNotificationCountChanged()");
@@ -1071,7 +800,10 @@ public class MainActivity extends AppCompatActivity
invalidateOptionsMenu();
}
- // TODO: Move from Javascript interface
+ /**
+ * Invalidate the top toolbar to update the unread messages counter
+ * @param unreadMessageCount new unread messages count
+ */
@Override
public void onUnreadMessageCountChanged(int unreadMessageCount) {
AppLog.i(this, "onUnreadMessageCountChanged()");
@@ -1079,22 +811,17 @@ public class MainActivity extends AppCompatActivity
invalidateOptionsMenu();
}
- private class JavaScriptInterface {
- @JavascriptInterface
- public void setUserProfile(final String webMessage) throws JSONException {
- AppLog.spam(this, "JavaScriptInterface.setUserProfile()");
- if (podUserProfile.isRefreshNeeded()) {
- AppLog.spam(this, "PodUserProfile needs refresh; Try to parse JSON");
- podUserProfile.parseJson(webMessage);
- } else {
- AppLog.spam(this, "No PodUserProfile refresh needed");
- }
+ @Override
+ public void onCustomTabsConnected() {
+ if(customTabsSession == null) {
+ AppLog.i(this, "CustomTabs warmup: "+customTabActivityHelper.warmup(0));
+ customTabsSession = customTabActivityHelper.getSession();
}
+ }
+
+ @Override
+ public void onCustomTabsDisconnected() {
- @JavascriptInterface
- public void contentHasBeenShared() {
- textToBeShared = null;
- }
}
@SuppressWarnings("StatementWithEmptyBody")
@@ -1105,7 +832,7 @@ public class MainActivity extends AppCompatActivity
switch (item.getItemId()) {
case R.id.nav_stream: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getStreamUrl());
+ openDiasporaUrl(urls.getStreamUrl());
} else {
snackbarNoInternet.show();
}
@@ -1114,7 +841,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_profile: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getProfileUrl());
+ openDiasporaUrl(urls.getProfileUrl());
} else {
snackbarNoInternet.show();
}
@@ -1122,19 +849,16 @@ public class MainActivity extends AppCompatActivity
break;
case R.id.nav_followed_tags: {
- if (WebHelper.isOnline(MainActivity.this)) {
- WebHelper.showFollowedTagsList(webView, app);
- setTitle(R.string.nav_followed_tags);
- } else {
- snackbarNoInternet.show();
- }
+ showFragment(getFragment(HashtagListFragment.TAG));
}
break;
+ //TODO: Replace with fragment
case R.id.nav_aspects: {
+ DiasporaStreamFragment stream = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG);
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(DiasporaUrlHelper.URL_BLANK);
- WebHelper.showAspectList(webView, app);
+ openDiasporaUrl(DiasporaUrlHelper.URL_BLANK);
+ WebHelper.showAspectList(stream.getWebView(), app);
setTitle(R.string.aspects);
} else {
snackbarNoInternet.show();
@@ -1144,7 +868,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_activities: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getActivityUrl());
+ openDiasporaUrl(urls.getActivityUrl());
} else {
snackbarNoInternet.show();
}
@@ -1153,7 +877,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_liked: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getLikedPostsUrl());
+ openDiasporaUrl(urls.getLikedPostsUrl());
} else {
snackbarNoInternet.show();
}
@@ -1162,7 +886,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_commented: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getCommentedUrl());
+ openDiasporaUrl(urls.getCommentedUrl());
} else {
snackbarNoInternet.show();
}
@@ -1171,7 +895,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_mentions: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getMentionsUrl());
+ openDiasporaUrl(urls.getMentionsUrl());
} else {
snackbarNoInternet.show();
}
@@ -1180,7 +904,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_public: {
if (WebHelper.isOnline(MainActivity.this)) {
- webView.loadUrlNew(urls.getPublicUrl());
+ openDiasporaUrl(urls.getPublicUrl());
} else {
snackbarNoInternet.show();
}
@@ -1198,7 +922,7 @@ public class MainActivity extends AppCompatActivity
}
break;
- case R.id.nav_help_license: {
+ case R.id.nav_about: {
startActivity(new Intent(MainActivity.this, AboutActivity.class));
}
break;
@@ -1208,6 +932,12 @@ public class MainActivity extends AppCompatActivity
return true;
}
+ /**
+ * React to results of requestPermission
+ * @param requestCode resCode
+ * @param permissions requested permissions
+ * @param grantResults granted results
+ */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
@@ -1228,81 +958,18 @@ public class MainActivity extends AppCompatActivity
}
/**
- * Set proxy according to arguments. host must not be "" or null, port must be positive.
- * Return true on success and update appSettings' proxy related values.
- *
- * @param host proxy host (eg. localhost or 127.0.0.1)
- * @param port proxy port (eg. 8118)
- * @return success
- * @throws IllegalArgumentException if arguments do not fit specifications above
+ * Return the string that will be shared into the new-post-editor
+ * @return String
*/
- private boolean setProxy(final String host, final int port) {
- AppLog.v(this, "setProxy()");
- if (host != null && !host.equals("") && port >= 0) {
- AppLog.v(this, "Set proxy to " + host + ":" + port);
- //Temporary change thread policy
- AppLog.v(this, "Set temporary ThreadPolicy");
- StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
- StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
- StrictMode.setThreadPolicy(tmp);
-
- AppLog.v(this, "Apply NetCipher proxy settings");
- NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections
- try {
- //Proxy for the ui__webview
- AppLog.v(this, "Apply Webkit proxy settings");
- WebkitProxy.setProxy(MainActivity.class.getName(), getApplicationContext(), null, host, port);
- } catch (Exception e) {
- AppLog.e(this, "Could not apply WebKit proxy settings:\n" + e.toString());
- }
- AppLog.v(this, "Save changes in appSettings");
- appSettings.setProxyEnabled(true);
- appSettings.setProxyWasEnabled(true);
-
- AppLog.v(this, "Reset old ThreadPolicy");
- StrictMode.setThreadPolicy(old);
- AppLog.v(this, "Success! Reload WebView");
- webView.reload();
- return true;
- } else {
- AppLog.w(this, "Invalid proxy configuration. Host: " + host + " Port: " + port + "\nRefuse to set proxy");
- return false;
- }
+ public String getTextToBeShared() {
+ return textToBeShared;
}
- private boolean setProxy() {
- return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort());
- }
-
- private void resetProxy() {
- AppLog.i(this, "resetProxy()");
- AppLog.v(this, "write changes to appSettings");
- appSettings.setProxyEnabled(false);
- appSettings.setProxyWasEnabled(false);
-
- //Temporary change thread policy
- AppLog.v(this, "Set temporary ThreadPolicy");
- StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
- StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
- StrictMode.setThreadPolicy(tmp);
-
- AppLog.v(this, "clear NetCipher proxy");
- NetCipher.clearProxy();
- try {
- AppLog.v(this, "clear WebKit proxy");
- WebkitProxy.resetProxy(MainActivity.class.getName(), this);
- } catch (Exception e) {
- AppLog.e(this, "Could not clear WebKit proxy:\n" + e.toString());
- }
- AppLog.v(this, "Reset old ThreadPolicy");
- StrictMode.setThreadPolicy(old);
-
- //Restart app
- AppLog.i(this, "Success! Restart app due to proxy reset");
- Intent restartActivity = new Intent(this, MainActivity.class);
- PendingIntent pendingIntent = PendingIntent.getActivity(this, 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
- System.exit(0);
+ /**
+ * Set the string that will be shared into the new-post-editor
+ * @param textToBeShared
+ */
+ public void setTextToBeShared(String textToBeShared) {
+ this.textToBeShared = textToBeShared;
}
}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java
index a1af7b9d..af1f3860 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java
@@ -94,8 +94,7 @@ public class SettingsActivity extends AppCompatActivity {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key));
- if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__clear_cache)) ||
- key.equals(getString(R.string.pref_key__font_size)) ||
+ if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__font_size)) ||
key.equals(getString(R.string.pref_key__load_images)) ||
key.equals(getString(R.string.pref_key__intellihide_toolbars)) ||
key.equals(getString(R.string.pref_key__http_proxy_enabled)) ||
@@ -162,11 +161,17 @@ public class SettingsActivity extends AppCompatActivity {
return true;
}
case R.string.pref_title__http_proxy_load_tor_preset: {
- ((EditTextPreference)findPreference(getString(R.string.pref_key__http_proxy_host))).setText("127.0.0.1");
- ((EditTextPreference)findPreference(getString(R.string.pref_key__http_proxy_port))).setText("8118");
+ ((EditTextPreference) findPreference(getString(R.string.pref_key__http_proxy_host))).setText("127.0.0.1");
+ ((EditTextPreference) findPreference(getString(R.string.pref_key__http_proxy_port))).setText("8118");
return true;
}
+ case R.string.pref_title__clear_cache:
+ {
+ intent.setAction(MainActivity.ACTION_CLEAR_CACHE);
+ break;
+ }
+
default: {
intent = null;
break;
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java
deleted file mode 100644
index 0eeccd3c..00000000
--- a/app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- This file is part of the Diaspora for Android.
-
- Diaspora for Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Diaspora for Android 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with the Diaspora for Android.
-
- If not, see .
- */
-
-package com.github.dfa.diaspora_android.activity;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v7.app.AppCompatActivity;
-
-import com.github.dfa.diaspora_android.App;
-import com.github.dfa.diaspora_android.R;
-import com.github.dfa.diaspora_android.util.Helpers;
-
-import butterknife.ButterKnife;
-
-
-public class SplashActivity extends AppCompatActivity {
- private App app;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.splash__activity);
- ButterKnife.bind(this);
- app = (App) getApplication();
-
- int delay = getResources().getInteger(R.integer.splash_delay);
- new Handler().postDelayed(startActivityRunnable, delay);
- }
-
- private final Runnable startActivityRunnable = new Runnable() {
- public void run() {
- boolean hasPodDomain = app.getSettings().hasPodDomain();
- Helpers.animateToActivity(SplashActivity.this,
- hasPodDomain ? MainActivity.class : PodSelectionActivity.class,
- true
- );
- }
- };
-}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java
new file mode 100644
index 00000000..70ee1054
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java
@@ -0,0 +1,371 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.fragment;
+
+import android.Manifest;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.StrictMode;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AlertDialog;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import com.github.dfa.diaspora_android.App;
+import com.github.dfa.diaspora_android.R;
+import com.github.dfa.diaspora_android.activity.MainActivity;
+import com.github.dfa.diaspora_android.data.AppSettings;
+import com.github.dfa.diaspora_android.ui.ContextMenuWebView;
+import com.github.dfa.diaspora_android.webview.CustomWebViewClient;
+import com.github.dfa.diaspora_android.webview.ProgressBarWebChromeClient;
+import com.github.dfa.diaspora_android.util.AppLog;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import info.guardianproject.netcipher.NetCipher;
+import info.guardianproject.netcipher.webkit.WebkitProxy;
+
+/**
+ * Fragment with a webView and a ProgressBar.
+ * This Fragment retains its instance.
+ * Created by vanitas on 26.09.16.
+ */
+
+public class BrowserFragment extends CustomFragment {
+ public static final String TAG = "com.github.dfa.diaspora_android.BrowserFragment";
+
+ protected View rootLayout;
+ protected ContextMenuWebView webView;
+ protected ProgressBar progressBar;
+ protected AppSettings appSettings;
+ protected CustomWebViewClient webViewClient;
+ protected WebSettings webSettings;
+
+ protected String pendingUrl;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ AppLog.d(this, "onCreateView()");
+ if(rootLayout == null) {
+ rootLayout = inflater.inflate(R.layout.browser__fragment, container, false);
+ }
+ return rootLayout;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ AppLog.d(this, "onViewCreated()");
+ super.onViewCreated(view, savedInstanceState);
+
+ if(this.appSettings == null) {
+ this.appSettings = ((App) getActivity().getApplication()).getSettings();
+ }
+
+ if(this.webView == null) {
+ this.webView = (ContextMenuWebView) view.findViewById(R.id.webView);
+ this.applyWebViewSettings();
+ }
+
+ if(this.progressBar == null) {
+ this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
+ }
+
+ if (appSettings.isProxyEnabled()) {
+ if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) {
+ AppLog.e(this, "Could not enable Proxy");
+ Toast.makeText(getContext(), R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show();
+ }
+ } else if (appSettings.wasProxyEnabled()) {
+ resetProxy();
+ }
+
+ if(pendingUrl != null) {
+ loadUrl(pendingUrl);
+ pendingUrl = null;
+ }
+
+ webView.setParentActivity(getActivity());
+
+ this.setRetainInstance(true);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+
+ if (getRetainInstance() && rootLayout.getParent() instanceof ViewGroup) {
+ ((ViewGroup) rootLayout.getParent()).removeView(rootLayout);
+ }
+ }
+
+ private void applyWebViewSettings() {
+ this.webSettings = webView.getSettings();
+ webSettings.setAllowFileAccess(false);
+ webSettings.setUseWideViewPort(true);
+ webSettings.setLoadWithOverviewMode(true);
+ webSettings.setDomStorageEnabled(true);
+ webSettings.setMinimumFontSize(appSettings.getMinimumFontSize());
+ webSettings.setLoadsImagesAutomatically(appSettings.isLoadImages());
+ webSettings.setAppCacheEnabled(true);
+
+ if (android.os.Build.VERSION.SDK_INT >= 21) {
+ WebView.enableSlowWholeDocumentDraw();
+ webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+ }
+
+ this.registerForContextMenu(webView);
+ //webView.setParentActivity(this);
+ webView.setOverScrollMode(WebView.OVER_SCROLL_ALWAYS);
+
+ this.webViewClient = new CustomWebViewClient((App) getActivity().getApplication(), webView);
+ webView.setWebViewClient(webViewClient);
+ webView.setWebChromeClient(new ProgressBarWebChromeClient(webView, progressBar));
+ }
+
+ /**
+ * Set proxy according to arguments. host must not be "" or null, port must be positive.
+ * Return true on success and update appSettings' proxy related values.
+ *
+ * @param host proxy host (eg. localhost or 127.0.0.1)
+ * @param port proxy port (eg. 8118)
+ * @return success
+ * @throws IllegalArgumentException if arguments do not fit specifications above
+ */
+ private boolean setProxy(final String host, final int port) {
+ AppLog.i(this, "StreamFragment.setProxy()");
+ if (host != null && !host.equals("") && port >= 0) {
+ AppLog.i(this, "Set proxy to "+host+":"+port);
+ //Temporary change thread policy
+ AppLog.v(this, "Set temporary ThreadPolicy");
+ StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
+ StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(tmp);
+
+ AppLog.v(this, "Apply NetCipher proxy settings");
+ NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections
+ try {
+ //Proxy for the webview
+ AppLog.v(this, "Apply Webkit proxy settings");
+ WebkitProxy.setProxy(MainActivity.class.getName(), getContext().getApplicationContext(), null, host, port);
+ } catch (Exception e) {
+ AppLog.e(this, "Could not apply WebKit proxy settings:\n"+e.toString());
+ }
+ AppLog.v(this, "Save changes in appSettings");
+ appSettings.setProxyEnabled(true);
+ appSettings.setProxyWasEnabled(true);
+
+ AppLog.v(this, "Reset old ThreadPolicy");
+ StrictMode.setThreadPolicy(old);
+ AppLog.i(this, "Success! Reload WebView");
+ webView.reload();
+ return true;
+ } else {
+ AppLog.e(this, "Invalid proxy configuration. Host: "+host+" Port: "+port+"\nRefuse to set proxy");
+ return false;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private boolean setProxy() {
+ return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort());
+ }
+
+ private void resetProxy() {
+ AppLog.i(this, "StreamFragment.resetProxy()");
+ AppLog.v(this, "write changes to appSettings");
+ appSettings.setProxyEnabled(false);
+ appSettings.setProxyWasEnabled(false);
+
+ //Temporary change thread policy
+ AppLog.v(this, "Set temporary ThreadPolicy");
+ StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
+ StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(tmp);
+
+ AppLog.v(this, "clear NetCipher proxy");
+ NetCipher.clearProxy();
+ try {
+ AppLog.v(this, "clear WebKit proxy");
+ WebkitProxy.resetProxy(MainActivity.class.getName(), getContext());
+ } catch (Exception e) {
+ AppLog.e(this, "Could not clear WebKit proxy:\n"+e.toString());
+ }
+ AppLog.v(this, "Reset old ThreadPolicy");
+ StrictMode.setThreadPolicy(old);
+
+ //Restart app
+ AppLog.i(this, "Success! Restart app due to proxy reset");
+ Intent restartActivity = new Intent(getContext(), MainActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+ AlarmManager mgr = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
+ mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
+ System.exit(0);
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ protected boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) {
+ AppLog.i(this, "StreamFragment.makeScreenshotOfWebView()");
+ if (android.os.Build.VERSION.SDK_INT >= 23) {
+ int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
+ if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ new AlertDialog.Builder(getContext())
+ .setMessage(R.string.permissions_screenshot)
+ .setNegativeButton(android.R.string.no, null)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (android.os.Build.VERSION.SDK_INT >= 23)
+ requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ MainActivity.REQUEST_CODE_ASK_PERMISSIONS);
+ }
+ })
+ .show();
+ return false;
+ }
+ requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ MainActivity.REQUEST_CODE_ASK_PERMISSIONS);
+ return false;
+ }
+ }
+
+ Date dateNow = new Date();
+ DateFormat dateFormat = new SimpleDateFormat("yy_MM_dd--HH_mm_ss", Locale.getDefault());
+ File fileSaveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/Diaspora");
+
+ String fileSaveName = hasToShareScreenshot ? ".DfA_share.jpg" : String.format("DfA_%s.jpg", dateFormat.format(dateNow));
+ if (!fileSaveDirectory.exists()) {
+ if(!fileSaveDirectory.mkdirs()) {
+ AppLog.w(this, "Could not mkdir "+fileSaveDirectory.getAbsolutePath());
+ }
+ }
+
+ if (!hasToShareScreenshot) {
+ Snackbar.make(webView, getString(R.string.share__toast_screenshot) + " " + fileSaveName, Snackbar.LENGTH_LONG).show();
+ }
+
+ Bitmap bitmap;
+ webView.setDrawingCacheEnabled(true);
+ bitmap = Bitmap.createBitmap(webView.getDrawingCache());
+ webView.setDrawingCacheEnabled(false);
+
+ OutputStream bitmapWriter = null;
+ try {
+ bitmapWriter = new FileOutputStream(new File(fileSaveDirectory, fileSaveName));
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bitmapWriter);
+ bitmapWriter.flush();
+ bitmap.recycle();
+ } catch (Exception e) {
+ return false;
+ } finally {
+ if (bitmapWriter != null) {
+ try {
+ bitmapWriter.close();
+ } catch (IOException _ignSaveored) {/* Nothing */}
+ }
+ }
+
+ // Only show share intent when Action Share Screenshot was selected
+ if (hasToShareScreenshot) {
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("image/jpeg");
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
+ sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
+ Uri bmpUri = Uri.fromFile(new File(fileSaveDirectory, fileSaveName));
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
+ startActivity(Intent.createChooser(sharingIntent, getString(R.string.action_share_dotdotdot)));
+ } else {
+ // Broadcast that this file is indexable
+ File file = new File(fileSaveDirectory, fileSaveName);
+ Uri uri = Uri.fromFile(file);
+ Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
+ getActivity().sendBroadcast(intent);
+ }
+ return true;
+ }
+
+ @Override
+ public String getFragmentTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
+ /* Nothing to do here */
+ }
+
+ public boolean onBackPressed() {
+ if(webView.canGoBack()) {
+ webView.goBack();
+ return true;
+ }
+ return false;
+ }
+
+ public void loadUrl(String url) {
+ if(getWebView() != null) {
+ AppLog.v(this, "loadUrl(): load "+url);
+ getWebView().loadUrlNew(url);
+ } else {
+ AppLog.v(this, "loadUrl(): WebView null: Set pending url to "+url);
+ pendingUrl = url;
+ }
+ }
+
+ public String getUrl() {
+ if(getWebView() != null) {
+ return getWebView().getUrl();
+ } else {
+ return pendingUrl;
+ }
+ }
+
+ public void reloadUrl() {
+ AppLog.v(this, "reloadUrl()");
+ if(getWebView() != null) {
+ getWebView().reload();
+ }
+ }
+
+ public ContextMenuWebView getWebView() {
+ return this.webView;
+ }
+}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java
new file mode 100644
index 00000000..3673d739
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java
@@ -0,0 +1,65 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.fragment;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.Menu;
+import android.view.MenuInflater;
+
+/**
+ * Customized abstract Fragment class with some useful methods
+ * Created by vanitas on 21.09.16.
+ */
+
+public abstract class CustomFragment extends Fragment {
+
+ public static final String TAG = "com.github.dfa.diaspora_android.CustomFragment";
+
+ /**
+ * We have an optionsMenu
+ * @param savedInstanceState state
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ /**
+ * Return the tag used to identify the Fragment.
+ * @return tag
+ */
+ public abstract String getFragmentTag();
+
+ /**
+ * Add fragment-dependent options to the bottom options toolbar
+ * @param menu bottom menu
+ * @param inflater inflater
+ */
+ public abstract void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater);
+
+ /**
+ * Return true if the fragment reacted to a back button press, false else.
+ * In case the fragment returned false, the parent activity should handle the backPress.
+ * @return did we react to the back press?
+ */
+ public abstract boolean onBackPressed();
+}
+
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java
new file mode 100644
index 00000000..d10b4e6d
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java
@@ -0,0 +1,345 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.fragment;
+
+import android.Manifest;
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AlertDialog;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.webkit.JavascriptInterface;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+
+import com.github.dfa.diaspora_android.App;
+import com.github.dfa.diaspora_android.R;
+import com.github.dfa.diaspora_android.activity.MainActivity;
+import com.github.dfa.diaspora_android.data.PodUserProfile;
+import com.github.dfa.diaspora_android.webview.DiasporaStreamWebChromeClient;
+import com.github.dfa.diaspora_android.webview.FileUploadWebChromeClient;
+import com.github.dfa.diaspora_android.util.AppLog;
+import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
+import com.github.dfa.diaspora_android.util.Helpers;
+import com.github.dfa.diaspora_android.util.WebHelper;
+
+import org.json.JSONException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Fragment that displays the Stream of the diaspora* user
+ * Created by vanitas on 26.09.16.
+ */
+
+public class DiasporaStreamFragment extends BrowserFragment {
+ public static final String TAG = "com.github.dfa.diaspora_android.StreamFragment";
+
+ protected DiasporaUrlHelper urls;
+
+ private ValueCallback imageUploadFilePathCallbackNew;
+ private ValueCallback imageUploadFilePathCallbackOld;
+ private String mCameraPhotoPath;
+
+ @SuppressLint("SetJavaScriptEnabled")
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ this.urls = new DiasporaUrlHelper(appSettings);
+ webView.setWebChromeClient(new DiasporaStreamWebChromeClient(webView, progressBar, fileUploadCallback, sharedTextCallback));
+
+ webView.getSettings().setJavaScriptEnabled(true);
+ webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge");
+ if(((MainActivity)getActivity()).getTextToBeShared() != null) {
+ loadUrl(urls.getNewPostUrl());
+ } else if(webView.getUrl() == null) {
+ loadUrl(urls.getStreamUrl());
+ }
+ }
+
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.stream__menu_top, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.stream__menu_bottom, menu);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ AppLog.d(this, "onActivityResult(): "+requestCode);
+ switch (requestCode) {
+ case MainActivity.INPUT_FILE_REQUEST_CODE_NEW:
+ case MainActivity.INPUT_FILE_REQUEST_CODE_OLD:
+ AppLog.v(this, "INPUT_FILE_REQUEST_CODE: "+requestCode);
+ onImageUploadResult(requestCode, resultCode, data);
+ return;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ AppLog.d(this, "StreamFragment.onOptionsItemSelected()");
+ switch (item.getItemId()) {
+ case R.id.action_reload: {
+ if(WebHelper.isOnline(getContext())) {
+ reloadUrl();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ case R.id.action_toggle_desktop_page: {
+ loadUrl(urls.getToggleMobileUrl());
+ return true;
+ }
+
+ case R.id.action_go_to_top: {
+ ObjectAnimator anim = ObjectAnimator.ofInt(webView, "scrollY", webView.getScrollY(), 0);
+ anim.setDuration(400);
+ anim.start();
+ return true;
+ }
+
+ case R.id.action_share_link: {
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("text/plain");
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
+ sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
+ startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot)));
+ return true;
+ }
+
+ case R.id.action_take_screenshot: {
+ makeScreenshotOfWebView(false);
+ return true;
+ }
+
+ case R.id.action_share_screenshot: {
+ makeScreenshotOfWebView(true);
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ public void onImageUploadResult(int requestCode, int resultCode, Intent data) {
+ AppLog.d(this, "onImageUploadResult");
+ switch (requestCode) {
+ case MainActivity.INPUT_FILE_REQUEST_CODE_NEW: {
+ AppLog.v(this, "Upload image using recent method (Lollipop+)");
+ if (imageUploadFilePathCallbackNew == null || resultCode != Activity.RESULT_OK) {
+ AppLog.e(this, "Callback is null: " + (imageUploadFilePathCallbackNew == null)
+ + " resultCode: " + resultCode);
+ if (imageUploadFilePathCallbackNew != null)
+ imageUploadFilePathCallbackNew.onReceiveValue(new Uri[]{});
+ return;
+ }
+ Uri[] results = null;
+ if (data == null) {
+ if (mCameraPhotoPath != null) {
+ AppLog.v(this, "Intent data is null. Try to parse cameraPhotoPath");
+ results = new Uri[]{Uri.parse(mCameraPhotoPath)};
+ } else {
+ AppLog.w(this, "Intent data is null and cameraPhotoPath is null");
+ }
+ } else {
+ String dataString = data.getDataString();
+ if (dataString != null) {
+ AppLog.v(this, "Intent has data. Try to parse dataString");
+ results = new Uri[]{Uri.parse(dataString)};
+ } else {
+ AppLog.w(this, "dataString is null");
+ }
+ }
+ AppLog.v(this, "handle received result over to callback");
+ imageUploadFilePathCallbackNew.onReceiveValue(results);
+ imageUploadFilePathCallbackNew = null;
+ return;
+ }
+ case MainActivity.INPUT_FILE_REQUEST_CODE_OLD: {
+ AppLog.v(this, "Upload image using legacy method (Jelly Bean, Kitkat)");
+ if (imageUploadFilePathCallbackOld == null || resultCode != Activity.RESULT_OK) {
+ AppLog.e(this, "Callback is null: " + (imageUploadFilePathCallbackOld == null)
+ + " resultCode: " + resultCode);
+ if (imageUploadFilePathCallbackOld != null)
+ imageUploadFilePathCallbackOld.onReceiveValue(null);
+ return;
+ }
+ Uri results = null;
+ if (data == null) {
+ if (mCameraPhotoPath != null) {
+ AppLog.v(this, "Intent has no data. Try to parse cameraPhotoPath");
+ results = Uri.parse(mCameraPhotoPath);
+ } else {
+ AppLog.w(this, "Intent has no data and cameraPhotoPath is null");
+ }
+ } else {
+ String dataString = data.getDataString();
+ if (dataString != null) {
+ AppLog.v(this, "Intent has data. Try to parse dataString");
+ results = Uri.parse(dataString);
+ } else {
+ AppLog.w(this, "dataString is null");
+ }
+ }
+ AppLog.v(this, "handle received result over to callback");
+ imageUploadFilePathCallbackOld.onReceiveValue(results);
+ imageUploadFilePathCallbackOld = null;
+ }
+ }
+ }
+
+ protected DiasporaStreamWebChromeClient.SharedTextCallback sharedTextCallback = new DiasporaStreamWebChromeClient.SharedTextCallback() {
+ @Override
+ public String getSharedText() {
+ return ((MainActivity)getActivity()).getTextToBeShared();
+ }
+ @Override
+ public void setSharedText(String shared) {
+ ((MainActivity)getActivity()).setTextToBeShared(shared);
+ }
+ };
+
+ protected FileUploadWebChromeClient.FileUploadCallback fileUploadCallback = new FileUploadWebChromeClient.FileUploadCallback() {
+ @Override
+ public boolean imageUpload(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
+ if(Build.VERSION.SDK_INT >= 23) {
+ int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
+ if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ new AlertDialog.Builder(getContext())
+ .setMessage(R.string.permissions_image)
+ .setNegativeButton(android.R.string.no, null)
+ .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (android.os.Build.VERSION.SDK_INT >= 23)
+ requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ MainActivity.REQUEST_CODE_ASK_PERMISSIONS);
+ }
+ })
+ .show();
+ return false;
+ }
+ requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ MainActivity.REQUEST_CODE_ASK_PERMISSIONS);
+ return false;
+ }
+ }
+ AppLog.v(this, "onOpenFileChooser");
+ if (imageUploadFilePathCallbackNew != null) imageUploadFilePathCallbackNew.onReceiveValue(null);
+ imageUploadFilePathCallbackNew = filePathCallback;
+ Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ if (takePictureIntent.resolveActivity(getContext().getPackageManager()) != null) {
+ // Create the File where the photo should go
+ File photoFile;
+ try {
+ photoFile = Helpers.createImageFile();
+ takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
+ } catch (IOException ex) {
+ AppLog.e(this, "ERROR creating temp file: "+ ex.toString());
+ // Error occurred while creating the File
+ Snackbar.make(webView, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show();
+ return false;
+ }
+ // Continue only if the File was successfully created
+ if (photoFile != null) {
+ mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
+ takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
+ Uri.fromFile(photoFile));
+ } else {
+ takePictureIntent = null;
+ }
+ }
+ Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
+ contentSelectionIntent.setType("image/*");
+ Intent[] intentArray;
+ if (takePictureIntent != null) {
+ intentArray = new Intent[]{takePictureIntent};
+ } else {
+ intentArray = new Intent[0];
+ }
+ Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
+ chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
+ chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
+ chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
+ AppLog.d(this, "startActivityForResult");
+ startActivityForResult(chooserIntent, MainActivity.INPUT_FILE_REQUEST_CODE_NEW);
+ return true;
+ }
+
+ @Override
+ public void legacyImageUpload(ValueCallback uploadMsg, String acceptType, String capture) {
+ AppLog.v(this, "openFileChooser(ValCallback, String, String");
+ imageUploadFilePathCallbackOld = uploadMsg;
+ Intent intent = new Intent();
+ intent.setType("image/*");
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ intent.putExtra("return-data", true);
+ intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ AppLog.v(this, "startActivityForResult");
+ startActivityForResult(Intent.createChooser(intent, "Select Picture"), MainActivity.INPUT_FILE_REQUEST_CODE_OLD);
+ }
+ };
+
+ private class JavaScriptInterface {
+ @SuppressWarnings("unused")
+ @JavascriptInterface
+ public void setUserProfile(final String webMessage) throws JSONException {
+ PodUserProfile pup = ((App)getActivity().getApplication()).getPodUserProfile();
+ AppLog.v(this, "StreamFragment.JavaScriptInterface.setUserProfile()");
+ if (pup.isRefreshNeeded()) {
+ AppLog.v(this, "PodUserProfile needs refresh; Try to parse JSON");
+ pup.parseJson(webMessage);
+ } else {
+ AppLog.v(this, "No PodUserProfile refresh needed");
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @JavascriptInterface
+ public void contentHasBeenShared() {
+ ((MainActivity)getActivity()).setTextToBeShared(null);
+ }
+ }
+
+ @Override
+ public String getFragmentTag() {
+ return TAG;
+ }
+}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java
new file mode 100644
index 00000000..104d6951
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java
@@ -0,0 +1,146 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.fragment;
+
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.github.dfa.diaspora_android.App;
+import com.github.dfa.diaspora_android.R;
+import com.github.dfa.diaspora_android.activity.MainActivity;
+import com.github.dfa.diaspora_android.util.AppLog;
+import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
+
+/**
+ * Fragment that shows a list of the Hashtags the user follows
+ * Created by vanitas on 29.09.16.
+ */
+
+public class HashtagListFragment extends CustomFragment {
+
+ public static final String TAG = "com.github.dfa.diaspora_android.HashtagListFragment";
+
+ protected RecyclerView followedTagsRecyclerView;
+ protected String[] followedTags;
+ protected App app;
+ protected DiasporaUrlHelper urls;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ AppLog.d(this, "onCreateView()");
+ return inflater.inflate(R.layout.hashtag_list__fragment, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ this.followedTagsRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_followed_tags__recycler_view);
+ this.app = (App) getActivity().getApplication();
+ this.urls = new DiasporaUrlHelper(app.getSettings());
+
+ followedTags = app.getPodUserProfile().getFollowedTags();
+ followedTagsRecyclerView.setHasFixedSize(true);
+ followedTagsRecyclerView.setNestedScrollingEnabled(false);
+
+ RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this.getContext());
+ followedTagsRecyclerView.setLayoutManager(layoutManager);
+
+ final FollowedTagsAdapter adapter = new FollowedTagsAdapter(followedTags, onHashtagClickListener);
+ followedTagsRecyclerView.setAdapter(adapter);
+
+ //Set window title
+ getActivity().setTitle(R.string.nav_followed_tags);
+ }
+
+ @Override
+ public String getFragmentTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
+ /* Nothing to do */
+ }
+
+ @Override
+ public boolean onBackPressed() {
+ return false;
+ }
+
+ protected View.OnClickListener onHashtagClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int itemPosition = followedTagsRecyclerView.getChildLayoutPosition(view);
+ if(itemPosition > -1 && itemPosition < followedTags.length) {
+ String tag = followedTags[itemPosition];
+ ((MainActivity)getActivity()).openDiasporaUrl(urls.getSearchTagsUrl(tag));
+ }
+ }
+ };
+
+ public static class FollowedTagsAdapter extends RecyclerView.Adapter {
+ private String[] followedTagsList;
+ private View.OnClickListener itemClickListener;
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ // each data item is just a string in this case
+ public TextView title;
+
+ public ViewHolder(View v) {
+ super(v);
+ title = (TextView) v.findViewById(R.id.recycler_view__list_item__text);
+ }
+ }
+
+ // Provide a suitable constructor (depends on the kind of dataset)
+ public FollowedTagsAdapter(String[] tags, View.OnClickListener itemClickListener) {
+ this.followedTagsList = tags;
+ this.itemClickListener = itemClickListener;
+ }
+
+ @Override
+ public FollowedTagsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.recycler_view__list_item, parent, false);
+ v.setOnClickListener(itemClickListener);
+ return new ViewHolder(v);
+ }
+
+ // Replace the contents of a view (invoked by the layout manager)
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+
+ holder.title.setText(followedTagsList[position]);
+
+ }
+
+ // Return the size of your dataset (invoked by the layout manager)
+ @Override
+ public int getItemCount() {
+ return followedTagsList.length;
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java
similarity index 61%
rename from app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java
rename to app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java
index 9729b8e4..9a2ad317 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java
@@ -16,7 +16,7 @@
If not, see .
*/
-package com.github.dfa.diaspora_android.activity;
+package com.github.dfa.diaspora_android.fragment;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
@@ -28,64 +28,103 @@ import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.content.LocalBroadcastManager;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.SpannableString;
import android.text.TextWatcher;
import android.text.util.Linkify;
+import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.webkit.CookieManager;
+import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.ListView;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
+import com.github.dfa.diaspora_android.activity.MainActivity;
+import com.github.dfa.diaspora_android.data.AppSettings;
import com.github.dfa.diaspora_android.task.GetPodsService;
-import com.github.dfa.diaspora_android.util.Helpers;
+import com.github.dfa.diaspora_android.util.AppLog;
+import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.WebHelper;
import java.util.ArrayList;
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import butterknife.OnItemClick;
+/**
+ * Fragment that lets the user choose a Pod
+ * Created by vanitas on 01.10.16.
+ */
+public class PodSelectionFragment extends CustomFragment {
+ public static final String TAG = "com.github.dfa.diaspora_android.PodSelectionFragment";
-public class PodSelectionActivity extends AppCompatActivity {
- private App app;
+ protected EditText editFilter;
+ protected ListView listPods;
+ protected ImageView selectPodButton;
- @BindView(R.id.podselection__edit_filter)
- EditText editFilter;
-
- @BindView(R.id.podselection__listpods)
- ListView listPods;
-
- @BindView(R.id.toolbar)
- Toolbar toolbar;
+ protected App app;
+ protected AppSettings appSettings;
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.podselection__activity);
- ButterKnife.bind(this);
- app = (App) getApplication();
- setSupportActionBar(toolbar);
-
-
- listPods.setTextFilterEnabled(true);
- setListedPods(app.getSettings().getPreviousPodlist());
- LocalBroadcastManager.getInstance(this).registerReceiver(podListReceiver, new IntentFilter(GetPodsService.MESSAGE_PODS_RECEIVED));
-
- if (!WebHelper.isOnline(PodSelectionActivity.this)) {
- Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
- }
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ AppLog.d(this, "onCreateView()");
+ return inflater.inflate(R.layout.podselection__fragment, container, false);
}
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ this.app = (App) getActivity().getApplication();
+ this.appSettings = app.getSettings();
+
+ this.editFilter = (EditText) view.findViewById(R.id.podselection__edit_filter);
+ this.listPods = (ListView) view.findViewById(R.id.podselection__listpods);
+ this.selectPodButton = (ImageView) view.findViewById(R.id.podselection__button_select_pod);
+
+ listPods.setTextFilterEnabled(true);
+ listPods.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
+ showPodConfirmationDialog((String) listPods.getAdapter().getItem(i));
+ }
+ });
+ setListedPods(appSettings.getPreviousPodlist());
+ LocalBroadcastManager.getInstance(getContext()).registerReceiver(podListReceiver, new IntentFilter(GetPodsService.MESSAGE_PODS_RECEIVED));
+ if (!WebHelper.isOnline(getContext())) {
+ Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
+ }
+ selectPodButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) {
+ showPodConfirmationDialog(editFilter.getText().toString());
+ } else {
+ Snackbar.make(listPods, R.string.valid_pod, Snackbar.LENGTH_LONG).show();
+ }
+ }
+ });
+ }
+
+ @Override
+ public String getFragmentTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
+ /* Nothing to do */
+ }
+
+ @Override
+ public boolean onBackPressed() {
+ return false;
+ }
private final BroadcastReceiver podListReceiver = new BroadcastReceiver() {
@Override
@@ -104,20 +143,11 @@ public class PodSelectionActivity extends AppCompatActivity {
}
};
- @OnClick(R.id.podselection__button_select_pod)
- public void onButtonSelectPodClicked(View view) {
- if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) {
- showPodConfirmationDialog(editFilter.getText().toString());
- } else {
- Snackbar.make(listPods, R.string.valid_pod, Snackbar.LENGTH_LONG).show();
- }
- }
-
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
- Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class);
- startService(i);
+ Intent i = new Intent(getContext(), GetPodsService.class);
+ getContext().startService(i);
}
@@ -128,7 +158,7 @@ public class PodSelectionActivity extends AppCompatActivity {
}
final ArrayAdapter adapter = new ArrayAdapter<>(
- PodSelectionActivity.this,
+ getContext(),
android.R.layout.simple_list_item_1,
listedPodsList);
@@ -154,24 +184,19 @@ public class PodSelectionActivity extends AppCompatActivity {
});
}
- @OnItemClick(R.id.podselection__listpods)
- public void onListPodsItemClicked(int position) {
- showPodConfirmationDialog((String) listPods.getAdapter().getItem(position));
- }
-
private void showPodConfirmationDialog(final String selectedPod) {
// Make a clickable link
final SpannableString dialogMessage = new SpannableString(getString(R.string.confirm_pod, selectedPod));
Linkify.addLinks(dialogMessage, Linkify.ALL);
// Check if online
- if (!WebHelper.isOnline(PodSelectionActivity.this)) {
+ if (!WebHelper.isOnline(getContext())) {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
return;
}
// Show dialog
- new AlertDialog.Builder(PodSelectionActivity.this)
+ new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.confirmation))
.setMessage(dialogMessage)
.setPositiveButton(android.R.string.yes,
@@ -201,40 +226,28 @@ public class PodSelectionActivity extends AppCompatActivity {
e.printStackTrace();
}
- Helpers.animateToActivity(this, MainActivity.class, true);
- }
-
-
- @Override
- public void onBackPressed() {
- Snackbar.make(listPods, R.string.confirm_exit, Snackbar.LENGTH_LONG)
- .setAction(android.R.string.yes, new View.OnClickListener() {
- public void onClick(View view) {
- finish();
- }
- })
- .show();
+ ((MainActivity)getActivity()).openDiasporaUrl(new DiasporaUrlHelper(appSettings).getPodUrl());
}
@Override
- protected void onDestroy() {
- LocalBroadcastManager.getInstance(this).unregisterReceiver(podListReceiver);
+ public void onDestroy() {
+ LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(podListReceiver);
super.onDestroy();
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.podselection__menu, menu);
- return true;
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.podselection__menu, menu);
+ super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_reload: {
- if (WebHelper.isOnline(PodSelectionActivity.this)) {
- Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class);
- startService(i);
+ if (WebHelper.isOnline(getContext())) {
+ Intent i = new Intent(getContext(), GetPodsService.class);
+ getContext().startService(i);
return true;
} else {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/receivers/OpenExternalLinkReceiver.java b/app/src/main/java/com/github/dfa/diaspora_android/receiver/OpenExternalLinkReceiver.java
similarity index 75%
rename from app/src/main/java/com/github/dfa/diaspora_android/receivers/OpenExternalLinkReceiver.java
rename to app/src/main/java/com/github/dfa/diaspora_android/receiver/OpenExternalLinkReceiver.java
index 0ef48e4f..e52b24ea 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/receivers/OpenExternalLinkReceiver.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/receiver/OpenExternalLinkReceiver.java
@@ -1,4 +1,22 @@
-package com.github.dfa.diaspora_android.receivers;
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.receiver;
import android.app.Activity;
import android.content.BroadcastReceiver;
@@ -9,7 +27,6 @@ import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.customtabs.CustomTabsIntent;
-import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.data.AppSettings;
@@ -17,7 +34,6 @@ import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.BrowserFallback;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper;
import com.github.dfa.diaspora_android.util.Helpers;
-import com.github.dfa.diaspora_android.util.Log;
/**
* BroadcastReceiver that opens links in a Chrome CustomTab
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java b/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java
similarity index 80%
rename from app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java
rename to app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java
index 10ddc5f5..ca8eda16 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java
@@ -1,4 +1,22 @@
-package com.github.dfa.diaspora_android.receivers;
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java
index 03460aa9..fab514ab 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java
@@ -1,3 +1,21 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
package com.github.dfa.diaspora_android.ui;
import android.content.Context;
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java
index adac6fd2..3be4ce63 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java
@@ -123,22 +123,49 @@ public class ContextMenuWebView extends NestedWebView {
case ID_SHARE_IMAGE:
if (url != null) {
- final Uri local = Uri.parse(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png");
- new ImageDownloadTask(null, local.getPath()) {
- @Override
- protected void onPostExecute(Bitmap result) {
- Uri myUri = Uri.fromFile(new File(local.getPath()));
- Intent sharingIntent = new Intent();
- sharingIntent.setAction(Intent.ACTION_SEND);
- sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri);
- sharingIntent.setType("image/png");
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- context.startActivity(Intent.createChooser(sharingIntent, "Share image using"));
+ boolean writeToStoragePermitted = true;
+ if (android.os.Build.VERSION.SDK_INT >= 23) {
+ int hasWRITE_EXTERNAL_STORAGE = parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
+ writeToStoragePermitted = false;
+ if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ new AlertDialog.Builder(parentActivity)
+ .setMessage(R.string.permissions_image)
+ .setPositiveButton(context.getText(android.R.string.yes), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (android.os.Build.VERSION.SDK_INT >= 23)
+ parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE);
+ }
+ })
+ .setNegativeButton(context.getText(android.R.string.no), null)
+ .show();
+ } else {
+ parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE);
+ }
}
- }.execute(url);
+ }
+ if (writeToStoragePermitted) {
+ final Uri local = Uri.parse(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png");
+ new ImageDownloadTask(null, local.getPath()) {
+ @Override
+ protected void onPostExecute(Bitmap result) {
+ Uri myUri = Uri.fromFile(new File(local.getPath()));
+ Intent sharingIntent = new Intent();
+ sharingIntent.setAction(Intent.ACTION_SEND);
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri);
+ sharingIntent.setType("image/png");
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ context.startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot)));
+ }
+ }.execute(url);
+ }
} else {
Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show();
}
+
break;
case ID_IMAGE_EXTERNAL_BROWSER:
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/AppLog.java b/app/src/main/java/com/github/dfa/diaspora_android/util/AppLog.java
index 171bbd6c..178cd008 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/util/AppLog.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/util/AppLog.java
@@ -1,3 +1,21 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
package com.github.dfa.diaspora_android.util;
/**
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/BrowserFallback.java b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/BrowserFallback.java
index a4bdd930..4e70f1c0 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/BrowserFallback.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/BrowserFallback.java
@@ -1,3 +1,21 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.app.Activity;
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java
index e43ce0b0..b515adcc 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java
@@ -1,3 +1,21 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.app.Activity;
@@ -118,6 +136,10 @@ public class CustomTabActivityHelper {
return session.mayLaunchUrl(uri, extras, otherLikelyBundles);
}
+ public boolean warmup(int flags) {
+ return mClient.warmup(flags);
+ }
+
/**
* A Callback for when the service is connected or disconnected. Use those callbacks to
* handle UI changes when the service is connected or disconnected
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabsHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabsHelper.java
index 6ab577af..c1b9c546 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabsHelper.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabsHelper.java
@@ -1,3 +1,21 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.content.Context;
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/Log.java b/app/src/main/java/com/github/dfa/diaspora_android/util/Log.java
index ad0791e7..f8743b1d 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/util/Log.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/util/Log.java
@@ -1,3 +1,21 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
package com.github.dfa.diaspora_android.util;
import com.github.dfa.diaspora_android.data.AppSettings;
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java
index 691481be..ba760d7b 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java
@@ -62,7 +62,7 @@ public class WebHelper {
public static void optimizeMobileSiteLayout(final WebView wv) {
wv.loadUrl("javascript: ( function() {" +
" if (document.documentElement == null || document.documentElement.style == null) { return; }" +
- " document.documentElement.style.paddingBottom = '260px';" +
+ " document.documentElement.style.paddingBottom = '50px';" +
" document.getElementById('main').style.paddingTop = '5px';" +
" if(document.getElementById('main_nav')) {" +
" document.getElementById('main_nav').parentNode.removeChild(" +
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/CustomWebViewClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/CustomWebViewClient.java
similarity index 95%
rename from app/src/main/java/com/github/dfa/diaspora_android/ui/CustomWebViewClient.java
rename to app/src/main/java/com/github/dfa/diaspora_android/webview/CustomWebViewClient.java
index 8e31a15c..914abcbb 100644
--- a/app/src/main/java/com/github/dfa/diaspora_android/ui/CustomWebViewClient.java
+++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/CustomWebViewClient.java
@@ -16,7 +16,7 @@
If not, see .
*/
-package com.github.dfa.diaspora_android.ui;
+package com.github.dfa.diaspora_android.webview;
import android.content.Intent;
import android.net.Uri;
@@ -37,6 +37,7 @@ public class CustomWebViewClient extends WebViewClient {
this.webView = webView;
}
+ //Open non-diaspora links in customtab/external browser
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!url.contains(app.getSettings().getPodDomain())) {
Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL);
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/webview/DiasporaStreamWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/DiasporaStreamWebChromeClient.java
new file mode 100644
index 00000000..f3572e97
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/DiasporaStreamWebChromeClient.java
@@ -0,0 +1,62 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.webview;
+
+import android.webkit.WebView;
+import android.widget.ProgressBar;
+
+import com.github.dfa.diaspora_android.util.AppLog;
+import com.github.dfa.diaspora_android.util.WebHelper;
+
+/**
+ * Created by vanitas on 26.09.16.
+ */
+
+public class DiasporaStreamWebChromeClient extends FileUploadWebChromeClient {
+ protected SharedTextCallback sharedTextCallback;
+
+ public DiasporaStreamWebChromeClient(WebView webView, ProgressBar progressBar, FileUploadCallback fileUploadCallback, SharedTextCallback callback) {
+ super(webView, progressBar, fileUploadCallback);
+ this.sharedTextCallback = callback;
+ }
+
+ @Override
+ public void onProgressChanged(WebView wv, int progress) {
+ super.onProgressChanged(wv, progress);
+ if (progress > 0 && progress <= 60) {
+ WebHelper.getUserProfile(wv);
+ WebHelper.optimizeMobileSiteLayout(wv);
+ }
+
+ if (progress > 60) {
+ WebHelper.optimizeMobileSiteLayout(wv);
+
+ String textToBeShared = sharedTextCallback.getSharedText();
+ if (textToBeShared != null) {
+ AppLog.d(this, "Share text into webView");
+ WebHelper.shareTextIntoWebView(wv, textToBeShared);
+ }
+ }
+ }
+
+ public interface SharedTextCallback {
+ String getSharedText();
+ void setSharedText(String shared);
+ }
+}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/webview/FileUploadWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/FileUploadWebChromeClient.java
new file mode 100644
index 00000000..a730182e
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/FileUploadWebChromeClient.java
@@ -0,0 +1,59 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.webview;
+
+import android.net.Uri;
+import android.webkit.ValueCallback;
+import android.webkit.WebView;
+import android.widget.ProgressBar;
+
+/**
+ * Created by vanitas on 26.09.16.
+ */
+
+public class FileUploadWebChromeClient extends ProgressBarWebChromeClient {
+ protected FileUploadCallback fileUploadCallback;
+
+ public FileUploadWebChromeClient(WebView webView, ProgressBar progressBar, FileUploadCallback fileUploadCallback) {
+ super(webView, progressBar);
+ this.fileUploadCallback = fileUploadCallback;
+ }
+
+ @Override
+ public void onProgressChanged(WebView wv, int progress) {
+ super.onProgressChanged(wv, progress);
+ }
+
+ //For Android 4.1/4.2 only. DO NOT REMOVE!
+ @SuppressWarnings("unused")
+ protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture)
+ {
+ fileUploadCallback.legacyImageUpload(uploadMsg, acceptType, capture);
+ }
+
+ @Override
+ public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
+ return fileUploadCallback.imageUpload(webView, filePathCallback, fileChooserParams);
+ }
+
+ public interface FileUploadCallback {
+ boolean imageUpload(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams);
+ void legacyImageUpload(ValueCallback uploadMsg, String acceptType, String capture);
+ }
+}
diff --git a/app/src/main/java/com/github/dfa/diaspora_android/webview/ProgressBarWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/ProgressBarWebChromeClient.java
new file mode 100644
index 00000000..ec5c7b41
--- /dev/null
+++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/ProgressBarWebChromeClient.java
@@ -0,0 +1,44 @@
+/*
+ This file is part of the Diaspora for Android.
+
+ Diaspora for Android is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Diaspora for Android 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the Diaspora for Android.
+
+ If not, see .
+ */
+package com.github.dfa.diaspora_android.webview;
+
+import android.view.View;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.widget.ProgressBar;
+
+/**
+ * WebChromeClient that connects the ProgressBar and the WebView and updates the progress of the progressBar.
+ * Created by vanitas on 26.09.16.
+ */
+
+public class ProgressBarWebChromeClient extends WebChromeClient {
+ protected final ProgressBar progressBar;
+ protected final WebView webView;
+
+ public ProgressBarWebChromeClient(WebView webView, ProgressBar progressBar) {
+ this.webView = webView;
+ this.progressBar = progressBar;
+ }
+
+ public void onProgressChanged(WebView wv, int progress) {
+ progressBar.setProgress(progress);
+ progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE);
+ }
+}
diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..11f95124
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_launcher.png b/app/src/main/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 00000000..8e89a6a9
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_launcher.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..b356e40a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..5055f6cf
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..2001d858
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..0d77fa66
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/drawable/ic_launcher.xml b/app/src/main/res/drawable/ic_launcher.xml
deleted file mode 100644
index 4d66007f..00000000
--- a/app/src/main/res/drawable/ic_launcher.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/layout/about__activity.xml b/app/src/main/res/layout/about__activity.xml
index c686e81e..6a8c3568 100644
--- a/app/src/main/res/layout/about__activity.xml
+++ b/app/src/main/res/layout/about__activity.xml
@@ -17,7 +17,7 @@
+ android:id="@+id/main__topbar"/>
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/hashtag_list__fragment.xml b/app/src/main/res/layout/hashtag_list__fragment.xml
new file mode 100644
index 00000000..94df572b
--- /dev/null
+++ b/app/src/main/res/layout/hashtag_list__fragment.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/main__activity.xml b/app/src/main/res/layout/main__activity.xml
index a546cd6d..7de0204c 100644
--- a/app/src/main/res/layout/main__activity.xml
+++ b/app/src/main/res/layout/main__activity.xml
@@ -2,7 +2,7 @@
-
+
-
+
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/podselection__activity.xml b/app/src/main/res/layout/podselection__activity.xml
deleted file mode 100644
index 418a66b4..00000000
--- a/app/src/main/res/layout/podselection__activity.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/podselection__fragment.xml b/app/src/main/res/layout/podselection__fragment.xml
new file mode 100644
index 00000000..b8e39ac4
--- /dev/null
+++ b/app/src/main/res/layout/podselection__fragment.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/recycler_view__list_item.xml b/app/src/main/res/layout/recycler_view__list_item.xml
new file mode 100644
index 00000000..764467e7
--- /dev/null
+++ b/app/src/main/res/layout/recycler_view__list_item.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/splash__activity.xml b/app/src/main/res/layout/splash__activity.xml
deleted file mode 100644
index 5f65f563..00000000
--- a/app/src/main/res/layout/splash__activity.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/ui__webview.xml b/app/src/main/res/layout/ui__webview.xml
deleted file mode 100644
index 35d12bc4..00000000
--- a/app/src/main/res/layout/ui__webview.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/menu/main__menu_bottom.xml b/app/src/main/res/menu/main__menu_bottom.xml
index 002a2a29..0c973856 100644
--- a/app/src/main/res/menu/main__menu_bottom.xml
+++ b/app/src/main/res/menu/main__menu_bottom.xml
@@ -8,42 +8,31 @@
android:id="@+id/action_search"
android:icon="@drawable/ic_search_white_48px"
app:showAsAction="always"
+ android:orderInCategory="100"
android:title="@string/action_search_by_tags_or_persons" />
-
- -
-
-
-
+ app:showAsAction="always"
+ android:orderInCategory="400"
+ android:title="@string/action_go_to_top" />
-
+ />
diff --git a/app/src/main/res/menu/main__menu_top.xml b/app/src/main/res/menu/main__menu_top.xml
index d6c873b7..73ea3bc7 100644
--- a/app/src/main/res/menu/main__menu_top.xml
+++ b/app/src/main/res/menu/main__menu_top.xml
@@ -6,19 +6,16 @@
+ />
-
-
+ app:showAsAction="always"
+ android:orderInCategory="200"
+ android:title="@string/conversations" />
diff --git a/app/src/main/res/menu/main__navdrawer.xml b/app/src/main/res/menu/main__navdrawer.xml
index 25a2f7a9..56323eb8 100644
--- a/app/src/main/res/menu/main__navdrawer.xml
+++ b/app/src/main/res/menu/main__navdrawer.xml
@@ -61,7 +61,7 @@
android:title="@string/settings" />
diff --git a/app/src/main/res/menu/podselection__menu.xml b/app/src/main/res/menu/podselection__menu.xml
index 1c33e1c9..8b498aa3 100644
--- a/app/src/main/res/menu/podselection__menu.xml
+++ b/app/src/main/res/menu/podselection__menu.xml
@@ -1,7 +1,5 @@