Merged in develop (pull request #20)

This commit is contained in:
tom79 2017-06-28 15:45:53 +00:00
commit f9ec972e55
100 changed files with 2288 additions and 1271 deletions

View File

@ -7,8 +7,8 @@ android {
applicationId "fr.gouv.etalab.mastodon"
minSdkVersion 15
targetSdkVersion 25
versionCode 22
versionName "1.2.5"
versionCode 23
versionName "1.2.6"
}
buildTypes {
release {
@ -17,14 +17,20 @@ android {
}
}
}
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.loopj.android:android-async-http:1.4.9'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
compile 'com.evernote:android-job:1.1.10'
compile 'com.evernote:android-job:1.1.11'
compile 'com.github.chrisbanes:PhotoView:2.0.0'
}

View File

@ -75,6 +75,12 @@
android:launchMode="singleTask"
android:noHistory="true"
/>
<activity android:name="fr.gouv.etalab.mastodon.activities.MediaActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTask"
android:noHistory="true"
/>
<activity android:name="fr.gouv.etalab.mastodon.activities.SearchResultActivity"
android:windowSoftInputMode="stateAlwaysHidden"
android:configChanges="orientation|screenSize"

View File

@ -86,7 +86,7 @@ public class MainActivity extends AppCompatActivity
private ImageLoader imageLoader;
private DisplayImageOptions options;
private View headerLayout;
static final int MIN_DISTANCE = 150;
static final int MIN_DISTANCE = 100;
private float downX, downY;
private int currentScreen = 1;
private actionSwipe currentAction;
@ -254,10 +254,12 @@ public class MainActivity extends AppCompatActivity
}
}else if( Intent.ACTION_SEND.equals(action) && type != null ){
if ("text/plain".equals(type)) {
String sharedSubject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
Intent intentToot = new Intent(getApplicationContext(), TootActivity.class);
Bundle b = new Bundle();
b.putString("sharedSubject", sharedSubject);
b.putString("sharedContent", sharedText);
intentToot.putExtras(b);
startActivity(intentToot);

View File

@ -0,0 +1,350 @@
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
*
* This program 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.
*
* Mastodon Etalab 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 Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
package fr.gouv.etalab.mastodon.activities;
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.URLUtil;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.VideoView;
import com.github.chrisbanes.photoview.PhotoView;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.FileAsyncHttpResponseHandler;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.io.File;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import cz.msebera.android.httpclient.Header;
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
import fr.gouv.etalab.mastodon.client.MastalabSSLSocketFactory;
import fr.gouv.etalab.mastodon.helper.Helper;
import mastodon.etalab.gouv.fr.mastodon.R;
import static fr.gouv.etalab.mastodon.helper.Helper.EXTERNAL_STORAGE_REQUEST_CODE;
/**
* Created by Thomas on 25/06/2017.
* Media Activity
*/
public class MediaActivity extends AppCompatActivity {
private RelativeLayout loader;
private ArrayList<Attachment> attachments;
private PhotoView imageView;
private VideoView videoView;
private float downX, downY;
private int mediaPosition;
MediaActivity.actionSwipe currentAction;
private ImageLoader imageLoader;
private DisplayImageOptions options;
static final int MIN_DISTANCE = 100;
private String finalUrlDownload;
private String preview_url;
private ImageView prev, next;
private boolean isHiding;
private Bitmap downloadedImage;
private File fileVideo;
private TextView progress;
private enum actionSwipe{
RIGHT_TO_LEFT,
LEFT_TO_RIGHT,
POP
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_media);
attachments = getIntent().getParcelableArrayListExtra("mediaArray");
mediaPosition = getIntent().getExtras().getInt("position", 1);
if( attachments == null || attachments.size() == 0)
finish();
if( getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
loader = (RelativeLayout) findViewById(R.id.loader);
imageView = (PhotoView) findViewById(R.id.media_picture);
videoView = (VideoView) findViewById(R.id.media_video);
prev = (ImageView) findViewById(R.id.media_prev);
next = (ImageView) findViewById(R.id.media_next);
prev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPosition--;
displayMediaAtPosition(actionSwipe.POP);
}
});
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mediaPosition++;
displayMediaAtPosition(actionSwipe.POP);
}
});
progress = (TextView) findViewById(R.id.loader_progress);
setTitle("");
final ViewGroup videoLayout = (ViewGroup) findViewById(R.id.videoLayout); // Your own view, read class comments
isHiding = false;
imageLoader = ImageLoader.getInstance();
options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
setTitle("");
displayMediaAtPosition(actionSwipe.POP);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_download:
if(Build.VERSION.SDK_INT >= 23 ){
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(MediaActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_REQUEST_CODE);
} else {
Helper.manageMoveFileDownload(MediaActivity.this, preview_url, finalUrlDownload, downloadedImage, fileVideo);
}
}else{
Helper.manageMoveFileDownload(MediaActivity.this, preview_url, finalUrlDownload, downloadedImage, fileVideo);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_media, menu);
return true;
}
/**
* Manage touch event
* Allows to swipe from timelines
* @param event MotionEvent
* @return boolean
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if( mediaPosition > attachments.size() || mediaPosition < 1 || attachments.size() <= 1)
return super.dispatchTouchEvent(event);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
//Displays navigation left/right buttons
if( attachments != null && attachments.size() > 1 && !isHiding){
prev.setVisibility(View.VISIBLE);
next.setVisibility(View.VISIBLE);
isHiding = true;
new Handler().postDelayed(new Runnable(){
public void run() {
prev.setVisibility(View.GONE);
next.setVisibility(View.GONE);
isHiding = false;
}
}, 1000);
}
return super.dispatchTouchEvent(event);
}
case MotionEvent.ACTION_UP: {
float upX = event.getX();
float upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// swipe horizontal
if( downX > MIN_DISTANCE & (Math.abs(deltaX) > MIN_DISTANCE && Math.abs(deltaY) < MIN_DISTANCE)){
if(deltaX < 0) { switchOnSwipe(MediaActivity.actionSwipe.LEFT_TO_RIGHT); return true; }
if(deltaX > 0) { switchOnSwipe(MediaActivity.actionSwipe.RIGHT_TO_LEFT); return true; }
}else{
currentAction = MediaActivity.actionSwipe.POP;
}
}
}
return super.dispatchTouchEvent(event);
}
private void switchOnSwipe(actionSwipe action){
loader.setVisibility(View.VISIBLE);
mediaPosition = (action == actionSwipe.LEFT_TO_RIGHT)?mediaPosition-1:mediaPosition+1;
displayMediaAtPosition(action);
}
private void displayMediaAtPosition(actionSwipe action){
if( mediaPosition > attachments.size() )
mediaPosition = 1;
if( mediaPosition < 1)
mediaPosition = attachments.size();
currentAction = action;
final Attachment attachment = attachments.get(mediaPosition-1);
String type = attachment.getType();
final String url = attachment.getUrl();
finalUrlDownload = url;
videoView.setVisibility(View.GONE);
if( videoView.isPlaying()) {
videoView.stopPlayback();
}
imageView.setVisibility(View.GONE);
preview_url = attachment.getPreview_url();
switch (type){
case "image":
imageLoader.displayImage(url, imageView, options, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
loader.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
downloadedImage = loadedImage;
fileVideo = null;
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
imageLoader.displayImage(url, imageView, options);
loader.setVisibility(View.GONE);
}
});
break;
case "video":
case "gifv":
AsyncHttpClient client = new AsyncHttpClient();
MastalabSSLSocketFactory mastalabSSLSocketFactory;
try {
mastalabSSLSocketFactory = new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore());
mastalabSSLSocketFactory.setHostnameVerifier(MastalabSSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
client.setSSLSocketFactory(mastalabSSLSocketFactory);
File file = new File(getCacheDir() + "/" + Helper.md5(url)+".mp4");
if(file.exists()) {
Uri uri = Uri.parse(file.getAbsolutePath());
videoView.setVisibility(View.VISIBLE);
videoView.setVideoURI(uri);
videoView.start();
MediaController mc = new MediaController(MediaActivity.this);
videoView.setMediaController(mc);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
loader.setVisibility(View.GONE);
}
});
videoView.setVisibility(View.VISIBLE);
fileVideo = file;
downloadedImage = null;
}else{
progress.setText("0 %");
progress.setVisibility(View.VISIBLE);
client.get(url, new FileAsyncHttpResponseHandler(/* Context */ this) {
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) {
progress.setVisibility(View.GONE);
}
@Override
public void onProgress(long bytesWritten, long totalSize) {
long progressPercentage = (long)100*bytesWritten/totalSize;
progress.setText(String.valueOf(progressPercentage) + " %");
}
@Override
public void onSuccess(int statusCode, Header[] headers, File response) {
File dir = getCacheDir();
File from = new File(dir, response.getName());
File to = new File(dir, Helper.md5(url) + ".mp4");
if (from.exists())
from.renameTo(to);
fileVideo = to;
downloadedImage = null;
progress.setVisibility(View.GONE);
Uri uri = Uri.parse(to.getAbsolutePath());
videoView.setVisibility(View.VISIBLE);
videoView.setVideoURI(uri);
videoView.start();
MediaController mc = new MediaController(MediaActivity.this);
videoView.setMediaController(mc);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
loader.setVisibility(View.GONE);
}
});
videoView.setVisibility(View.VISIBLE);
}
});
}
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
e.printStackTrace();
}
break;
}
String filename = URLUtil.guessFileName(url, null, null);
if( filename == null)
filename = url;
LayoutInflater mInflater = LayoutInflater.from(MediaActivity.this);
ActionBar actionBar = getSupportActionBar();
if( actionBar != null){
View picture_actionbar = mInflater.inflate(R.layout.picture_actionbar, null);
TextView picture_actionbar_title = (TextView) picture_actionbar.findViewById(R.id.picture_actionbar);
picture_actionbar_title.setText(filename);
actionBar.setCustomView(picture_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
}else {
setTitle(url);
}
}
}

View File

@ -32,9 +32,11 @@ import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
@ -97,7 +99,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
private ImageLoader imageLoader;
private DisplayImageOptions options;
private LinearLayout toot_picture_container;
private List<Attachment> attachments;
private ArrayList<Attachment> attachments;
private boolean isSensitive = false;
private ImageButton toot_visibility;
private Button toot_it;
@ -107,7 +109,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
private ListView toot_lv_accounts;
private BroadcastReceiver search_validate;
private Status tootReply = null;
private String sharedContent;
private String sharedContent, sharedSubject;
private CheckBox toot_sensitive;
private String pattern = "^.*(@([a-zA-Z0-9_]{2,}))$";
@ -134,10 +136,49 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
toot_lv_accounts = (ListView) findViewById(R.id.toot_lv_accounts);
toot_sensitive = (CheckBox) findViewById(R.id.toot_sensitive);
final LinearLayout drawer_layout = (LinearLayout) findViewById(R.id.drawer_layout);
/*drawer_layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = drawer_layout.getRootView().getHeight() - drawer_layout.getHeight();
if (heightDiff > 100) {
ViewGroup.LayoutParams params = toot_picture_container.getLayoutParams();
params.height = (int) Helper.convertDpToPixel(20, getApplicationContext());
params.width = (int) Helper.convertDpToPixel(20, getApplicationContext());
toot_picture_container.setLayoutParams(params);
} else {
ViewGroup.LayoutParams params = toot_picture_container.getLayoutParams();
params.height = (int) Helper.convertDpToPixel(100, getApplicationContext());
params.width = (int) Helper.convertDpToPixel(100, getApplicationContext());
toot_picture_container.setLayoutParams(params);
}
}
});*/
drawer_layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = drawer_layout.getRootView().getHeight() - drawer_layout.getHeight();
if (heightDiff > Helper.convertDpToPixel(200, getApplicationContext())) {
ViewGroup.LayoutParams params = toot_picture_container.getLayoutParams();
params.height = (int) Helper.convertDpToPixel(50, getApplicationContext());
params.width = (int) Helper.convertDpToPixel(50, getApplicationContext());
toot_picture_container.setLayoutParams(params);
}else {
ViewGroup.LayoutParams params = toot_picture_container.getLayoutParams();
params.height = (int) Helper.convertDpToPixel(100, getApplicationContext());
params.width = (int) Helper.convertDpToPixel(100, getApplicationContext());
toot_picture_container.setLayoutParams(params);
}
}
});
Bundle b = getIntent().getExtras();
if(b != null) {
tootReply = b.getParcelable("tootReply");
sharedContent = b.getString("sharedContent", null);
sharedSubject = b.getString("sharedSubject", null);
}
if( tootReply != null) {
setTitle(R.string.toot_title_reply);
@ -191,7 +232,11 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
}else {
setTitle(R.string.toot_title);
}
if( sharedContent != null ){ //Shared content
if( sharedSubject != null){
sharedContent = sharedSubject + "\n\n" + sharedContent;
}
toot_content.setText( String.format("\n%s", sharedContent));
}
attachments = new ArrayList<>();

View File

@ -15,34 +15,30 @@
package fr.gouv.etalab.mastodon.activities;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.util.Log;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.DownloadListener;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.webview.MastalabWebChromeClient;
import fr.gouv.etalab.mastodon.webview.MastalabWebViewClient;
import mastodon.etalab.gouv.fr.mastodon.R;
import static fr.gouv.etalab.mastodon.helper.Helper.EXTERNAL_STORAGE_REQUEST_CODE;
import static fr.gouv.etalab.mastodon.helper.Helper.manageDownloads;
/**
* Created by Thomas on 24/06/2017.
@ -52,8 +48,7 @@ import mastodon.etalab.gouv.fr.mastodon.R;
public class WebviewActivity extends AppCompatActivity {
private String url;
private ProgressBar pbar;
private static boolean isVideoFullscreen;
@Override
@ -67,48 +62,15 @@ public class WebviewActivity extends AppCompatActivity {
finish();
if( getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean javascript = sharedpreferences.getBoolean(Helper.SET_JAVASCRIPT, true);
pbar = (ProgressBar) findViewById(R.id.progress_bar);
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(javascript);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setDisplayZoomControls(false);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setSupportMultipleWindows(false);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
//noinspection deprecation
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
webView.getSettings().setMediaPlaybackRequiresUserGesture(true);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
boolean cookies = sharedpreferences.getBoolean(Helper.SET_COOKIES, false);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies(webView, cookies);
}
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
WebView webView = Helper.initializeWebview(WebviewActivity.this, R.id.webview);
setTitle("");
FrameLayout webview_container = (FrameLayout) findViewById(R.id.webview_container);
final ViewGroup videoLayout = (ViewGroup) findViewById(R.id.videoLayout); // Your own view, read class comments
MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient(webView, webview_container, videoLayout);
mastalabWebChromeClient.setOnToggledFullscreen(new ToggledFullscreenCallback() {
MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient(WebviewActivity.this, webView, webview_container, videoLayout);
mastalabWebChromeClient.setOnToggledFullscreen(new MastalabWebChromeClient.ToggledFullscreenCallback() {
@Override
public void toggledFullscreen(boolean fullscreen) {
@ -130,7 +92,22 @@ public class WebviewActivity extends AppCompatActivity {
}
});
webView.setWebChromeClient(mastalabWebChromeClient);
webView.setWebViewClient(new MastalabWebViewClient());
webView.setWebViewClient(new MastalabWebViewClient(WebviewActivity.this));
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
if(Build.VERSION.SDK_INT >= 23 ){
if (ContextCompat.checkSelfPermission(WebviewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(WebviewActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(WebviewActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_REQUEST_CODE);
} else {
manageDownloads(WebviewActivity.this, url);
}
}else{
manageDownloads(WebviewActivity.this, url);
}
}
});
webView.loadUrl(url);
}
@ -147,208 +124,7 @@ public class WebviewActivity extends AppCompatActivity {
@Override
public void onDestroy(){
isVideoFullscreen = false;
super.onDestroy();
}
private class MastalabWebViewClient extends WebViewClient{
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public void onPageStarted (WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
ActionBar actionBar = getSupportActionBar();
LayoutInflater mInflater = LayoutInflater.from(WebviewActivity.this);
if( actionBar != null){
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, null);
TextView webview_title = (TextView) webview_actionbar.findViewById(R.id.webview_title);
webview_title.setText(url);
actionBar.setCustomView(webview_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
}else {
setTitle(url);
}
}
}
interface ToggledFullscreenCallback {
void toggledFullscreen(boolean fullscreen);
}
private class MastalabWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
private FrameLayout videoViewContainer;
private CustomViewCallback videoViewCallback;
private ToggledFullscreenCallback toggledFullscreenCallback;
private WebView webView;
private View activityNonVideoView;
private ViewGroup activityVideoView;
MastalabWebChromeClient(WebView webView, FrameLayout webviewContainer, ViewGroup videoLayout){
isVideoFullscreen = false;
this.webView = webView;
this.activityNonVideoView = webviewContainer;
this.activityVideoView = videoLayout;
}
@Override
public void onProgressChanged(WebView view, int progress) {
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
pbar.setVisibility(ProgressBar.VISIBLE);
}
pbar.setProgress(progress);
if (progress == 100) {
pbar.setVisibility(ProgressBar.GONE);
}
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
LayoutInflater mInflater = LayoutInflater.from(WebviewActivity.this);
ActionBar actionBar = getSupportActionBar();
if( actionBar != null){
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, null);
TextView webview_title = (TextView) webview_actionbar.findViewById(R.id.webview_title);
webview_title.setText(view.getTitle());
ImageView webview_favicon = (ImageView) webview_actionbar.findViewById(R.id.webview_favicon);
if( icon != null)
webview_favicon.setImageBitmap(icon);
actionBar.setCustomView(webview_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
}else {
setTitle(view.getTitle());
}
}
//FULLSCREEN VIDEO
//Code from https://stackoverflow.com/a/16179544/3197259
/**
* Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
* @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
*/
void setOnToggledFullscreen(ToggledFullscreenCallback callback) {
this.toggledFullscreenCallback = callback;
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (view instanceof FrameLayout) {
if( getSupportActionBar() != null)
getSupportActionBar().hide();
// A video wants to be shown
FrameLayout frameLayout = (FrameLayout) view;
View focusedChild = frameLayout.getFocusedChild();
// Save video related variables
isVideoFullscreen = true;
this.videoViewContainer = frameLayout;
this.videoViewCallback = callback;
// Hide the non-video view, add the video view, and show it
activityNonVideoView.setVisibility(View.INVISIBLE);
activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
activityVideoView.setVisibility(View.VISIBLE);
if (focusedChild instanceof android.widget.VideoView) {
// android.widget.VideoView (typically API level <11)
android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;
// Handle all the required events
videoView.setOnCompletionListener(this);
videoView.setOnErrorListener(this);
} else {
// Other classes, including:
// - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)
// - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)
// - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19+)
// Handle HTML5 video ended event only if the class is a SurfaceView
// Test case: TextureView of Sony Xperia T API level 16 doesn't work fullscreen when loading the javascript below
if (webView != null && webView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView) {
// Run javascript code that detects the video end and notifies the Javascript interface
String js = "javascript:";
js += "var _ytrp_html5_video_last;";
js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];";
js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {";
{
js += "_ytrp_html5_video_last = _ytrp_html5_video;";
js += "function _ytrp_html5_video_ended() {";
{
js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView
}
js += "}";
js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";
}
js += "}";
webView.loadUrl(js);
}
}
// Notify full-screen change
if (toggledFullscreenCallback != null) {
toggledFullscreenCallback.toggledFullscreen(true);
}
}
}
// Available in API level 14+, deprecated in API level 18+
@Override @SuppressWarnings("deprecation")
public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
onShowCustomView(view, callback);
}
@Override
public void onHideCustomView() {
if( getSupportActionBar() != null)
getSupportActionBar().show();
// This method should be manually called on video end in all cases because it's not always called automatically.
// This method must be manually called on back key press (from this class' onBackPressed() method).
if (isVideoFullscreen) {
// Hide the video view, remove it, and show the non-video view
activityVideoView.setVisibility(View.INVISIBLE);
activityVideoView.removeView(videoViewContainer);
activityNonVideoView.setVisibility(View.VISIBLE);
// Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
if (videoViewCallback != null && !videoViewCallback.getClass().getName().contains(".chromium.")) {
videoViewCallback.onCustomViewHidden();
}
// Reset video related variables
isVideoFullscreen = false;
videoViewContainer = null;
videoViewCallback = null;
// Notify full-screen change
if (toggledFullscreenCallback != null) {
toggledFullscreenCallback.toggledFullscreen(false);
}
}
}
// Video will start loading
@Override
public View getVideoLoadingProgressView() {
return super.getVideoLoadingProgressView();
}
// Video finished playing, only called in the case of android.widget.VideoView (typically API level <11)
@Override
public void onCompletion(MediaPlayer mp) {
onHideCustomView();
}
// Error while playing video, only called in the case of android.widget.VideoView (typically API level <11)
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false; // By returning false, onCompletion() will be called
}
}
}

View File

@ -1160,7 +1160,7 @@ public class API {
//Retrieves attachments
JSONArray arrayAttachement = resobj.getJSONArray("media_attachments");
List<Attachment> attachments = new ArrayList<>();
ArrayList<Attachment> attachments = new ArrayList<>();
if( arrayAttachement != null){
for(int j = 0 ; j < arrayAttachement.length() ; j++){
JSONObject attObj = arrayAttachement.getJSONObject(j);

View File

@ -14,11 +14,15 @@
* see <http://www.gnu.org/licenses>. */
package fr.gouv.etalab.mastodon.client.Entities;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Thomas on 23/04/2017.
* Manages Media
*/
public class Attachment {
public class Attachment implements Parcelable {
private String id;
private String type;
@ -27,6 +31,31 @@ public class Attachment {
private String preview_url;
private String text_url;
public Attachment(Parcel in) {
id = in.readString();
type = in.readString();
url = in.readString();
remote_url = in.readString();
preview_url = in.readString();
text_url = in.readString();
}
public static final Creator<Attachment> CREATOR = new Creator<Attachment>() {
@Override
public Attachment createFromParcel(Parcel in) {
return new Attachment(in);
}
@Override
public Attachment[] newArray(int size) {
return new Attachment[size];
}
};
public Attachment() {
}
public String getId() {
return id;
}
@ -74,4 +103,19 @@ public class Attachment {
public void setText_url(String text_url) {
this.text_url = text_url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(type);
dest.writeString(url);
dest.writeString(remote_url);
dest.writeString(preview_url);
dest.writeString(text_url);
}
}

View File

@ -18,6 +18,7 @@ package fr.gouv.etalab.mastodon.client.Entities;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -46,7 +47,7 @@ public class Status implements Parcelable {
private String visibility;
private boolean attachmentShown = false;
private boolean spoilerShown = false;
private List<Attachment> media_attachments;
private ArrayList<Attachment> media_attachments;
private List<Mention> mentions;
private List<Tag> tags;
private Application application;
@ -208,11 +209,11 @@ public class Status implements Parcelable {
}
public List<Attachment> getMedia_attachments() {
public ArrayList<Attachment> getMedia_attachments() {
return media_attachments;
}
public void setMedia_attachments(List<Attachment> media_attachments) {
public void setMedia_attachments(ArrayList<Attachment> media_attachments) {
this.media_attachments = media_attachments;
}

View File

@ -185,9 +185,27 @@ public class NotificationsListAdapter extends BaseAdapter {
holder.status_privacy.setImageResource(R.drawable.ic_local_post_office);
break;
}
Drawable imgFav, imgReblog;
if( status.isFavourited())
imgFav = ContextCompat.getDrawable(context, R.drawable.ic_fav_yellow);
else
imgFav = ContextCompat.getDrawable(context, R.drawable.ic_fav_black);
if( status.isReblogged())
imgReblog = ContextCompat.getDrawable(context, R.drawable.ic_retweet_yellow);
else
imgReblog = ContextCompat.getDrawable(context, R.drawable.ic_retweet_black);
imgFav.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f));
imgReblog.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f));
holder.status_favorite_count.setCompoundDrawables(imgFav, null, null, null);
holder.status_reblog_count.setCompoundDrawables(imgReblog, null, null, null);
}else {
holder.notification_status_container.setVisibility(View.GONE);
}
holder.notification_account_profile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

View File

@ -14,7 +14,6 @@ package fr.gouv.etalab.mastodon.drawers;
* You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
import android.Manifest;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -22,21 +21,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
@ -46,18 +39,15 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.util.ArrayList;
import java.util.List;
import fr.gouv.etalab.mastodon.activities.MainActivity;
import fr.gouv.etalab.mastodon.activities.MediaActivity;
import fr.gouv.etalab.mastodon.activities.ShowConversationActivity;
import fr.gouv.etalab.mastodon.activities.TootActivity;
import fr.gouv.etalab.mastodon.client.Entities.Error;
@ -71,7 +61,6 @@ import fr.gouv.etalab.mastodon.client.Entities.Attachment;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
import static fr.gouv.etalab.mastodon.helper.Helper.EXTERNAL_STORAGE_REQUEST_CODE;
/**
@ -201,7 +190,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
holder.status_account_displayname.setCompoundDrawables( img, null, null, null);
}else if( status.getReblog() != null){
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_retweet_header);
Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_retweet_black);
img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
holder.status_account_displayname.setCompoundDrawables( img, null, null, null);
}else{
@ -348,7 +337,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
imgReblog = ContextCompat.getDrawable(context, R.drawable.ic_retweet_black);
imgFav.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f));
imgReblog.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (15 * scale + 0.5f));
imgReblog.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f));
holder.status_favorite_count.setCompoundDrawables(imgFav, null, null, null);
holder.status_reblog_count.setCompoundDrawables(imgReblog, null, null, null);
@ -463,6 +452,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
}else {
holder.status_prev4_container.setVisibility(View.VISIBLE);
}
int position = 1;
for(final Attachment attachment: attachments){
ImageView imageView;
if( i == 0) {
@ -496,13 +486,20 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
if( url.trim().contains("missing.png"))
continue;
imageLoader.displayImage(url, imageView, options);
final int finalPosition = position;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPicture(attachment);
Intent intent = new Intent(context, MediaActivity.class);
Bundle b = new Bundle();
intent.putParcelableArrayListExtra("mediaArray", status.getMedia_attachments());
b.putInt("position", finalPosition);
intent.putExtras(b);
context.startActivity(intent);
}
});
i++;
position++;
}
holder.status_document_container.setVisibility(View.VISIBLE);
}else{
@ -511,101 +508,6 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
holder.status_show_more.setVisibility(View.GONE);
}
private void showPicture(final Attachment attachment) {
final AlertDialog.Builder alertadd = new AlertDialog.Builder(context);
LayoutInflater factory = LayoutInflater.from(context);
final View view = factory.inflate(R.layout.show_attachment, null);
alertadd.setView(view);
final RelativeLayout loader = (RelativeLayout) view.findViewById(R.id.loader);
switch (attachment.getType()){
case "image": {
String url = attachment.getPreview_url();
if(url == null || url.trim().equals(""))
url = attachment.getUrl();
final ImageView imageView = (ImageView) view.findViewById(R.id.dialog_imageview);
imageLoader.displayImage(url, imageView, options, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
loader.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
imageLoader.displayImage(attachment.getPreview_url(), imageView, options);
loader.setVisibility(View.GONE);
}
});
break;
}
case "gifv":
case "video": {
if( attachment.getRemote_url().contains(".gif") ){
view.findViewById(R.id.dialog_webview_container).setVisibility(View.VISIBLE);
WebView webView = (WebView) view.findViewById(R.id.dialog_webview);
webView.getSettings().setJavaScriptEnabled(false);
webView.clearCache(false);
webView.setScrollbarFadingEnabled(true);
webView.getSettings().setBuiltInZoomControls(false);
webView.getSettings().setSupportZoom(false);
webView.getSettings().setUseWideViewPort(false);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
webView.setInitialScale(0);
String url = attachment.getRemote_url();
if(url == null || url.trim().equals(""))
url = attachment.getUrl();
webView.loadUrl(url);
loader.setVisibility(View.GONE);
}else {
String url = attachment.getRemote_url();
if(url == null || url.trim().equals(""))
url = attachment.getUrl();
Uri uri = Uri.parse(url);
VideoView videoView = (VideoView) view.findViewById(R.id.dialog_videoview);
videoView.setVisibility(View.VISIBLE);
videoView.setVideoURI(uri);
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
loader.setVisibility(View.GONE);
}
});
}
break;
}
}
String urlDownload = attachment.getRemote_url();
if( urlDownload == null || urlDownload.trim().equals(""))
urlDownload = attachment.getUrl();
final String finalUrlDownload = urlDownload;
alertadd.setPositiveButton(R.string.download, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
if(Build.VERSION.SDK_INT >= 23 ){
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions((MainActivity)context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_REQUEST_CODE);
} else {
Helper.manageDownloads(context, finalUrlDownload);
}
}else{
Helper.manageDownloads(context, finalUrlDownload);
}
dlg.dismiss();
}
});
alertadd.setNeutralButton(R.string.close, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
dlg.dismiss();
}
});
alertadd.show();
}
@Override
public void onPostAction(int statusCode, API.StatusAction statusAction, String targetedId, Error error) {

View File

@ -13,22 +13,34 @@ package fr.gouv.etalab.mastodon.fragments;
*
* You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v7.widget.SwitchCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import fr.gouv.etalab.mastodon.helper.Helper;
import mastodon.etalab.gouv.fr.mastodon.R;
import static android.app.Activity.RESULT_OK;
/**
* Created by Thomas on 24/06/2017.
@ -38,6 +50,8 @@ public class SettingsFragment extends Fragment {
private Context context;
private static final int ACTIVITY_CHOOSE_FILE = 411;
private TextView set_folder;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -141,10 +155,45 @@ public class SettingsFragment extends Fragment {
}else {
set_cookies_container.setVisibility(View.GONE);
}
final String targeted_folder = sharedpreferences.getString(Helper.SET_FOLDER_RECORD, Environment.DIRECTORY_DOWNLOADS);
set_folder = (TextView) rootView.findViewById(R.id.set_folder);
set_folder.setText(targeted_folder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
set_folder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@SuppressLint("InlinedApi") Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, ACTIVITY_CHOOSE_FILE);
}
});
}else {
LinearLayout file_chooser = (LinearLayout) rootView.findViewById(R.id.file_chooser);
file_chooser.setVisibility(View.GONE);
}
return rootView;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) return;
if(requestCode == ACTIVITY_CHOOSE_FILE) {
Uri treeUri = data.getData();
Uri docUri = DocumentsContract.buildDocumentUriUsingTree(treeUri,
DocumentsContract.getTreeDocumentId(treeUri));
String path = getPath(context, docUri);
if( path == null )
path = Environment.DIRECTORY_DOWNLOADS;
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.SET_FOLDER_RECORD, path);
editor.apply();
set_folder.setText(path);
}
}
@Override
@ -160,7 +209,123 @@ public class SettingsFragment extends Fragment {
this.context = context;
}
//From: https://gist.github.com/asifmujteba/d89ba9074bc941de1eaa#file-asfurihelper
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
}

View File

@ -28,6 +28,7 @@ import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
@ -51,23 +52,36 @@ import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.webkit.CookieManager;
import android.webkit.MimeTypeMap;
import android.webkit.URLUtil;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.loopj.android.http.BuildConfig;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@ -75,6 +89,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -87,6 +102,7 @@ import fr.gouv.etalab.mastodon.asynctasks.RemoveAccountAsyncTask;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Mention;
import fr.gouv.etalab.mastodon.client.Entities.Tag;
import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import mastodon.etalab.gouv.fr.mastodon.R;
@ -160,7 +176,7 @@ public class Helper {
public static final String SET_EMBEDDED_BROWSER = "set_embedded_browser";
public static final String SET_JAVASCRIPT = "set_javascript";
public static final String SET_COOKIES = "set_cookies";
public static final String SET_FOLDER_RECORD = "set_folder_record";
//End points
public static final String EP_AUTHORIZE = "/oauth/authorize";
@ -445,6 +461,10 @@ public class Helper {
}
/**
* Manage downloads with URLs
* @param context Context
@ -460,15 +480,13 @@ public class Helper {
Toast.makeText(context,R.string.toast_error,Toast.LENGTH_LONG).show();
return;
}
Uri uri = Uri.parse(url);
File f = new File("" + uri);
final String fileName = f.getName();
final String fileName = URLUtil.guessFileName(url, null, null);
builder.setMessage(context.getResources().getString(R.string.download_file, fileName));
builder.setCancelable(false)
.setPositiveButton(context.getString(R.string.yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
request.allowScanningByMediaScanner();
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,fileName);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager dm = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
@ -487,6 +505,14 @@ public class Helper {
alert.show();
}
private static String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
/**
* Sends notification with intent
@ -522,6 +548,97 @@ public class Helper {
notificationManager.notify(notificationId, notificationBuilder.build());
}
/**
* Manage downloads with URLs
* @param context Context
* @param url String download url
*/
public static void manageMoveFileDownload(final Context context, final String preview_url, final String url, Bitmap bitmap, File fileVideo){
final String fileName = URLUtil.guessFileName(url, null, null);final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String myDir = sharedpreferences.getString(Helper.SET_FOLDER_RECORD, Environment.DIRECTORY_DOWNLOADS);
try {
File file;
if( bitmap != null) {
File filebmp = new File (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
FileOutputStream out = new FileOutputStream(filebmp);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
file = new File(myDir, fileName);
copy(filebmp, file);
}else{
File fileVideoTargeded = new File(myDir, fileName);
copy(fileVideo, fileVideoTargeded);
file = fileVideoTargeded;
}
Random r = new Random();
final int notificationIdTmp = r.nextInt(10000);
// prepare intent which is triggered if the
// notification is selected
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
final Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
Uri uri = Uri.parse("file://" + file.getAbsolutePath());
intent.setDataAndType(uri, getMimeType(url));
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
File cacheDir = new File(context.getCacheDir(), context.getString(R.string.app_name));
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.imageDownloader(new PatchBaseImageDownloader(context))
.threadPoolSize(5)
.threadPriority(Thread.MIN_PRIORITY + 3)
.denyCacheImageMultipleSizesInMemory()
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoaderNoty.init(config);
imageLoaderNoty.loadImage(preview_url, options, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
notify_user(context, intent, notificationIdTmp, loadedImage, context.getString(R.string.save_over), context.getString(R.string.download_from, fileName));
Toast.makeText(context, R.string.toast_saved,Toast.LENGTH_LONG).show();
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
notify_user(context, intent, notificationIdTmp, BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_save), context.getString(R.string.save_over), context.getString(R.string.download_from, fileName));
Toast.makeText(context, R.string.toast_saved,Toast.LENGTH_LONG).show();
}});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Copy a file by transferring bytes from in to out
* @param src File source file
* @param dst File targeted file
* @throws IOException Exception
*/
public static void copy(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}catch (Exception ignored){}finally {
out.close();
}
} catch (Exception ignored){}finally {
in.close();
}
}
/**
* Returns the instance of the authenticated user
* @param context Context
@ -904,4 +1021,68 @@ public class Helper {
return statusTV;
}
public static WebView initializeWebview(Activity activity, int webviewId){
WebView webView = (WebView) activity.findViewById(webviewId);
final SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean javascript = sharedpreferences.getBoolean(Helper.SET_JAVASCRIPT, true);
webView.getSettings().setJavaScriptEnabled(javascript);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setDisplayZoomControls(false);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setSupportMultipleWindows(false);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
//noinspection deprecation
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
webView.getSettings().setMediaPlaybackRequiresUserGesture(true);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
boolean cookies = sharedpreferences.getBoolean(Helper.SET_COOKIES, false);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies(webView, cookies);
}
webView.getSettings().setAppCacheEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
return webView;
}
public static String md5(final String s) {
final String MD5 = "MD5";
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest
.getInstance(MD5);
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuilder hexString = new StringBuilder();
for (byte aMessageDigest : messageDigest) {
String h = Integer.toHexString(0xFF & aMessageDigest);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
}

View File

@ -22,13 +22,18 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.view.View;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.io.File;
import java.util.List;
@ -124,13 +129,11 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
List<Status> statuses = apiResponse.getStatuses();
if( apiResponse.getError() != null || statuses == null || statuses.size() == 0)
return;
Bitmap icon_notification = null;
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String max_id = sharedpreferences.getString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, null);
final String max_id = sharedpreferences.getString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, null);
//No previous notifications in cache, so no notification will be sent
String message;
String title = null;
for(Status status: statuses){
//The notification associated to max_id is discarded as it is supposed to have already been sent
@ -138,41 +141,55 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
if( (max_id != null && status.getId().equals(max_id)) || status.getAccount().getAcct().trim().equals(acct.trim()))
continue;
String notificationUrl = status.getAccount().getAvatar();
if( notificationUrl != null && icon_notification == null){
try {
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
.imageDownloader(new PatchBaseImageDownloader(getContext()))
.threadPoolSize(5)
.threadPriority(Thread.MIN_PRIORITY + 3)
.denyCacheImageMultipleSizesInMemory()
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoaderNoty.init(config);
icon_notification = imageLoaderNoty.loadImageSync(notificationUrl);
title = getContext().getResources().getString(R.string.notif_pouet, status.getAccount().getUsername());
}catch (Exception e){
icon_notification = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.mastodonlogo);
}
if(statuses.size() > 0 )
message = getContext().getResources().getQuantityString(R.plurals.other_notif_hometimeline, statuses.size(), statuses.size());
else
message = "";
final Intent intent = new Intent(getContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT);
intent.putExtra(PREF_KEY_ID, userId);
long notif_id = Long.parseLong(userId);
final int notificationId = ((notif_id + 2) > 2147483647) ? (int) (2147483647 - notif_id - 2) : (int) (notif_id + 2);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, apiResponse.getMax_id());
editor.apply();
if( notificationUrl != null){
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
.imageDownloader(new PatchBaseImageDownloader(getContext()))
.threadPoolSize(5)
.threadPriority(Thread.MIN_PRIORITY + 3)
.denyCacheImageMultipleSizesInMemory()
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoaderNoty.init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
final String finalMessage = message;
final String finalTitle = getContext().getResources().getString(R.string.notif_pouet, status.getAccount().getUsername());
imageLoaderNoty.loadImage(notificationUrl, options, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
if( max_id != null)
notify_user(getContext(), intent, notificationId, loadedImage, finalTitle, finalMessage);
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
if( max_id != null)
notify_user(getContext(), intent, notificationId, BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.mastodonlogo), finalTitle, finalMessage);
}});
}
}
if(statuses.size() > 0 )
message = getContext().getResources().getQuantityString(R.plurals.other_notif_hometimeline, statuses.size(), statuses.size());
else
message = "";
final Intent intent = new Intent(getContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT);
intent.putExtra(PREF_KEY_ID, userId);
long notif_id = Long.parseLong(userId);
int notificationId = ((notif_id + 2) > 2147483647) ? (int) (2147483647 - notif_id - 2) : (int) (notif_id + 2);
if( max_id != null)
notify_user(getContext(), intent, notificationId, icon_notification,title,message);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, apiResponse.getMax_id());
editor.apply();
}

View File

@ -22,12 +22,19 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.view.View;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.io.File;
import java.util.List;
import java.util.Set;
@ -134,7 +141,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true);
boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true);
boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true);
String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + userId, null);
final String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + userId, null);
//No previous notifications in cache, so no notification will be sent
int newFollows = 0;
int newAdds = 0;
@ -143,7 +150,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
int newShare = 0;
String notificationUrl = null;
String title = null;
String message;
final String message;
for(Notification notification: notifications){
//The notification associated to max_id is discarded as it is supposed to have already been sent
if( max_id != null && notification.getId().equals(max_id))
@ -187,24 +194,6 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
break;
default:
}
if( notificationUrl != null && icon_notification == null){
try {
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
.imageDownloader(new PatchBaseImageDownloader(getContext()))
.threadPoolSize(5)
.threadPriority(Thread.MIN_PRIORITY + 3)
.denyCacheImageMultipleSizesInMemory()
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoaderNoty.init(config);
icon_notification = imageLoaderNoty.loadImageSync(notificationUrl);
}catch (Exception e){
icon_notification = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.mastodonlogo);
}
}
}
int allNotifCount = newFollows + newAdds + newAsks + newMentions + newShare;
if( allNotifCount > 0){
@ -219,9 +208,38 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT);
intent.putExtra(PREF_KEY_ID, userId);
long notif_id = Long.parseLong(userId);
int notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1);
if( max_id != null)
notify_user(getContext(), intent, notificationId, icon_notification,title,message);
final int notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1);
if( notificationUrl != null && icon_notification == null){
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
.imageDownloader(new PatchBaseImageDownloader(getContext()))
.threadPoolSize(5)
.threadPriority(Thread.MIN_PRIORITY + 3)
.denyCacheImageMultipleSizesInMemory()
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoaderNoty.init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
final String finalTitle = title;
imageLoaderNoty.loadImage(notificationUrl, options, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
if( max_id != null)
notify_user(getContext(), intent, notificationId, loadedImage, finalTitle, message);
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
if( max_id != null)
notify_user(getContext(), intent, notificationId, BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.mastodonlogo), finalTitle, message);
}});
}
}
SharedPreferences.Editor editor = sharedpreferences.edit();

View File

@ -0,0 +1,223 @@
package fr.gouv.etalab.mastodon.webview;
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
*
* This program 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.
*
* Mastodon Etalab 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 Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
import android.app.Activity;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import mastodon.etalab.gouv.fr.mastodon.R;
/**
* Created by Thomas on 25/06/2017.
* Custom WebChromeClient
*/
public class MastalabWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
private FrameLayout videoViewContainer;
private WebChromeClient.CustomViewCallback videoViewCallback;
private ToggledFullscreenCallback toggledFullscreenCallback;
private WebView webView;
private View activityNonVideoView;
private ViewGroup activityVideoView;
private ProgressBar pbar;
private boolean isVideoFullscreen;
private Activity activity;
public interface ToggledFullscreenCallback {
void toggledFullscreen(boolean fullscreen);
}
public MastalabWebChromeClient(Activity activity, WebView webView, FrameLayout activityNonVideoView, ViewGroup activityVideoView){
this.activity = activity;
this.isVideoFullscreen = false;
this.webView = webView;
this.pbar = (ProgressBar) activity.findViewById(R.id.progress_bar);
this.activityNonVideoView = activityNonVideoView;
this.activityVideoView = activityVideoView;
}
@Override
public void onProgressChanged(WebView view, int progress) {
if( pbar != null){
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
pbar.setVisibility(ProgressBar.VISIBLE);
}
pbar.setProgress(progress);
if (progress == 100) {
pbar.setVisibility(ProgressBar.GONE);
}
}
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
LayoutInflater mInflater = LayoutInflater.from(activity);
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
if( actionBar != null){
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, null);
TextView webview_title = (TextView) webview_actionbar.findViewById(R.id.webview_title);
webview_title.setText(view.getTitle());
ImageView webview_favicon = (ImageView) webview_actionbar.findViewById(R.id.webview_favicon);
if( icon != null)
webview_favicon.setImageBitmap(icon);
actionBar.setCustomView(webview_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
}else {
activity.setTitle(view.getTitle());
}
}
//FULLSCREEN VIDEO
//Code from https://stackoverflow.com/a/16179544/3197259
/**
* Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
* @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
*/
public void setOnToggledFullscreen(ToggledFullscreenCallback callback) {
this.toggledFullscreenCallback = callback;
}
@Override
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
if (view instanceof FrameLayout) {
if( ((AppCompatActivity) activity).getSupportActionBar() != null)
((AppCompatActivity) activity).getSupportActionBar().hide();
// A video wants to be shown
FrameLayout frameLayout = (FrameLayout) view;
View focusedChild = frameLayout.getFocusedChild();
// Save video related variables
isVideoFullscreen = true;
this.videoViewContainer = frameLayout;
this.videoViewCallback = callback;
// Hide the non-video view, add the video view, and show it
activityNonVideoView.setVisibility(View.INVISIBLE);
activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
activityVideoView.setVisibility(View.VISIBLE);
if (focusedChild instanceof android.widget.VideoView) {
// android.widget.VideoView (typically API level <11)
android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;
// Handle all the required events
videoView.setOnCompletionListener(this);
videoView.setOnErrorListener(this);
} else {
// Other classes, including:
// - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)
// - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)
// - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19+)
// Handle HTML5 video ended event only if the class is a SurfaceView
// Test case: TextureView of Sony Xperia T API level 16 doesn't work fullscreen when loading the javascript below
if (webView != null && webView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView) {
// Run javascript code that detects the video end and notifies the Javascript interface
String js = "javascript:";
js += "var _ytrp_html5_video_last;";
js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];";
js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {";
{
js += "_ytrp_html5_video_last = _ytrp_html5_video;";
js += "function _ytrp_html5_video_ended() {";
{
js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView
}
js += "}";
js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";
}
js += "}";
webView.loadUrl(js);
}
}
// Notify full-screen change
if (toggledFullscreenCallback != null) {
toggledFullscreenCallback.toggledFullscreen(true);
}
}
}
// Available in API level 14+, deprecated in API level 18+
@Override @SuppressWarnings("deprecation")
public void onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
onShowCustomView(view, callback);
}
@Override
public void onHideCustomView() {
if( ((AppCompatActivity) activity).getSupportActionBar() != null)
((AppCompatActivity) activity).getSupportActionBar().show();
// This method should be manually called on video end in all cases because it's not always called automatically.
// This method must be manually called on back key press (from this class' onBackPressed() method).
if (isVideoFullscreen) {
// Hide the video view, remove it, and show the non-video view
activityVideoView.setVisibility(View.INVISIBLE);
activityVideoView.removeView(videoViewContainer);
activityNonVideoView.setVisibility(View.VISIBLE);
// Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
if (videoViewCallback != null && !videoViewCallback.getClass().getName().contains(".chromium.")) {
videoViewCallback.onCustomViewHidden();
}
// Reset video related variables
isVideoFullscreen = false;
videoViewContainer = null;
videoViewCallback = null;
// Notify full-screen change
if (toggledFullscreenCallback != null) {
toggledFullscreenCallback.toggledFullscreen(false);
}
}
}
// Video will start loading
@Override
public View getVideoLoadingProgressView() {
return super.getVideoLoadingProgressView();
}
// Video finished playing, only called in the case of android.widget.VideoView (typically API level <11)
@Override
public void onCompletion(MediaPlayer mp) {
onHideCustomView();
}
// Error while playing video, only called in the case of android.widget.VideoView (typically API level <11)
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false; // By returning false, onCompletion() will be called
}
}

View File

@ -0,0 +1,66 @@
package fr.gouv.etalab.mastodon.webview;
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
*
* This program 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.
*
* Mastodon Etalab 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 Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
import android.app.Activity;
import android.graphics.Bitmap;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import fr.gouv.etalab.mastodon.helper.Helper;
import mastodon.etalab.gouv.fr.mastodon.R;
/**
* Created by Thomas on 25/06/2017.
* Custom WebViewClient
*/
public class MastalabWebViewClient extends WebViewClient {
private Activity activity;
public MastalabWebViewClient(Activity activity){
this.activity = activity;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
@Override
public void onPageStarted (WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
LayoutInflater mInflater = LayoutInflater.from(activity);
if( actionBar != null){
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, null);
TextView webview_title = (TextView) webview_actionbar.findViewById(R.id.webview_title);
webview_title.setText(url);
actionBar.setCustomView(webview_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
}else {
activity.setTitle(url);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 937 B

After

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 715 B

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 850 B

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 869 B

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 473 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/half_overlay"
android:drawable="@drawable/ic_action_clock"
android:width="20dp"
android:height="20dp"
/>
</layer-list>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/half_overlay"
android:drawable="@drawable/ic_action_star"
android:width="20dp"
android:height="20dp"
/>
</layer-list>

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/half_overlay"
android:drawable="@drawable/ic_retweet"
android:width="20dp"
android:height="15dp"
/>
</layer-list>

View File

@ -32,6 +32,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:divider="@null"
>
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Thomas Schneider
This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
This program 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.
Mastodon Etalab 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 Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<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/background_image"
>
<ImageView
android:visibility="gone"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:src="@drawable/ic_prev_pic"
android:id="@+id/media_prev"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_width="20dp"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
<ImageView
android:visibility="gone"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp"
android:id="@+id/media_next"
android:src="@drawable/ic_next_pic"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_width="20dp"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
<com.github.chrisbanes.photoview.PhotoView
android:visibility="gone"
android:layout_centerInParent="true"
android:id="@+id/media_picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<VideoView
android:layout_centerInParent="true"
android:visibility="gone"
android:id="@+id/media_video"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Main Loader -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
>
<ProgressBar
android:id="@+id/pbar_inf"
android:layout_width="50dp"
android:layout_height="50dp"
android:indeterminate="true" />
<TextView
android:id="@+id/loader_progress"
android:textSize="12sp"
android:visibility="gone"
android:layout_marginTop="10dp"
android:textColor="@color/colorAccent"
android:layout_below="@+id/pbar_inf"
android:layout_width="50dp"
android:gravity="center"
android:layout_height="wrap_content" />
</RelativeLayout>
</RelativeLayout>

View File

@ -29,6 +29,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:divider="@null"
>
</ListView>
<RelativeLayout

View File

@ -17,6 +17,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:divider="@null"
>
</ListView>
<!-- Main Loader -->

View File

@ -83,6 +83,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="100dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<RelativeLayout

View File

@ -30,7 +30,7 @@
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="10dp"
android:padding="2dp">
android:padding="1dp">
</ProgressBar>
<FrameLayout
android:id="@+id/webview_container"

View File

@ -15,142 +15,146 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout 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:paddingTop="10dp"
android:paddingBottom="10dp"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:id="@+id/main_container"
android:paddingLeft="@dimen/drawer_padding"
android:paddingRight="@dimen/drawer_padding"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout 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"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_gravity="center_horizontal"
android:id="@+id/account_pp"
android:layout_width="60dp"
android:layout_height="60dp"
tools:ignore="ContentDescription" />
<android.support.design.widget.FloatingActionButton
android:layout_marginTop="20dp"
android:visibility="gone"
android:id="@+id/account_action_block"
app:fabSize="mini"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="center"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_block_white" />
<android.support.design.widget.FloatingActionButton
android:layout_marginTop="20dp"
android:visibility="gone"
android:id="@+id/account_action_mute"
app:fabSize="mini"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="center"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_mute_white" />
</LinearLayout>
<LinearLayout
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:orientation="vertical">
android:id="@+id/main_container"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/account_dn"
android:maxLines="1"
android:orientation="vertical">
<ImageView
android:layout_gravity="center_horizontal"
android:id="@+id/account_pp"
android:layout_width="60dp"
android:layout_height="60dp"
tools:ignore="ContentDescription" />
<android.support.design.widget.FloatingActionButton
android:layout_marginTop="20dp"
android:visibility="gone"
android:id="@+id/account_action_block"
app:fabSize="mini"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="center"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_block_white" />
<android.support.design.widget.FloatingActionButton
android:layout_marginTop="20dp"
android:visibility="gone"
android:id="@+id/account_action_mute"
app:fabSize="mini"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="center"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_mute_white" />
</LinearLayout>
<LinearLayout
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
android:orientation="horizontal">
<TextView
android:id="@+id/account_dn"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="@+id/account_un"
android:maxLines="1"
android:layout_width="wrap_content"
android:textSize="14sp"
android:layout_height="wrap_content"
/>
</LinearLayout>
<TextView
android:id="@+id/account_un"
android:layout_marginTop="10dp"
android:visibility="gone"
android:id="@+id/account_ac"
android:textSize="16sp"
android:maxLines="1"
android:layout_width="wrap_content"
android:textSize="14sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:text="@string/status"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_sc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/following"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_fgc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/followers"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_frc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:animateLayoutChanges="true"
android:visibility="gone"
android:id="@+id/account_ds"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:layout_marginTop="10dp"
android:visibility="gone"
android:id="@+id/account_ac"
android:textSize="16sp"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:text="@string/status"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_sc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/following"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_fgc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/followers"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_frc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:animateLayoutChanges="true"
android:visibility="gone"
android:id="@+id/account_ds"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,57 +15,65 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:id="@+id/account_container"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:id="@+id/account_pp"
android:layout_width="60dp"
android:layout_height="60dp"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/account_un"
android:padding="5dp"
android:maxLines="1"
android:gravity="center"
android:textSize="16sp"
android:layout_gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="wrap_content"
android:gravity="end"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/btn_authorize"
android:text="@string/authorize"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_gravity="end"
android:gravity="center"
android:textColor="@color/white"
style="@style/Base.Widget.AppCompat.Button.Small"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_reject"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:text="@string/reject"
android:layout_gravity="end"
android:gravity="center"
android:textColor="@color/white"
style="@style/Base.Widget.AppCompat.Button.Small"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
android:id="@+id/account_container"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:id="@+id/account_pp"
android:layout_width="60dp"
android:layout_height="60dp"
</LinearLayout>
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/account_un"
android:padding="5dp"
android:maxLines="1"
android:gravity="center"
android:textSize="16sp"
android:layout_gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="wrap_content"
android:gravity="end"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/btn_authorize"
android:text="@string/authorize"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_gravity="end"
android:gravity="center"
android:textColor="@color/white"
style="@style/Base.Widget.AppCompat.Button.Small"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_reject"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:text="@string/reject"
android:layout_gravity="end"
android:gravity="center"
android:textColor="@color/white"
style="@style/Base.Widget.AppCompat.Button.Small"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,136 +15,140 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:paddingTop="10dp"
android:paddingBottom="10dp"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:id="@+id/main_container"
android:paddingLeft="@dimen/drawer_padding"
android:paddingRight="@dimen/drawer_padding"
android:orientation="vertical">
<TextView
android:id="@+id/account_search_title"
android:visibility="gone"
android:textSize="18sp"
android:background="@color/blue_light"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textStyle="bold"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/accounts"
android:textColor="@color/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/account_search_container"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:id="@+id/main_container"
android:orientation="vertical">
<TextView
android:id="@+id/account_search_title"
android:visibility="gone"
android:textSize="18sp"
android:background="@color/blue_light"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textStyle="bold"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/accounts"
android:textColor="@color/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/account_search_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_gravity="center_horizontal"
android:id="@+id/account_pp"
android:layout_width="60dp"
android:layout_height="60dp"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:orientation="vertical">
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/account_dn"
android:maxLines="1"
android:orientation="vertical">
<ImageView
android:layout_gravity="center_horizontal"
android:id="@+id/account_pp"
android:layout_width="60dp"
android:layout_height="60dp"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
android:orientation="horizontal">
<TextView
android:id="@+id/account_dn"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="@+id/account_un"
android:maxLines="1"
android:layout_width="wrap_content"
android:textSize="14sp"
android:layout_height="wrap_content"
/>
</LinearLayout>
<TextView
android:id="@+id/account_un"
android:layout_marginTop="10dp"
android:visibility="gone"
android:maxLines="1"
android:layout_width="wrap_content"
android:textSize="14sp"
android:id="@+id/account_ac"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
<TextView
android:layout_marginTop="10dp"
android:visibility="gone"
android:maxLines="1"
android:id="@+id/account_ac"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:text="@string/status"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_sc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/following"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_fgc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/followers"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_frc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:orientation="horizontal"
android:baselineAligned="false">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:text="@string/status"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_sc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/following"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_fgc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"
android:text="@string/followers"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_frc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,34 +15,42 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:id="@+id/account_container"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:id="@+id/account_pp"
android:layout_width="30dp"
android:layout_height="30dp"
tools:ignore="ContentDescription" />
<TextView
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:maxLines="1"
android:id="@+id/account_un"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_dn"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:maxLines="1"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:orientation="horizontal">
<ImageView
android:layout_gravity="center"
android:id="@+id/account_pp"
android:layout_width="30dp"
android:layout_height="30dp"
tools:ignore="ContentDescription" />
<TextView
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:maxLines="1"
android:id="@+id/account_un"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/account_dn"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:maxLines="1"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,131 +15,139 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:paddingTop="10dp"
android:paddingBottom="10dp"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:id="@+id/main_container"
android:maxWidth="500dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/notification_account_profile"
android:layout_height="50dp"
android:layout_width="50dp"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal|top"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_width="0dp"
android:layout_weight="1"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:padding="5dp"
android:id="@+id/notification_type"
android:textStyle="bold"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:id="@+id/main_container"
android:orientation="horizontal">
<ImageView
android:id="@+id/notification_account_profile"
android:layout_height="50dp"
android:layout_width="50dp"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal|top"
tools:ignore="ContentDescription" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/notification_account_displayname"
android:drawablePadding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:id="@+id/notification_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/status_date"
android:layout_width="match_parent"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_gravity="end"
android:gravity="end"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/notification_status_container"
android:layout_width="match_parent"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/notification_status_content"
android:layout_marginTop="10dp"
android:autoLink="web"
android:padding="5dp"
android:id="@+id/notification_type"
android:textStyle="bold"
android:textSize="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/status_document_container"
android:orientation="vertical"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/notification_account_displayname"
android:drawablePadding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:id="@+id/notification_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/status_date"
android:layout_width="match_parent"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_gravity="end"
android:gravity="end"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/notification_status_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="vertical">
<TextView
android:drawableStart="@drawable/dr_favorites"
android:drawableLeft="@drawable/dr_favorites"
android:drawablePadding="5dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_favorite_count"
android:layout_width="wrap_content"
android:id="@+id/notification_status_content"
android:layout_marginTop="10dp"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:drawableStart="@drawable/dr_reblogs"
android:drawableLeft="@drawable/dr_reblogs"
android:drawablePadding="5dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_reblog_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_marginLeft="30dp"
android:layout_marginStart="30dp"
android:id="@+id/status_reply"
android:layout_gravity="center_vertical"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_reply"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="end"
android:gravity="end"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:id="@+id/status_document_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
<LinearLayout
android:id="@+id/status_action_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="@dimen/drawer_padding"
android:layout_marginStart="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_vertical_margin"
android:layout_marginEnd="@dimen/activity_vertical_margin"
android:layout_marginRight="@dimen/activity_vertical_margin"
android:orientation="horizontal">
<TextView
android:drawablePadding="2dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_favorite_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:drawablePadding="2dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_reblog_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_marginRight="20dp"
android:layout_marginEnd="20dp"
android:id="@+id/status_privacy"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:id="@+id/status_reply"
android:layout_gravity="center_vertical"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@color/light_grey"
/>
android:src="@drawable/ic_reply"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="end"
android:gravity="end"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_height="wrap_content">
<ImageView
android:layout_marginRight="20dp"
android:layout_marginEnd="20dp"
android:id="@+id/status_privacy"
android:layout_gravity="center_vertical"
android:layout_width="25dp"
android:layout_height="25dp"
tools:ignore="ContentDescription" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,329 +15,329 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:paddingTop="10dp"
android:paddingBottom="10dp"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/drawer_padding"
android:paddingRight="@dimen/drawer_padding"
android:layout_marginTop="5dp"
android:id="@+id/main_container"
android:orientation="vertical">
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="false">
<RelativeLayout
android:layout_height="60dp"
android:layout_width="60dp"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal|top">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="@+id/status_account_profile"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_account_profile_boost"
android:layout_height="30dp"
android:layout_width="30dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:background="@drawable/imageview_border"
android:visibility="gone"
tools:ignore="ContentDescription" />
</RelativeLayout>
android:id="@+id/main_container"
android:orientation="vertical">
<LinearLayout
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:orientation="horizontal"
android:baselineAligned="false">
<RelativeLayout
android:layout_height="60dp"
android:layout_width="60dp"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal|top">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="@+id/status_account_profile"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_account_profile_boost"
android:layout_height="30dp"
android:layout_width="30dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:background="@drawable/imageview_border"
android:visibility="gone"
tools:ignore="ContentDescription" />
</RelativeLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_account_displayname"
android:textSize="16sp"
android:textStyle="bold"
android:maxLines="1"
android:drawablePadding="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_account_displayname"
android:textSize="16sp"
android:textStyle="bold"
android:maxLines="1"
android:drawablePadding="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="1"
android:id="@+id/status_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:visibility="gone"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="1"
android:id="@+id/status_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:visibility="gone"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:textSize="14sp"
android:maxLines="1"
android:id="@+id/status_reblog_user"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/status_toot_date"
android:layout_width="match_parent"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_gravity="end"
android:gravity="end"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/status_spoiler_container"
android:layout_width="match_parent"
android:orientation="vertical"
android:visibility="gone"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_spoiler"
android:layout_marginTop="10dp"
android:autoLink="web"
android:id="@+id/status_reblog_user"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/status_spoiler_button"
android:textAllCaps="false"
android:drawableLeft="@drawable/ic_remove_red_eye"
android:drawableStart="@drawable/ic_remove_red_eye"
android:gravity="center"
android:drawablePadding="5dp"
android:paddingLeft="10dp"
android:paddingStart="10dp"
<TextView
android:id="@+id/status_toot_date"
android:layout_width="match_parent"
android:paddingRight="10dp"
android:paddingEnd="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:maxLines="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/load_attachment_spoiler" />
</LinearLayout>
<LinearLayout
android:id="@+id/status_content_container"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_content"
android:layout_marginTop="10dp"
android:autoLink="web"
android:layout_width="match_parent"
android:paddingLeft="10dp"
android:layout_gravity="end"
android:gravity="end"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/status_document_container"
android:orientation="horizontal"
android:id="@+id/status_spoiler_container"
android:layout_width="match_parent"
android:layout_height="200dp"
android:baselineAligned="false">
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/status_prev1"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_prev1_play"
android:visibility="gone"
android:layout_centerInParent="true"
android:layout_width="20dp"
android:src="@drawable/ic_play_arrow"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
</RelativeLayout>
android:orientation="vertical"
android:visibility="gone"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_spoiler"
android:layout_marginTop="10dp"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/status_spoiler_button"
android:textAllCaps="false"
android:drawableLeft="@drawable/ic_remove_red_eye"
android:drawableStart="@drawable/ic_remove_red_eye"
android:gravity="center"
android:drawablePadding="5dp"
android:paddingLeft="10dp"
android:paddingStart="10dp"
android:paddingRight="10dp"
android:paddingEnd="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:maxLines="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/load_attachment_spoiler" />
</LinearLayout>
<LinearLayout
android:id="@+id/status_content_container"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_content"
android:layout_marginTop="10dp"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:id="@+id/status_container2"
android:layout_weight="1"
android:layout_height="match_parent">
android:id="@+id/status_document_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="200dp"
android:baselineAligned="false">
<RelativeLayout
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="0dp"
android:layout_weight="1">
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/status_prev2"
android:id="@+id/status_prev1"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_prev1_play"
android:visibility="gone"
android:id="@+id/status_prev2_play"
android:layout_centerInParent="true"
android:layout_width="20dp"
android:src="@drawable/ic_play_arrow"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
</RelativeLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:id="@+id/status_container2"
android:layout_weight="1"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_marginTop="2dp"
android:id="@+id/status_container3"
android:layout_height="0dp"
android:baselineAligned="false">
android:layout_height="match_parent">
<RelativeLayout
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content">
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="0dp"
android:layout_weight="1">
<ImageView
android:id="@+id/status_prev3"
android:id="@+id/status_prev2"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_prev3_play"
android:layout_centerInParent="true"
android:layout_width="20dp"
android:src="@drawable/ic_play_arrow"
android:visibility="gone"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
</RelativeLayout>
<RelativeLayout
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:layout_weight="1"
android:layout_width="0dp"
android:id="@+id/status_prev4_container"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/status_prev4"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_prev4_play"
android:id="@+id/status_prev2_play"
android:layout_centerInParent="true"
android:visibility="gone"
android:layout_width="20dp"
android:src="@drawable/ic_play_arrow"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
</RelativeLayout>
<LinearLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_marginTop="2dp"
android:id="@+id/status_container3"
android:layout_height="0dp"
android:baselineAligned="false">
<RelativeLayout
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/status_prev3"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_prev3_play"
android:layout_centerInParent="true"
android:layout_width="20dp"
android:src="@drawable/ic_play_arrow"
android:visibility="gone"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
</RelativeLayout>
<RelativeLayout
android:layout_marginLeft="2dp"
android:layout_marginStart="2dp"
android:layout_weight="1"
android:layout_width="0dp"
android:id="@+id/status_prev4_container"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/status_prev4"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/status_prev4_play"
android:layout_centerInParent="true"
android:visibility="gone"
android:layout_width="20dp"
android:src="@drawable/ic_play_arrow"
android:layout_height="20dp"
tools:ignore="ContentDescription" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/status_show_more"
android:visibility="gone"
android:textAllCaps="false"
android:drawableLeft="@drawable/ic_photo"
android:drawableStart="@drawable/ic_photo"
android:gravity="center"
android:drawablePadding="5dp"
android:paddingLeft="10dp"
android:paddingStart="10dp"
android:paddingRight="10dp"
android:paddingEnd="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:maxLines="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/load_attachment" />
</LinearLayout>
<Button
android:id="@+id/status_show_more"
android:visibility="gone"
android:textAllCaps="false"
android:drawableLeft="@drawable/ic_photo"
android:drawableStart="@drawable/ic_photo"
android:gravity="center"
android:drawablePadding="5dp"
android:paddingLeft="10dp"
android:paddingStart="10dp"
android:paddingRight="10dp"
android:paddingEnd="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:maxLines="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/load_attachment" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/status_action_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:padding="@dimen/drawer_padding"
android:layout_marginStart="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_vertical_margin"
android:layout_marginEnd="@dimen/activity_vertical_margin"
android:layout_marginRight="@dimen/activity_vertical_margin"
android:orientation="horizontal">
<TextView
android:drawableStart="@drawable/dr_favorites"
android:drawableLeft="@drawable/dr_favorites"
android:drawablePadding="2dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_favorite_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:drawableStart="@drawable/dr_reblogs"
android:drawableLeft="@drawable/dr_reblogs"
android:drawablePadding="2dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_reblog_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:id="@+id/status_reply"
android:layout_gravity="center_vertical"
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@drawable/ic_reply"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="end"
android:gravity="end"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_height="wrap_content">
<ImageView
android:layout_marginRight="20dp"
android:layout_marginEnd="20dp"
android:id="@+id/status_privacy"
android:id="@+id/status_action_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="@dimen/drawer_padding"
android:layout_marginStart="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_vertical_margin"
android:layout_marginEnd="@dimen/activity_vertical_margin"
android:layout_marginRight="@dimen/activity_vertical_margin"
android:orientation="horizontal">
<TextView
android:drawablePadding="2dp"
android:layout_gravity="center_vertical"
android:layout_width="25dp"
android:layout_height="25dp"
tools:ignore="ContentDescription" />
android:gravity="center_vertical"
android:id="@+id/status_favorite_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:drawablePadding="2dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:id="@+id/status_reblog_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:id="@+id/status_more"
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@drawable/ic_action_more"
android:id="@+id/status_reply"
android:layout_gravity="center_vertical"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_reply"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_gravity="end"
android:gravity="end"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_height="wrap_content">
<ImageView
android:layout_marginRight="20dp"
android:layout_marginEnd="20dp"
android:id="@+id/status_privacy"
android:layout_gravity="center_vertical"
android:layout_width="25dp"
android:layout_height="25dp"
tools:ignore="ContentDescription" />
<ImageView
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:id="@+id/status_more"
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@drawable/ic_action_more"
tools:ignore="ContentDescription" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,97 +15,101 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:paddingTop="10dp"
android:paddingBottom="10dp"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/drawer_padding"
android:paddingRight="@dimen/drawer_padding"
android:layout_marginTop="5dp"
android:id="@+id/main_container"
android:orientation="vertical">
<TextView
android:id="@+id/status_search_title"
android:visibility="gone"
android:text="@string/status"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
android:background="@color/blue_light"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textStyle="bold"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/statuts_search_container"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/status_account_profile"
android:layout_height="50dp"
android:layout_width="50dp"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal|top"
tools:ignore="ContentDescription" />
android:id="@+id/main_container"
android:orientation="vertical">
<TextView
android:id="@+id/status_search_title"
android:visibility="gone"
android:text="@string/status"
android:textColor="@color/colorPrimary"
android:textSize="18sp"
android:background="@color/blue_light"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textStyle="bold"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_width="0dp"
android:layout_weight="1"
android:id="@+id/statuts_search_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
android:orientation="horizontal">
<ImageView
android:id="@+id/status_account_profile"
android:layout_height="50dp"
android:layout_width="50dp"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal|top"
tools:ignore="ContentDescription" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_account_displayname"
android:textSize="16sp"
android:textStyle="bold"
android:maxLines="1"
android:drawablePadding="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/status_account_displayname"
android:textSize="16sp"
android:textStyle="bold"
android:maxLines="1"
android:drawablePadding="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="1"
android:id="@+id/status_account_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:visibility="gone"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="1"
android:id="@+id/status_account_username"
android:layout_width="wrap_content"
android:id="@+id/status_reblog_user"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/status_toot_date"
android:layout_width="match_parent"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_gravity="end"
android:gravity="end"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/status_content"
android:layout_marginTop="10dp"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:visibility="gone"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:textSize="14sp"
android:maxLines="1"
android:id="@+id/status_reblog_user"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/status_toot_date"
android:layout_width="match_parent"
android:paddingRight="10dp"
android:paddingLeft="10dp"
android:layout_gravity="end"
android:gravity="end"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/status_content"
android:layout_marginTop="10dp"
android:autoLink="web"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -15,37 +15,44 @@
You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/drawer_padding"
android:paddingRight="@dimen/drawer_padding"
android:id="@+id/account_container"
android:orientation="vertical">
<TextView
android:id="@+id/tag_search_title"
android:textColor="@color/colorPrimary"
android:visibility="gone"
android:textSize="18sp"
android:background="@color/blue_light"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textStyle="bold"
android:text="@string/tags"
android:layout_gravity="center"
android:gravity="center"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_marginTop="10dp"
card_view:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:padding="20dp"
android:id="@+id/tag_name"
android:textSize="16sp"
android:layout_gravity="center_vertical"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
android:layout_height="wrap_content"
android:id="@+id/account_container"
android:orientation="vertical">
<TextView
android:id="@+id/tag_search_title"
android:textColor="@color/colorPrimary"
android:visibility="gone"
android:textSize="18sp"
android:background="@color/blue_light"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:textStyle="bold"
android:text="@string/tags"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:padding="20dp"
android:id="@+id/tag_name"
android:textSize="16sp"
android:layout_gravity="center_vertical"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -32,6 +32,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:divider="@null"
>
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>

View File

@ -32,6 +32,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:divider="@null"
>
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>

View File

@ -53,6 +53,43 @@
android:text="@string/set_display_reply"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/file_chooser"
android:layout_marginTop="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:maxLines="1"
android:text="@string/set_folder_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:maxLines="2"
android:textStyle="italic"
android:textColor="@color/colorAccent"
android:id="@+id/set_folder"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:layout_marginTop="5dp"
android:textSize="12sp"
android:textStyle="italic"
android:text="@string/click_to_change"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<CheckBox
android:layout_marginTop="10dp"
android:id="@+id/set_embedded_browser"

View File

@ -32,6 +32,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:divider="@null"
>
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>

View File

@ -27,7 +27,6 @@
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -82,6 +81,7 @@
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:padding="2dp"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
@ -99,6 +99,7 @@
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:padding="2dp"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
@ -117,6 +118,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="2dp"
android:layout_height="wrap_content">
<TextView
android:maxLines="1"

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Thomas Schneider
This file is a part of Mastodon Etalab for mastodon.etalab.gouv.fr
This program 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.
Mastodon Etalab 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 Thomas Schneider; if not,
see <http://www.gnu.org/licenses>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_gravity="center_vertical"
android:id="@+id/picture_actionbar"
android:maxLines="1"
android:layout_width="match_parent"
android:textColor="@color/white"
android:layout_height="wrap_content"
android:textSize="14sp" />
</LinearLayout>

View File

@ -0,0 +1,9 @@
<?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_download"
android:title="@string/action_download"
android:icon="@drawable/ic_save"
app:showAsAction="always" />
</menu>

View File

@ -4,4 +4,5 @@
<dimen name="toot_padding">200dp</dimen>
<dimen name="fab_margin">100dp</dimen>
<dimen name="activity_vertical_margin">20dp</dimen>
<dimen name="activity_padding_top_header">15dp</dimen>
</resources>

View File

@ -14,7 +14,7 @@
<color name="splashc">#F5F5F5</color>
<color name="white">#FFF</color>
<color name="blue_light">#E3F2FD</color>
<color name="blue_light">#C5CAE9</color>
<color name="light_grey">#E0E0E0</color>
<color name="darkicon">#424242</color>
<color name="yellowicon">#FDD835</color>
@ -23,6 +23,5 @@
<color name="background_image">#282c37</color>
<color name="green_1">#009688</color>
<color name="red_1">#F44336</color>
<color name="black">#000</color>
</resources>

View File

@ -2,6 +2,7 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="activity_padding_header">10dp</dimen>
<dimen name="nav_header_vertical_spacing">16dp</dimen>
<dimen name="nav_header_height">160dp</dimen>
<dimen name="fab_margin">16dp</dimen>

View File

@ -10,7 +10,7 @@
<string name="action_privacy">Confidentialité</string>
<string name="action_cache">Cache</string>
<string name="action_logout">Déconnexion</string>
<string name="action_download">Télécharger</string>
<string name="login">Connexion</string>
<!-- common -->
@ -20,6 +20,10 @@
<string name="cancel">Annuler</string>
<string name="download">Télécharger</string>
<string name="download_file">Télécharger %1$s</string>
<string name="download_over">Téléchargement terminé</string>
<string name="save_file">Enregistrer %1$s</string>
<string name="save_over">Enregistrement terminé</string>
<string name="download_from">Fichier : %1$s</string>
<string name="password">Mot de passe</string>
<string name="email">Email</string>
<string name="accounts">Comptes</string>
@ -59,7 +63,9 @@
<string name="delete_account_title">Supprimer un compte</string>
<string name="delete_account_message">Supprimer le compte %1$s de l\'application ?</string>
<string name="send_email">Envoyer un email</string>
<string name="choose_file">Veuillez sélectionner un fichier</string>
<string name="choose_file_error">Aucun explorateur de fichiers trouvé !</string>
<string name="click_to_change">Cliquez sur le chemin pour changer</string>
<!-- Status -->
<string name="no_status">Aucun pouet à afficher !</string>
<string name="fav_added">Pouet ajouté aux favoris !</string>
@ -211,6 +217,7 @@
<string name="toast_error_login">Impossible de vous connecter !</string>
<string name="toast_update_credential_ok">Les données du profil ont été sauvegardées !</string>
<string name="nothing_to_do">Aucune action ne peut être réalisée</string>
<string name="toast_saved">Le média a été enregistré !</string>
<!-- Settings -->
<string name="settings_title_optimisation">Optimisation du chargement</string>
<string name="set_toots_page">Nombre de pouets par chargement</string>
@ -224,6 +231,7 @@
<string name="load_attachment_spoiler">Afficher le contenu ?</string>
<string name="load_sensitive_attachment">Charger les images sensibles</string>
<string name="set_display_reply">Afficher le message précédent lors d\'une réponse</string>
<string name="set_folder_title">Destination : </string>
<string name="settings_title_notifications">Gestion des notifications</string>
<string name="set_notif_follow">Notifier lorsque quelquun me suit</string>
@ -299,6 +307,7 @@
L\'utilisation de bibliothèques est réduite au strict minimum :\n
- <b>Android Asynchronous Http Client</b> : Pour la gestion des requêtes\n
- <b>Universal Image Loader</b> : Pour la gestion des médias\n
- <b>Android-Job</b> : Pour la gestion des services
- <b>Android-Job</b> : Pour la gestion des services\n
- <b>PhotoView</b> : Pour la gestion des images
</string>
</resources>