1
0
Fork 0
mirror of https://github.com/gsantner/dandelion synced 2024-11-22 12:22:08 +01:00

Merged master

This commit is contained in:
vanitasvitae 2016-10-10 15:07:30 +02:00
commit c09618f191
Signed by: vanitasvitae
GPG key ID: DCCFB3302C9E4615
62 changed files with 1943 additions and 1101 deletions

View file

@ -24,10 +24,10 @@ I have:
#### Expected result #### 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: Upload screenshots via drag&drop if needed and apply resizing:
`<img width="30%" height="30%" src="https://cloud.githubusercontent.com/assets/67..b55.jpg">` `<img width="30%" height="30%" src="https://cloud.githubusercontent.com/assets/67..b55.jpg">`

View file

@ -6,7 +6,7 @@ android:
- tools - tools
- tools # TODO https://github.com/travis-ci/travis-ci/issues/6193 - tools # TODO https://github.com/travis-ci/travis-ci/issues/6193
- platform-tools - platform-tools
- build-tools-24.0.1 - build-tools-24.0.2
- android-24 - android-24
- extra-android-m2repository - extra-android-m2repository
before_cache: before_cache:

View file

@ -1,8 +1,9 @@
[![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android) [![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android)
[![Build Status](https://travis-ci.org/Diaspora-for-Android/diaspora-android.svg?branch=master)](https://travis-ci.org/Diaspora-for-Android/diaspora-android) <a name="badgers"></a>[![Build Status](https://travis-ci.org/Diaspora-for-Android/diaspora-android.svg?branch=master)](https://travis-ci.org/Diaspora-for-Android/diaspora-android)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/diaspora-for-android/localized.svg)](https://crowdin.com/project/diaspora-for-android) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/diaspora-for-android/localized.svg)](https://crowdin.com/project/diaspora-for-android)
[![Join the chat at https://gitter.im/Diaspora-for-Android/diaspora-android](https://badges.gitter.im/Diaspora-for-Android/diaspora-android.svg)](https://gitter.im/Diaspora-for-Android/diaspora-android?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Chat - FreeNode IRC](https://img.shields.io/badge/chat-on%20freenode-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/?nick=user-dfa|?#diaspora-for-android)
[![Chat - Gitter](https://img.shields.io/badge/chat-on%20gitter-blue.svg)](https://gitter.im/Diaspora-for-Android/diaspora-android)
# Diaspora for Android # Diaspora for Android
@ -15,28 +16,28 @@ This is an unofficial webview based client for the community-run, distributed so
## Contributions ## Contributions
We are always open for any kind of contribution. (PR's, bug reports, feature requests, translations, ..) 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). 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.
Note that the main project members are mostly busy with their job/university/school and may not react or start coding immediately.
We use Crowdin to translate Diaspora for Android. Join our project here: <https://crowdin.com/project/diaspora-for-android/invite> We use Crowdin to translate Diaspora for Android. Join our project here: <https://crowdin.com/project/diaspora-for-android/invite>. If your desired language is not listed please contact the maintainers/owner.
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 ### 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 ### 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. [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 :) 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 ### 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 ### 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 ## Maintainers
- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io)) - gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c))
- vanitasvitae ([GitHub](https://github.com/vanitasvitae)) - vanitasvitae ([GitHub](https://github.com/vanitasvitae), [Diaspora](https://pod.geraspora.de/people/bbd7af90fbec013213e34860008dbc6c))

View file

@ -1,14 +1,24 @@
<table> <table>
<tr> <tr>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698079/5025aa3a-63b9-11e6-9c25-dda3020dd36f.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/01.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698080/503f9904-63b9-11e6-9eb7-9ad1500889af.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/02.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698082/50443bee-63b9-11e6-9881-d8e871453650.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/03.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698083/50488514-63b9-11e6-8a44-e7d7e43ae728.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/04.png" height="60%" width="60%"></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698085/504b17ac-63b9-11e6-845f-273f9d0e50ff.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/05.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698084/504ab4b0-63b9-11e6-96a0-32bc27f4b0ab.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/06.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698081/503ff9a8-63b9-11e6-8c52-d14fdf973881.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/07.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/7854206/17698086/505cbd0e-63b9-11e6-8719-9398b81734a1.png" height="60%" width="60%"></td> <td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/08.png" height="60%" width="60%"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/09.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/10.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/11.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/12.png" height="60%" width="60%"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/13.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/14.png" height="60%" width="60%"></td>
</tr> </tr>
</table> </table>

View file

@ -3,14 +3,14 @@ apply plugin: 'android-apt'
android { android {
compileSdkVersion 24 compileSdkVersion 24
buildToolsVersion "24.0.1" buildToolsVersion "24.0.2"
defaultConfig { defaultConfig {
applicationId "com.github.dfa.diaspora_android" applicationId "com.github.dfa.diaspora_android"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 24 targetSdkVersion 24
versionCode 8 versionCode 8
versionName "0.1.6" versionName "0.1.6-next"
} }
buildTypes { buildTypes {
release { release {

View file

@ -12,52 +12,40 @@
android:name="com.github.dfa.diaspora_android.App" android:name="com.github.dfa.diaspora_android.App"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/AppTheme" > android:theme="@style/AppTheme" >
<provider <provider
android:name="com.github.dfa.diaspora_android.data.HashtagProvider" android:name="com.github.dfa.diaspora_android.data.HashtagProvider"
android:authorities="com.github.dfa.diaspora_android.mainactivity" /> android:authorities="com.github.dfa.diaspora_android.mainactivity" />
<activity
android:name="com.github.dfa.diaspora_android.activity.SplashActivity" <service
android:launchMode="singleInstance" android:name="com.github.dfa.diaspora_android.task.GetPodsService"
android:configChanges="keyboardHidden|orientation|screenSize" android:enabled="true"
android:label="@string/app_name" android:exported="false" />
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.PodSelectionActivity"
android:launchMode="singleInstance"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/title_activity_pods"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity <activity
android:name=".activity.SettingsActivity" android:name=".activity.SettingsActivity"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:label="@string/settings"> android:label="@string/settings" />
</activity>
<service <activity
android:name="com.github.dfa.diaspora_android.task.GetPodsService" android:name=".activity.AboutActivity"
android:enabled="true" android:label="@string/about_activity__title_about_app"
android:exported="false" > android:theme="@style/AppTheme.NoActionBar"/>
</service>
<activity <activity
android:name=".activity.MainActivity" android:name=".activity.MainActivity"
android:launchMode="singleTop" android:launchMode="singleTop"
android:windowSoftInputMode="adjustPan" android:windowSoftInputMode="adjustResize"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/AppTheme.NoActionBar" android:theme="@style/AppTheme.NoActionBar"
android:label="@string/diaspora"> android:label="@string/diaspora">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
@ -255,9 +243,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".activity.AboutActivity"
android:label="@string/about_activity__title_about_app"
android:theme="@style/AppTheme.NoActionBar"/>
</application> </application>
</manifest> </manifest>

View file

@ -62,10 +62,10 @@ public class AboutActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter; private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager; private ViewPager mViewPager;
@BindView(R.id.toolbar) @BindView(R.id.main__topbar)
protected Toolbar toolbar; protected Toolbar toolbar;
@BindView(R.id.linearlayout) @BindView(R.id.appbar_linear_layout)
protected LinearLayout linearLayout; protected LinearLayout linearLayout;
@Override @Override

View file

@ -94,8 +94,7 @@ public class SettingsActivity extends AppCompatActivity {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(key)); updatePreference(findPreference(key));
if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__clear_cache)) || if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__font_size)) ||
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__load_images)) ||
key.equals(getString(R.string.pref_key__intellihide_toolbars)) || key.equals(getString(R.string.pref_key__intellihide_toolbars)) ||
key.equals(getString(R.string.pref_key__http_proxy_enabled)) || key.equals(getString(R.string.pref_key__http_proxy_enabled)) ||
@ -162,11 +161,17 @@ public class SettingsActivity extends AppCompatActivity {
return true; return true;
} }
case R.string.pref_title__http_proxy_load_tor_preset: { 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_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_port))).setText("8118");
return true; return true;
} }
case R.string.pref_title__clear_cache:
{
intent.setAction(MainActivity.ACTION_CLEAR_CACHE);
break;
}
default: { default: {
intent = null; intent = null;
break; break;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
);
}
};
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Uri[]> imageUploadFilePathCallbackNew;
private ValueCallback<Uri> 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<Uri[]> 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<Uri> uploadMsg, String acceptType, String capture) {
AppLog.v(this, "openFileChooser(ValCallback<Uri>, 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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<FollowedTagsAdapter.ViewHolder> {
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;
}
}
}

View file

@ -16,7 +16,7 @@
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android.activity; package com.github.dfa.diaspora_android.fragment;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -28,64 +28,103 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.content.LocalBroadcastManager; 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.Editable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.util.Linkify; import android.text.util.Linkify;
import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R; 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.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 com.github.dfa.diaspora_android.util.WebHelper;
import java.util.ArrayList; import java.util.ArrayList;
import butterknife.BindView; /**
import butterknife.ButterKnife; * Fragment that lets the user choose a Pod
import butterknife.OnClick; * Created by vanitas on 01.10.16.
import butterknife.OnItemClick; */
public class PodSelectionFragment extends CustomFragment {
public static final String TAG = "com.github.dfa.diaspora_android.PodSelectionFragment";
public class PodSelectionActivity extends AppCompatActivity { protected EditText editFilter;
private App app; protected ListView listPods;
protected ImageView selectPodButton;
@BindView(R.id.podselection__edit_filter) protected App app;
EditText editFilter; protected AppSettings appSettings;
@BindView(R.id.podselection__listpods)
ListView listPods;
@BindView(R.id.toolbar)
Toolbar toolbar;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); AppLog.d(this, "onCreateView()");
setContentView(R.layout.podselection__activity); return inflater.inflate(R.layout.podselection__fragment, container, false);
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();
}
} }
@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() { private final BroadcastReceiver podListReceiver = new BroadcastReceiver() {
@Override @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 @Override
protected void onResume() { public void onResume() {
super.onResume(); super.onResume();
Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class); Intent i = new Intent(getContext(), GetPodsService.class);
startService(i); getContext().startService(i);
} }
@ -128,7 +158,7 @@ public class PodSelectionActivity extends AppCompatActivity {
} }
final ArrayAdapter<String> adapter = new ArrayAdapter<>( final ArrayAdapter<String> adapter = new ArrayAdapter<>(
PodSelectionActivity.this, getContext(),
android.R.layout.simple_list_item_1, android.R.layout.simple_list_item_1,
listedPodsList); 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) { private void showPodConfirmationDialog(final String selectedPod) {
// Make a clickable link // Make a clickable link
final SpannableString dialogMessage = new SpannableString(getString(R.string.confirm_pod, selectedPod)); final SpannableString dialogMessage = new SpannableString(getString(R.string.confirm_pod, selectedPod));
Linkify.addLinks(dialogMessage, Linkify.ALL); Linkify.addLinks(dialogMessage, Linkify.ALL);
// Check if online // Check if online
if (!WebHelper.isOnline(PodSelectionActivity.this)) { if (!WebHelper.isOnline(getContext())) {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
return; return;
} }
// Show dialog // Show dialog
new AlertDialog.Builder(PodSelectionActivity.this) new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.confirmation)) .setTitle(getString(R.string.confirmation))
.setMessage(dialogMessage) .setMessage(dialogMessage)
.setPositiveButton(android.R.string.yes, .setPositiveButton(android.R.string.yes,
@ -201,40 +226,28 @@ public class PodSelectionActivity extends AppCompatActivity {
e.printStackTrace(); e.printStackTrace();
} }
Helpers.animateToActivity(this, MainActivity.class, true); ((MainActivity)getActivity()).openDiasporaUrl(new DiasporaUrlHelper(appSettings).getPodUrl());
}
@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();
} }
@Override @Override
protected void onDestroy() { public void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(podListReceiver); LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(podListReceiver);
super.onDestroy(); super.onDestroy();
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
getMenuInflater().inflate(R.menu.podselection__menu, menu); inflater.inflate(R.menu.podselection__menu, menu);
return true; super.onCreateOptionsMenu(menu, inflater);
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_reload: { case R.id.action_reload: {
if (WebHelper.isOnline(PodSelectionActivity.this)) { if (WebHelper.isOnline(getContext())) {
Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class); Intent i = new Intent(getContext(), GetPodsService.class);
startService(i); getContext().startService(i);
return true; return true;
} else { } else {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.receiver;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -9,7 +27,6 @@ import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.support.customtabs.CustomTabsIntent; 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.R;
import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.data.AppSettings; 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.BrowserFallback;
import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper; import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper;
import com.github.dfa.diaspora_android.util.Helpers; import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.util.Log;
/** /**
* BroadcastReceiver that opens links in a Chrome CustomTab * BroadcastReceiver that opens links in a Chrome CustomTab

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.receiver;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui; package com.github.dfa.diaspora_android.ui;
import android.content.Context; import android.content.Context;

View file

@ -123,22 +123,49 @@ public class ContextMenuWebView extends NestedWebView {
case ID_SHARE_IMAGE: case ID_SHARE_IMAGE:
if (url != null) { if (url != null) {
final Uri local = Uri.parse(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png"); boolean writeToStoragePermitted = true;
new ImageDownloadTask(null, local.getPath()) { if (android.os.Build.VERSION.SDK_INT >= 23) {
@Override int hasWRITE_EXTERNAL_STORAGE = parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
protected void onPostExecute(Bitmap result) { if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
Uri myUri = Uri.fromFile(new File(local.getPath())); writeToStoragePermitted = false;
Intent sharingIntent = new Intent(); if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
sharingIntent.setAction(Intent.ACTION_SEND); new AlertDialog.Builder(parentActivity)
sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri); .setMessage(R.string.permissions_image)
sharingIntent.setType("image/png"); .setPositiveButton(context.getText(android.R.string.yes), new DialogInterface.OnClickListener() {
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); @Override
context.startActivity(Intent.createChooser(sharingIntent, "Share image using")); 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 { } else {
Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show(); Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show();
} }
break; break;
case ID_IMAGE_EXTERNAL_BROWSER: case ID_IMAGE_EXTERNAL_BROWSER:

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.util; package com.github.dfa.diaspora_android.util;
/** /**

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.util.CustomTabHelpers; package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.app.Activity; import android.app.Activity;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.util.CustomTabHelpers; package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.app.Activity; import android.app.Activity;
@ -118,6 +136,10 @@ public class CustomTabActivityHelper {
return session.mayLaunchUrl(uri, extras, otherLikelyBundles); 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 * A Callback for when the service is connected or disconnected. Use those callbacks to
* handle UI changes when the service is connected or disconnected * handle UI changes when the service is connected or disconnected

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.util.CustomTabHelpers; package com.github.dfa.diaspora_android.util.CustomTabHelpers;
import android.content.Context; import android.content.Context;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.util; package com.github.dfa.diaspora_android.util;
import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.data.AppSettings;

View file

@ -62,7 +62,7 @@ public class WebHelper {
public static void optimizeMobileSiteLayout(final WebView wv) { public static void optimizeMobileSiteLayout(final WebView wv) {
wv.loadUrl("javascript: ( function() {" + wv.loadUrl("javascript: ( function() {" +
" if (document.documentElement == null || document.documentElement.style == null) { return; }" + " 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';" + " document.getElementById('main').style.paddingTop = '5px';" +
" if(document.getElementById('main_nav')) {" + " if(document.getElementById('main_nav')) {" +
" document.getElementById('main_nav').parentNode.removeChild(" + " document.getElementById('main_nav').parentNode.removeChild(" +

View file

@ -16,7 +16,7 @@
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android.ui; package com.github.dfa.diaspora_android.webview;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@ -37,6 +37,7 @@ public class CustomWebViewClient extends WebViewClient {
this.webView = webView; this.webView = webView;
} }
//Open non-diaspora links in customtab/external browser
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!url.contains(app.getSettings().getPodDomain())) { if (!url.contains(app.getSettings().getPodDomain())) {
Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL); Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Uri> uploadMsg, String acceptType, String capture)
{
fileUploadCallback.legacyImageUpload(uploadMsg, acceptType, capture);
}
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
return fileUploadCallback.imageUpload(webView, filePathCallback, fileChooserParams);
}
public interface FileUploadCallback {
boolean imageUpload(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams);
void legacyImageUpload(ValueCallback<Uri> uploadMsg, String acceptType, String capture);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -1,6 +0,0 @@
<vector android:height="24dp" android:viewportHeight="20.0"
android:viewportWidth="20.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillAlpha="1" android:fillColor="#207be6"
android:pathData="M10,10m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0" android:strokeColor="#00000000"/>
<path android:fillColor="#fafafa" android:pathData="M11.337,14.123C11.06,13.736 10.626,13.13 10.374,12.778 10.117,12.418 9.908,12.138 9.897,12.138c-0.011,-0 -0.416,0.544 -0.958,1.287 -0.516,0.708 -0.942,1.288 -0.948,1.288 -0.015,0 -1.86,-1.3 -1.865,-1.313 -0.002,-0.007 0.415,-0.619 0.927,-1.361 0.512,-0.742 0.931,-1.36 0.931,-1.375 0,-0.023 -0.166,-0.081 -1.468,-0.515C5.71,9.879 5.042,9.656 5.032,9.652 5.019,9.647 5.095,9.389 5.359,8.558 5.549,7.959 5.708,7.465 5.713,7.459c0.005,-0.006 0.707,0.219 1.559,0.499 0.852,0.28 1.557,0.51 1.565,0.51 0.009,-0 0.019,-0.013 0.022,-0.029 0.003,-0.016 0.011,-0.742 0.016,-1.613 0.006,-0.871 0.015,-1.591 0.021,-1.6 0.008,-0.013 0.248,-0.016 1.127,-0.016 0.614,0 1.123,0.004 1.13,0.01 0.01,0.007 0.027,0.485 0.055,1.561 0.046,1.766 0.047,1.79 0.075,1.79 0.011,0 0.686,-0.226 1.501,-0.502 0.815,-0.276 1.485,-0.498 1.49,-0.492 0.016,0.019 0.685,2.194 0.676,2.202 -0.004,0.004 -0.684,0.237 -1.511,0.517 -1.137,0.385 -1.504,0.514 -1.507,0.531 -0.002,0.012 0.389,0.596 0.886,1.324 0.489,0.716 0.888,1.308 0.886,1.314 -0.005,0.015 -1.836,1.364 -1.852,1.364 -0.006,0 -0.239,-0.317 -0.516,-0.705z"/>
</vector>

View file

@ -17,7 +17,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/linearlayout" android:id="@+id/appbar_linear_layout"
android:orientation="vertical" android:orientation="vertical"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap" app:layout_scrollFlags="scroll|enterAlways|snap"
@ -26,7 +26,7 @@
<android.support.v7.widget.Toolbar <android.support.v7.widget.Toolbar
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/toolbar"/> android:id="@+id/main__topbar"/>
<android.support.design.widget.TabLayout <android.support.design.widget.TabLayout
android:id="@+id/tabs" android:id="@+id/tabs"

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.dfa.diaspora_android.ui.ContextMenuWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="7dp"
android:indeterminate="false"
android:progressDrawable="@drawable/progressbar"/>
</RelativeLayout>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/fragment_followed_tags__recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<!-- Offset -->
<android.support.v4.widget.Space
android:id="@+id/spacer"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_toolbar_height"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>

View file

@ -2,7 +2,7 @@
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main__layout" android:id="@+id/main__navdrawer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"

View file

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent" android:layout_width="match_parent"
tools:context=".activity.MainActivity"> android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<android.support.design.widget.AppBarLayout <android.support.design.widget.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -13,7 +14,7 @@
android:theme="@style/AppTheme.AppBarOverlay"> android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar <android.support.v7.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/main__topbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
@ -22,17 +23,21 @@
</android.support.design.widget.AppBarLayout> </android.support.design.widget.AppBarLayout>
<include layout="@layout/main__content"/> <FrameLayout
android:id="@+id/fragment_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.AppBarLayout <android.support.design.widget.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom|end"
android:theme="@style/AppTheme.AppBarOverlay" android:theme="@style/AppTheme.AppBarOverlay"
app:layout_behavior=".ui.BottomBarBehavior"> app:layout_behavior=".ui.BottomBarBehavior">
<android.support.v7.widget.ActionMenuView <android.support.v7.widget.ActionMenuView
android:id="@+id/toolbar2" android:id="@+id/main__bottombar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="45dp" android:layout_height="45dp"
android:background="@color/colorPrimary" android:background="@color/colorPrimary"

View file

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".activity.MainActivity"
tools:showIn="@layout/main__app_bar">
<FrameLayout
android:id="@+id/placeholder_webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"/>
<ProgressBar
android:id="@+id/progressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="7dp"
android:indeterminate="false"
android:progressDrawable="@drawable/progressbar"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</RelativeLayout>

View file

@ -1,88 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activity.PodSelectionActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/podselection__activity">
<ListView
android:id="@+id/podselection__listpods"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/podselection__podupti_notice"
android:layout_below="@+id/podselection__edit_filter"
android:choiceMode="singleChoice" />
<EditText
android:id="@+id/podselection__edit_filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/textView"
android:layout_toStartOf="@+id/podselection__button_select_pod"
android:hint="@string/filter_hint"
android:inputType="textUri|textWebEditText" />
<ImageView
android:id="@+id/podselection__button_select_pod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/podselection__listpods"
android:layout_alignEnd="@+id/podselection__listpods"
android:layout_alignTop="@+id/podselection__edit_filter"
android:contentDescription="@string/confirm_url"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:src="@drawable/ic_arrow_forward_black_48px" />
<TextView
android:id="@+id/podselection__podupti_notice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:autoLink="web"
android:text="@string/podlist_source_note"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/podselection__listpods"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="0dp"
android:gravity="center_vertical"
android:text="@string/prefix_https"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/podselection__fragment">
<ListView
android:id="@+id/podselection__listpods"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/podselection__podupti_notice"
android:layout_below="@+id/podselection__edit_filter"
android:choiceMode="singleChoice" />
<EditText
android:id="@+id/podselection__edit_filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/textView"
android:layout_toStartOf="@+id/podselection__button_select_pod"
android:hint="@string/filter_hint"
android:inputType="textUri|textWebEditText" />
<ImageView
android:id="@+id/podselection__button_select_pod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/podselection__listpods"
android:layout_alignEnd="@+id/podselection__listpods"
android:layout_alignTop="@+id/podselection__edit_filter"
android:contentDescription="@string/confirm_url"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:src="@drawable/ic_arrow_forward_black_48px" />
<TextView
android:id="@+id/podselection__podupti_notice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:autoLink="web"
android:text="@string/podlist_source_note"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/podselection__listpods"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="0dp"
android:gravity="center_vertical"
android:text="@string/prefix_https"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider"/>
<TextView
android:id="@+id/recycler_view__list_item__text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider"/>
</LinearLayout>

View file

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primary"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".activity.SplashActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:shadowColor="@color/black"
android:minHeight="100dp"
android:scaleType="fitXY"
android:minWidth="100dp"
android:src="@drawable/ic_launcher"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp"
android:text="@string/app_name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/white"
android:textSize="32sp"
android:textStyle="bold"/>
</RelativeLayout>

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.github.dfa.diaspora_android.ui.ContextMenuWebView
android:id="@+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true" />
</LinearLayout>

View file

@ -8,42 +8,31 @@
android:id="@+id/action_search" android:id="@+id/action_search"
android:icon="@drawable/ic_search_white_48px" android:icon="@drawable/ic_search_white_48px"
app:showAsAction="always" app:showAsAction="always"
android:orderInCategory="100"
android:title="@string/action_search_by_tags_or_persons" /> android:title="@string/action_search_by_tags_or_persons" />
<item <item
android:id="@+id/action_compose" android:id="@+id/action_compose"
android:icon="@drawable/ic_mode_edit_white_48px" android:icon="@drawable/ic_mode_edit_white_48px"
app:showAsAction="always" app:showAsAction="always"
android:orderInCategory="200"
android:title="@string/action_compose_new_post" /> android:title="@string/action_compose_new_post" />
<item
android:icon="@drawable/ic_share_white_48px"
android:title="@string/action_share_dotdotdot"
app:showAsAction="always" >
<menu>
<item android:id="@+id/action_share_screenshot" android:title="@string/share__share_screenshot"/>
<item android:id="@+id/action_take_screenshot" android:title="@string/share__take_screenshot"/>
<item android:id="@+id/action_share_link" android:title="@string/share__share_link_as_text"/>
</menu>
</item>
<!-- Keep right most --> <!-- Keep right most -->
<item <item
android:id="@+id/action_go_to_top" android:id="@+id/action_go_to_top"
android:icon="@drawable/ic_arrow_upward_white_48px" android:icon="@drawable/ic_arrow_upward_white_48px"
android:title="@string/action_go_to_top" app:showAsAction="always"
app:showAsAction="always"/> android:orderInCategory="400"
android:title="@string/action_go_to_top" />
<!-- overflow menu --> <!-- overflow menu -->
<item
android:id="@+id/action_toggle_desktop_page"
android:icon="@drawable/ic_sync_white_48px"
android:title="@string/action_toggle_desktop_page" />
<item <item
android:id="@+id/action_exit" android:id="@+id/action_exit"
app:showAsAction="never"
android:orderInCategory="600"
android:title="@string/action_exit_app" android:title="@string/action_exit_app"
app:showAsAction="never" /> />
</menu> </menu>

View file

@ -6,19 +6,16 @@
<item <item
android:id="@+id/action_notifications" android:id="@+id/action_notifications"
android:icon="@drawable/ic_notifications_white_48px__layer" android:icon="@drawable/ic_notifications_white_48px__layer"
app:showAsAction="always"
android:orderInCategory="100"
android:title="@string/notifications" android:title="@string/notifications"
app:showAsAction="always" /> />
<item <item
android:id="@+id/action_conversations" android:id="@+id/action_conversations"
android:icon="@drawable/ic_mail_white_48px__layer" android:icon="@drawable/ic_mail_white_48px__layer"
android:title="@string/conversations" app:showAsAction="always"
app:showAsAction="always" /> android:orderInCategory="200"
android:title="@string/conversations" />
<item
android:id="@+id/action_reload"
android:icon="@drawable/ic_refresh_white_48px"
android:title="@string/reload"
app:showAsAction="always"/>
</menu> </menu>

View file

@ -61,7 +61,7 @@
android:title="@string/settings" /> android:title="@string/settings" />
<item <item
android:id="@+id/nav_help_license" android:id="@+id/nav_about"
android:icon="@drawable/ic_info_black_48px" android:icon="@drawable/ic_info_black_48px"
android:title="@string/nav_help_license" /> android:title="@string/nav_help_license" />
</menu> </menu>

View file

@ -1,7 +1,5 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:tools="http://schemas.android.com/tools"
tools:context=".activity.PodSelectionActivity">
<item <item
android:id="@+id/action_reload" android:id="@+id/action_reload"

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:icon="@drawable/ic_share_white_48px"
app:showAsAction="always"
android:orderInCategory="300"
android:title="@string/action_share_dotdotdot">
<menu>
<item android:id="@+id/action_share_screenshot" android:title="@string/share__share_screenshot"/>
<item android:id="@+id/action_take_screenshot" android:title="@string/share__take_screenshot"/>
<item android:id="@+id/action_share_link" android:title="@string/share__share_link_as_text"/>
</menu>
</item>
<item
android:id="@+id/action_toggle_desktop_page"
android:icon="@drawable/ic_sync_white_48px"
android:orderInCategory="700"
android:title="@string/action_toggle_desktop_page" />
</menu>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_reload"
android:icon="@drawable/ic_refresh_white_48px"
app:showAsAction="always"
android:orderInCategory="1000"
android:title="@string/reload"/>
</menu>

View file

@ -21,13 +21,14 @@
<string name="pref_title__load_images">Lade Bilder</string> <string name="pref_title__load_images">Lade Bilder</string>
<string name="pref_desc__load_images">Deaktiviere das Laden von Bildern, um den Datenverbrauch zu verringern</string> <string name="pref_desc__load_images">Deaktiviere das Laden von Bildern, um den Datenverbrauch zu verringern</string>
<!-- Proxy --> <!-- Proxy -->
<string name="pref_title__sub_proxy">Proxy</string>
<string name="pref_title__proxy_enabled">Aktiviere Netzwerkproxy</string> <string name="pref_title__proxy_enabled">Aktiviere Netzwerkproxy</string>
<string name="pref_desc__http_proxy_enabled">Nutze einen Proxyserver, um Firewalls zu umgehen</string> <string name="pref_desc__http_proxy_enabled">Nutze einen Proxyserver, um Firewalls zu umgehen</string>
<string name="pref_title__http_proxy_host">Host</string> <string name="pref_title__http_proxy_host">Host</string>
<string name="pref_title__http_proxy_port">Port</string> <string name="pref_title__http_proxy_port">Port</string>
<!-- Chrome custom tabs --> <!-- Chrome custom tabs -->
<string name="pref_title__chrome_custom_tabs_enabled">Chrome Custom Tabs</string> <string name="pref_title__chrome_custom_tabs_enabled">Chrome Custom Tabs</string>
<string name="pref_desc__chrome_custom_tabs_enabled">Externe Links mit Chrome Custom Tabs öffnen. Für dieses Feature muss Chromium oder Google Chrome installiert sein</string> <string name="pref_desc__chrome_custom_tabs_enabled">Externe Links mit Chrome Custom Tabs öffnen. Chromium oder Google Chrome muss für dieses Feature installiert sein.\nWICHTIGER HINWEIS: Chrome Custom Tabs verwenden die konfigurierten Proxy-Server nicht!</string>
<!-- Diaspora Settings --> <!-- Diaspora Settings -->
<string name="pref_title__personal_settings">Persönliche Einstellungen</string> <string name="pref_title__personal_settings">Persönliche Einstellungen</string>
<string name="pref_desc__personal_settings">Öffne die Einstellungen deines Diaspora Accounts</string> <string name="pref_desc__personal_settings">Öffne die Einstellungen deines Diaspora Accounts</string>

View file

@ -21,13 +21,13 @@
<string name="pref_title__load_images">Charger les images</string> <string name="pref_title__load_images">Charger les images</string>
<string name="pref_desc__load_images">Désactiver le chargements des images pour préserver la data mobile</string> <string name="pref_desc__load_images">Désactiver le chargements des images pour préserver la data mobile</string>
<!-- Proxy --> <!-- Proxy -->
<string name="pref_title__sub_proxy">Proxy</string>
<string name="pref_title__proxy_enabled">Activer Proxy</string> <string name="pref_title__proxy_enabled">Activer Proxy</string>
<string name="pref_desc__http_proxy_enabled">Serveur Proxy.\n(Nécessite un redémarrage)</string> <string name="pref_desc__http_proxy_enabled">Serveur Proxy.\n(Nécessite un redémarrage)</string>
<string name="pref_title__http_proxy_host">Hôte</string> <string name="pref_title__http_proxy_host">Hôte</string>
<string name="pref_title__http_proxy_port">Port</string> <string name="pref_title__http_proxy_port">Port</string>
<!-- Chrome custom tabs --> <!-- Chrome custom tabs -->
<string name="pref_title__chrome_custom_tabs_enabled">Onglets personnalisés de Chrome</string> <string name="pref_title__chrome_custom_tabs_enabled">Onglets personnalisés de Chrome</string>
<string name="pref_desc__chrome_custom_tabs_enabled">Ouvrir les liens externes avec les onglets personnalisés. Chromium ou Google Chrome doit être installé pour cette fonctionnalité</string>
<!-- Diaspora Settings --> <!-- Diaspora Settings -->
<string name="pref_title__personal_settings">Paramètres personnels</string> <string name="pref_title__personal_settings">Paramètres personnels</string>
<string name="pref_desc__personal_settings">Ouvrir vos paramètres de compte diaspora</string> <string name="pref_desc__personal_settings">Ouvrir vos paramètres de compte diaspora</string>

View file

@ -21,11 +21,13 @@
<string name="pref_title__load_images">Carica immagini</string> <string name="pref_title__load_images">Carica immagini</string>
<string name="pref_desc__load_images">Disabilita il caricamento delle immagini per risparmiare la rete dati</string> <string name="pref_desc__load_images">Disabilita il caricamento delle immagini per risparmiare la rete dati</string>
<!-- Proxy --> <!-- Proxy -->
<string name="pref_title__sub_proxy">Proxy</string>
<string name="pref_title__proxy_enabled">Attiva proxy</string> <string name="pref_title__proxy_enabled">Attiva proxy</string>
<string name="pref_desc__http_proxy_enabled">Traffico del proxy di Diaspora per bypassare i firewall.\nPuò essere necessario il riavvio dell\'app</string> <string name="pref_desc__http_proxy_enabled">Traffico del proxy di Diaspora per bypassare i firewall.\nPuò essere necessario il riavvio dell\'app</string>
<string name="pref_title__http_proxy_host">Host</string> <string name="pref_title__http_proxy_host">Host</string>
<string name="pref_title__http_proxy_port">Porta</string> <string name="pref_title__http_proxy_port">Porta</string>
<!-- Chrome custom tabs --> <!-- Chrome custom tabs -->
<string name="pref_title__chrome_custom_tabs_enabled">Schede personalizzate di Chrome</string>
<!-- Diaspora Settings --> <!-- Diaspora Settings -->
<string name="pref_title__personal_settings">Impostazioni personali</string> <string name="pref_title__personal_settings">Impostazioni personali</string>
<string name="pref_desc__personal_settings">Apri le impostazioni del tuo account Diaspora</string> <string name="pref_desc__personal_settings">Apri le impostazioni del tuo account Diaspora</string>

View file

@ -21,13 +21,13 @@
<string name="pref_title__load_images">画像の読み込み</string> <string name="pref_title__load_images">画像の読み込み</string>
<string name="pref_desc__load_images">安全なモバイルデータのため、画像の読み込みを無効にします</string> <string name="pref_desc__load_images">安全なモバイルデータのため、画像の読み込みを無効にします</string>
<!-- Proxy --> <!-- Proxy -->
<string name="pref_title__sub_proxy">プロキシ</string>
<string name="pref_title__proxy_enabled">プロキシを有効にする</string> <string name="pref_title__proxy_enabled">プロキシを有効にする</string>
<string name="pref_desc__http_proxy_enabled">Diaspora の通信をプロキシして、ファイアウォールに回避します。\n再起動が必要になることがあります</string> <string name="pref_desc__http_proxy_enabled">Diaspora の通信をプロキシして、ファイアウォールに回避します。\n再起動が必要になることがあります</string>
<string name="pref_title__http_proxy_host">ホスト</string> <string name="pref_title__http_proxy_host">ホスト</string>
<string name="pref_title__http_proxy_port">ポート</string> <string name="pref_title__http_proxy_port">ポート</string>
<!-- Chrome custom tabs --> <!-- Chrome custom tabs -->
<string name="pref_title__chrome_custom_tabs_enabled">Chrome カスタムタブ</string> <string name="pref_title__chrome_custom_tabs_enabled">Chrome カスタムタブ</string>
<string name="pref_desc__chrome_custom_tabs_enabled">Chrome カスタム タブで外部リンクを開きます。この機能は Chromium または Google Chrome をインストールする必要があります</string>
<!-- Diaspora Settings --> <!-- Diaspora Settings -->
<string name="pref_title__personal_settings">個人用設定</string> <string name="pref_title__personal_settings">個人用設定</string>
<string name="pref_desc__personal_settings">Diaspora アカウント設定を開きます</string> <string name="pref_desc__personal_settings">Diaspora アカウント設定を開きます</string>

View file

@ -7,6 +7,7 @@
<dimen name="activity_vertical_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen>
<dimen name="appbar_padding_top">8dp</dimen> <dimen name="appbar_padding_top">8dp</dimen>
<dimen name="bottom_toolbar_height">45dp</dimen>
<!-- Per the design guidelines, navigation drawers should be between 240dp and 320dp: <!-- Per the design guidelines, navigation drawers should be between 240dp and 320dp:
https://developer.android.com/design/patterns/navigation-drawer.html --> https://developer.android.com/design/patterns/navigation-drawer.html -->

View file

@ -85,7 +85,7 @@
<string name="pref_title__http_proxy_load_tor_preset">Load Tor Preset</string> <string name="pref_title__http_proxy_load_tor_preset">Load Tor Preset</string>
<string name="pref_desc__http_proxy_load_tor_preset">Load proxy settings for Tor (Orbot) HTTP Proxy</string> <string name="pref_desc__http_proxy_load_tor_preset">Load proxy settings for Tor (Orbot) HTTP Proxy</string>
<string name="pref_title__sub_proxy">Proxy</string> <string name="pref_title__sub_proxy">Proxy</string>
<string name="pref_desc__sub_proxy">@string/pref_desc__http_proxy_enabled</string> <string name="pref_desc__sub_proxy" translatable="false">@string/pref_desc__http_proxy_enabled</string>
<string name="pref_title__proxy_enabled">Enable Proxy</string> <string name="pref_title__proxy_enabled">Enable Proxy</string>
<string name="pref_desc__http_proxy_enabled">Proxy Diaspora\'s traffic to circumvent firewalls.\nMay require restart</string> <string name="pref_desc__http_proxy_enabled">Proxy Diaspora\'s traffic to circumvent firewalls.\nMay require restart</string>
<string name="pref_title__http_proxy_host">Host</string> <string name="pref_title__http_proxy_host">Host</string>
@ -96,7 +96,7 @@
<!-- Chrome custom tabs --> <!-- Chrome custom tabs -->
<string name="pref_title__chrome_custom_tabs_enabled">Chrome Custom Tabs</string> <string name="pref_title__chrome_custom_tabs_enabled">Chrome Custom Tabs</string>
<string name="pref_desc__chrome_custom_tabs_enabled">Open external links with Chrome Custom Tabs. Chromium or Google Chrome needs to be installed for this feature</string> <string name="pref_desc__chrome_custom_tabs_enabled">Open external links with Chrome Custom Tabs. Chromium or Google Chrome needs to be installed for this feature. \nIMPORTANT NOTE: Chrome Custom Tabs do not use configured proxy servers!</string>
<!-- Diaspora Settings --> <!-- Diaspora Settings -->
<string name="pref_title__personal_settings">Personal settings</string> <string name="pref_title__personal_settings">Personal settings</string>

View file

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.1.3' classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong

View file

@ -1 +0,0 @@
crowdin.yaml

View file

@ -1,40 +0,0 @@
#!/bin/bash
#########################################################
#
# Title
#
# Created by Gregor Santer (gsantner), 2016
# https://gsantner.github.io/
#
#########################################################
#Pfade
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SCRIPTFILE=$(readlink -f $0)
SCRIPTPATH=$(dirname $SCRIPTFILE)
argc=$#
#########################################################
cd "$SCRIPTDIR"
if [ ! -f "crowdin.yaml" ] ; then
echo "project_identifier: diaspora-for-android" > 'crowdin.yaml'
echo "base_path: $(realpath '../../')" >>'crowdin.yaml'
echo "api_key: DONT_PUSH_API_KEY" >>'crowdin.yaml'
cat "../../crowdin.yaml" >> "crowdin.yaml"
echo "# Add all non locality languages here" >> "crowdin.yaml"
echo "# (e.g. enUS, enUK, deCH, deAT will automatically go into the right folder)" >> "crowdin.yaml"
echo "# Otherwise e.g. en would get added into the folder enEN (which is wrong)." >> "crowdin.yaml"
echo "# https://crowdin.com/page/api/language-codes contains supported language codes" >> "crowdin.yaml"
echo "# The first listed ones here are diffently managed by crowdin than on android" >> "crowdin.yaml"
fi
if grep -q "DONT_PUSH" "crowdin.yaml" ; then
echo "Insert API key to crowdin.yaml"
echo "and update folder to the root folder of the repository"
exit
fi
# Load latest translations
crowdin-cli download -b master