diff --git a/app/app-fdroid-release.apk b/app/app-fdroid-release.apk
new file mode 100644
index 000000000..d9e6f72e9
Binary files /dev/null and b/app/app-fdroid-release.apk differ
diff --git a/app/build.gradle b/app/build.gradle
index 2b6c24625..59b7089f9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,8 +7,8 @@ android {
applicationId "fr.gouv.etalab.mastodon"
minSdkVersion 15
targetSdkVersion 25
- versionCode 48
- versionName "1.4.8"
+ versionCode 49
+ versionName "1.4.9-beta-1"
}
buildTypes {
release {
diff --git a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java
index fb0c6943d..dc8566632 100644
--- a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java
+++ b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java
@@ -15,26 +15,31 @@
package fr.gouv.etalab.mastodon.activities;
import android.annotation.SuppressLint;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
+import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SwitchCompat;
+import android.util.Log;
+import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.support.design.widget.NavigationView;
@@ -61,12 +66,13 @@ import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import java.io.File;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Stack;
-import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import fr.gouv.etalab.mastodon.asynctasks.RetrieveMetaDataAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
@@ -75,7 +81,9 @@ import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment;
import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment;
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
import fr.gouv.etalab.mastodon.helper.Helper;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMetaDataInterface;
import fr.gouv.etalab.mastodon.interfaces.OnUpdateAccountInfoInterface;
+import fr.gouv.etalab.mastodon.services.StreamingService;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
@@ -100,7 +108,7 @@ import android.support.v4.app.FragmentStatePagerAdapter;
public class MainActivity extends AppCompatActivity
- implements NavigationView.OnNavigationItemSelectedListener, OnUpdateAccountInfoInterface {
+ implements NavigationView.OnNavigationItemSelectedListener, OnUpdateAccountInfoInterface, OnRetrieveMetaDataInterface {
private FloatingActionButton toot;
private HashMap tagTile = new HashMap<>();
@@ -119,7 +127,8 @@ public class MainActivity extends AppCompatActivity
private DisplayStatusFragment homeFragment;
private DisplayNotificationsFragment notificationsFragment;
-
+ private BroadcastReceiver receive_data;
+ private boolean display_local, display_global;
public MainActivity() {
}
@@ -127,7 +136,47 @@ public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
+ receive_data = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Bundle b = intent.getExtras();
+ StreamingService.EventStreaming eventStreaming = (StreamingService.EventStreaming) intent.getSerializableExtra("eventStreaming");
+ if( eventStreaming == StreamingService.EventStreaming.NOTIFICATION){
+ if(notificationsFragment != null){
+ if(notificationsFragment.getUserVisibleHint() && isActivityVisible()){
+ notificationsFragment.showNewContent();
+ }else{
+ notificationsFragment.refresh();
+ }
+ }
+ }else if(eventStreaming == StreamingService.EventStreaming.UPDATE){
+ if( homeFragment != null){
+ if(homeFragment.getUserVisibleHint() && isActivityVisible()){
+ homeFragment.showNewContent();
+ }else{
+ homeFragment.refresh();
+ }
+ }
+ }else if(eventStreaming == StreamingService.EventStreaming.DELETE){
+ String id = b.getString("id");
+ if(notificationsFragment != null) {
+ if (notificationsFragment.getUserVisibleHint()) {
+
+ } else {
+
+ }
+ }
+ }
+ updateNotifCounter();
+ updateHomeCounter();
+ }
+ };
+ LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA));
+
+
final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if( theme == Helper.THEME_LIGHT){
@@ -137,6 +186,9 @@ public class MainActivity extends AppCompatActivity
}
setContentView(R.layout.activity_main);
+ display_local = sharedpreferences.getBoolean(Helper.SET_DISPLAY_LOCAL, true);
+ display_global = sharedpreferences.getBoolean(Helper.SET_DISPLAY_GLOBAL, true);
+
//Test if user is still log in
if( ! Helper.isLoggedIn(getApplicationContext())) {
//It is not, the user is redirected to the login page
@@ -145,7 +197,16 @@ public class MainActivity extends AppCompatActivity
finish();
return;
}
-
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ List accounts = new AccountDAO(getApplicationContext(), db).getAllAccount();
+ if( accounts != null){
+ for (Account account: accounts) {
+ Intent intent = new Intent(getApplicationContext(), StreamingService.class);
+ intent.putExtra("accountId", account.getId());
+ intent.putExtra("accountAcct", account.getAcct());
+ startService(intent);
+ }
+ }
Helper.fillMapEmoji(getApplicationContext());
//Here, the user is authenticated
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
@@ -194,8 +255,10 @@ public class MainActivity extends AppCompatActivity
tabLayout.addTab(tabHome);
tabLayout.addTab(tabNotif);
- tabLayout.addTab(tabLocal);
- tabLayout.addTab(tabPublic);
+ if( display_local)
+ tabLayout.addTab(tabLocal);
+ if( display_global)
+ tabLayout.addTab(tabPublic);
viewPager = (ViewPager) findViewById(R.id.viewpager);
main_app_container = (RelativeLayout) findViewById(R.id.main_app_container);
@@ -203,7 +266,6 @@ public class MainActivity extends AppCompatActivity
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
- final boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
@@ -222,29 +284,32 @@ public class MainActivity extends AppCompatActivity
main_app_container.setVisibility(View.GONE);
viewPager.setVisibility(View.VISIBLE);
Helper.switchLayout(MainActivity.this);
- switch (tab.getPosition()){
- case 0:
- item = navigationView.getMenu().findItem(R.id.nav_home);
- fragmentTag = "HOME_TIMELINE";
- if( bubbles && homeFragment != null)
- homeFragment.refreshData();
- updateHomeCounter(0);
- break;
- case 1:
- fragmentTag = "NOTIFICATIONS";
- item = navigationView.getMenu().findItem(R.id.nav_notification);
- updateNotifCounter(0);
- if( bubbles && notificationsFragment != null)
- notificationsFragment.refreshData();
- break;
- case 2:
- fragmentTag = "LOCAL_TIMELINE";
- item = navigationView.getMenu().findItem(R.id.nav_local);
- break;
- case 3:
+ if( tab.getPosition() == 0) {
+ item = navigationView.getMenu().findItem(R.id.nav_home);
+ fragmentTag = "HOME_TIMELINE";
+ if (homeFragment != null && Helper.getUnreadToots(getApplicationContext(), null) > 0) {
+ homeFragment.refresh();
+ }
+ Helper.cacheStatusClear(getApplicationContext(), null);
+ updateHomeCounter();
+ }else if( tab.getPosition() == 1) {
+ fragmentTag = "NOTIFICATIONS";
+ item = navigationView.getMenu().findItem(R.id.nav_notification);
+ if (notificationsFragment != null && Helper.getUnreadNotifications(getApplicationContext(), null) > 0) {
+ notificationsFragment.refresh();
+ }
+ Helper.cacheNotificationsClear(getApplicationContext(), null);
+ updateNotifCounter();
+ }else if( tab.getPosition() == 2 && display_local) {
+
+ fragmentTag = "LOCAL_TIMELINE";
+ item = navigationView.getMenu().findItem(R.id.nav_local);
+ }else if( tab.getPosition() == 2 && !display_local) {
item = navigationView.getMenu().findItem(R.id.nav_global);
fragmentTag = "PUBLIC_TIMELINE";
- break;
+ }else if( tab.getPosition() == 3){
+ item = navigationView.getMenu().findItem(R.id.nav_global);
+ fragmentTag = "PUBLIC_TIMELINE";
}
if( item != null){
toolbarTitle.setText(item.getTitle());
@@ -281,9 +346,15 @@ public class MainActivity extends AppCompatActivity
Fragment fragment = (Fragment) viewPager.getAdapter().instantiateItem(viewPager, tab.getPosition());
switch (tab.getPosition()){
case 0:
+ DisplayStatusFragment displayStatusFragment = ((DisplayStatusFragment) fragment);
+ if( displayStatusFragment != null )
+ displayStatusFragment.scrollToTop();
+ Helper.cacheStatusClear(getApplicationContext(), null);
+ updateHomeCounter();
+ break;
case 2:
case 3:
- DisplayStatusFragment displayStatusFragment = ((DisplayStatusFragment) fragment);
+ displayStatusFragment = ((DisplayStatusFragment) fragment);
if( displayStatusFragment != null )
displayStatusFragment.scrollToTop();
break;
@@ -291,6 +362,8 @@ public class MainActivity extends AppCompatActivity
DisplayNotificationsFragment displayNotificationsFragment = ((DisplayNotificationsFragment) fragment);
if( displayNotificationsFragment != null )
displayNotificationsFragment.scrollToTop();
+ Helper.cacheNotificationsClear(getApplicationContext(), null);
+ updateNotifCounter();
break;
}
}
@@ -354,7 +427,11 @@ public class MainActivity extends AppCompatActivity
Intent intent = new Intent(MainActivity.this, SearchResultActivity.class);
intent.putExtra("search", query);
startActivity(intent);
- return true;
+ toolbar_search.setQuery("", false);
+ toolbar_search.setIconified(true);
+ toolbarTitle.setVisibility(View.VISIBLE);
+ pp_actionBar.setVisibility(View.VISIBLE);
+ return false;
}
@Override
public boolean onQueryTextChange(String newText) {
@@ -421,15 +498,14 @@ public class MainActivity extends AppCompatActivity
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoader.init(configImg);
- SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
options = new DisplayImageOptions.Builder().displayer(new RoundedBitmapDisplayer(90)).cacheInMemory(false)
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
headerLayout = navigationView.getHeaderView(0);
- String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
- Account account = new AccountDAO(getApplicationContext(), db).getAccountByToken(prefKeyOauthTokenT);
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Account account = new AccountDAO(getApplicationContext(), db).getAccountByID(userId);
updateHeaderAccountInfo(MainActivity.this, account, headerLayout, imageLoader, options);
loadPPInActionBar(MainActivity.this, account.getAvatar());
//Locked account can see follow request
@@ -545,6 +621,21 @@ public class MainActivity extends AppCompatActivity
String sharedSubject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
+ /* Some apps don't send the URL as the first part of the EXTRA_TEXT,
+ the BBC News app being one such, in this case find where the URL
+ is and strip that out into sharedText.
+ */
+ Matcher matcher;
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
+ matcher = Patterns.WEB_URL.matcher(sharedText);
+ else
+ matcher = Helper.urlPattern.matcher(sharedText);
+ while (matcher.find()){
+ int matchStart = matcher.start(1);
+ int matchEnd = matcher.end();
+ sharedText = sharedText.substring(matchStart, matchEnd);
+ }
+ new RetrieveMetaDataAsyncTask(sharedText, MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Intent intentToot = new Intent(getApplicationContext(), TootActivity.class);
Bundle b = new Bundle();
b.putString("sharedSubject", sharedSubject);
@@ -599,6 +690,7 @@ public class MainActivity extends AppCompatActivity
//Hide search bar on back pressed
if( !toolbar_search.isIconified()){
toolbar_search.setIconified(true);
+ return;
}
if( viewPager.getVisibility() == View.VISIBLE){
if (stackBack.size() > 1) {
@@ -615,7 +707,7 @@ public class MainActivity extends AppCompatActivity
unCheckAllMenuItems(navigationView);
toot.setVisibility(View.VISIBLE);
//Manages theme for icon colors
- SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if( theme == Helper.THEME_DARK){
changeDrawableColor(getApplicationContext(), R.drawable.ic_reply,R.color.dark_text);
@@ -800,22 +892,25 @@ public class MainActivity extends AppCompatActivity
@Override
public void onResume(){
super.onResume();
- SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
- if( bubbles){
- Handler handler = new Handler();
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {refreshData();}
- }, 1000);
- }
+ MainActivity.activityResumed();
+ updateNotifCounter();
+ updateHomeCounter();
//Proceeds to update of the authenticated account
if(Helper.isLoggedIn(getApplicationContext()))
new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ @Override
+ protected void onPause() {
+ super.onPause();
+ MainActivity.activityPaused();
+ }
-
+ @Override
+ public void onDestroy(){
+ super.onDestroy();
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data);
+ }
@SuppressWarnings("StatementWithEmptyBody")
@Override
@@ -838,20 +933,25 @@ public class MainActivity extends AppCompatActivity
}
toolbarTitle.setText(item.getTitle());
if (id == R.id.nav_home) {
- //noinspection ConstantConditions
- tabLayout.getTabAt(0).select();
+ if( tabLayout.getSelectedTabPosition() != 0)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(0).select();
return true;
} else if( id == R.id.nav_notification){
- //noinspection ConstantConditions
- tabLayout.getTabAt(1).select();
+ if( tabLayout.getSelectedTabPosition() != 1)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(1).select();
return true;
}else if (id == R.id.nav_local) {
- //noinspection ConstantConditions
- tabLayout.getTabAt(2).select();
+
+ if( tabLayout.getSelectedTabPosition() != 2)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(2).select();
return true;
} else if (id == R.id.nav_global) {
- //noinspection ConstantConditions
- tabLayout.getTabAt(3).select();
+ if( tabLayout.getSelectedTabPosition() != 3)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(3).select();
return true;
}
DisplayStatusFragment statusFragment;
@@ -948,7 +1048,16 @@ public class MainActivity extends AppCompatActivity
}
-
+ @Override
+ public void onRetrieveMetaData(boolean error, String image, String title, String description) {
+ if( !error) {
+ Intent intentSendImage = new Intent(Helper.RECEIVE_PICTURE);
+ intentSendImage.putExtra("image", image);
+ intentSendImage.putExtra("title", title);
+ intentSendImage.putExtra("description", description);
+ LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intentSendImage);
+ }
+ }
/**
@@ -973,26 +1082,29 @@ public class MainActivity extends AppCompatActivity
//Selection comes from another menu, no action to do
DisplayStatusFragment statusFragment;
Bundle bundle = new Bundle();
- switch (position) {
- case 0:
- homeFragment = new DisplayStatusFragment();
- bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.HOME);
- homeFragment.setArguments(bundle);
- return homeFragment;
- case 1:
- notificationsFragment = new DisplayNotificationsFragment();
- return notificationsFragment;
- case 2:
+ if (position == 0) {
+ homeFragment = new DisplayStatusFragment();
+ bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.HOME);
+ homeFragment.setArguments(bundle);
+ return homeFragment;
+ }else if( position == 1) {
+ notificationsFragment = new DisplayNotificationsFragment();
+ return notificationsFragment;
+ }else if( position == 2 && display_local) {
statusFragment = new DisplayStatusFragment();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.LOCAL);
statusFragment.setArguments(bundle);
return statusFragment;
- case 3:
+ }else if( position == 2 && !display_local){
statusFragment = new DisplayStatusFragment();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PUBLIC);
statusFragment.setArguments(bundle);
return statusFragment;
-
+ }else if (position == 3){
+ statusFragment = new DisplayStatusFragment();
+ bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PUBLIC);
+ statusFragment.setArguments(bundle);
+ return statusFragment;
}
return null;
}
@@ -1003,40 +1115,8 @@ public class MainActivity extends AppCompatActivity
}
}
- private void refreshData(){
- final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
- String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
- SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
- Account account = new AccountDAO(getApplicationContext(), db).getAccountByToken(prefKeyOauthTokenT);
- if( account != null){
- String last_refresh = sharedpreferences.getString(Helper.LAST_BUBBLE_REFRESH_NOTIF + account.getId(), null);
- Date last_refresh_date = Helper.stringToDate(getApplicationContext(), last_refresh);
- if (last_refresh_date == null || (new Date().getTime() - last_refresh_date.getTime()) >= TimeUnit.SECONDS.toMillis(60)) {
-
- if( notificationsFragment != null ){
- notificationsFragment.update();
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_BUBBLE_REFRESH_NOTIF+ account.getId(),Helper.dateToString(getApplicationContext(), new Date()));
- editor.apply();
- }
- }
-
- last_refresh = sharedpreferences.getString(Helper.LAST_BUBBLE_REFRESH_HOME + account.getId(), null);
- last_refresh_date = Helper.stringToDate(getApplicationContext(), last_refresh);
-
- if (last_refresh_date == null || (new Date().getTime() - last_refresh_date.getTime()) >= TimeUnit.SECONDS.toMillis(60)) {
- if( homeFragment != null ){
- homeFragment.update();
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_BUBBLE_REFRESH_HOME+ account.getId(),Helper.dateToString(getApplicationContext(), new Date()));
- editor.apply();
- }
- }
- }
- }
-
- public void updateHomeCounter(int newHomeCount){
+ public void updateHomeCounter(){
if( tabLayout.getTabAt(0) == null )
return;
//noinspection ConstantConditions
@@ -1044,20 +1124,17 @@ public class MainActivity extends AppCompatActivity
if( tabHome == null)
return;
TextView tabCounterHome = (TextView) tabHome.findViewById(R.id.tab_counter);
- tabCounterHome.setText(String.valueOf(newHomeCount));
- if( newHomeCount > 0){
+ tabCounterHome.setText(String.valueOf(Helper.getUnreadToots(getApplicationContext(), null)));
+ if( Helper.getUnreadToots(getApplicationContext(), null) > 0){
//New data are available
//The fragment is not displayed, so the counter is displayed
- if( tabLayout.getSelectedTabPosition() != 0)
- tabCounterHome.setVisibility(View.VISIBLE);
- else
- tabCounterHome.setVisibility(View.GONE);
+ tabCounterHome.setVisibility(View.VISIBLE);
}else {
tabCounterHome.setVisibility(View.GONE);
}
}
- public void updateNotifCounter(int newNotifCount){
+ public void updateNotifCounter(){
if(tabLayout.getTabAt(1) == null)
return;
//noinspection ConstantConditions
@@ -1065,15 +1142,25 @@ public class MainActivity extends AppCompatActivity
if( tabNotif == null)
return;
TextView tabCounterNotif = (TextView) tabNotif.findViewById(R.id.tab_counter);
- tabCounterNotif.setText(String.valueOf(newNotifCount));
- if( newNotifCount > 0){
- if( tabLayout.getSelectedTabPosition() != 1)
- tabCounterNotif.setVisibility(View.VISIBLE);
- else
- tabCounterNotif.setVisibility(View.GONE);
+ tabCounterNotif.setText(String.valueOf(Helper.getUnreadNotifications(getApplicationContext(), null)));
+ if( Helper.getUnreadNotifications(getApplicationContext(), null) > 0){
+ tabCounterNotif.setVisibility(View.VISIBLE);
}else {
tabCounterNotif.setVisibility(View.GONE);
}
}
+ public static boolean isActivityVisible() {
+ return activityVisible;
+ }
+
+ private static void activityResumed() {
+ activityVisible = true;
+ }
+
+ private static void activityPaused() {
+ activityVisible = false;
+ }
+
+ private static boolean activityVisible;
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 968e2e13f..838a98a6c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -24,6 +24,7 @@
+
+
+
+
+
+
+
@@ -70,7 +79,6 @@
+
developers = new ArrayList<>();
+ private List contributors = new ArrayList<>();
+ private AccountSearchDevAdapter accountSearchWebAdapterDeveloper;
+ private AccountSearchDevAdapter accountSearchWebAdapterContributors;
@SuppressWarnings("deprecation")
@Override
@@ -73,7 +80,8 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA
about_version.setText(getResources().getString(R.string.about_vesrion, version));
} catch (PackageManager.NameNotFoundException ignored) {}
- about_developer = (Button) findViewById(R.id.about_developer);
+ ExpandableHeightListView lv_developers = (ExpandableHeightListView) findViewById(R.id.lv_developers);
+ ExpandableHeightListView lv_contributors = (ExpandableHeightListView) findViewById(R.id.lv_contributors);
Button about_code = (Button) findViewById(R.id.about_code);
Button about_license = (Button) findViewById(R.id.about_license);
Button about_thekinrar = (Button) findViewById(R.id.about_thekinrar);
@@ -93,17 +101,7 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA
startActivity(browserIntent);
}
});
- if(Helper.isLoggedIn(getApplicationContext())) {
- about_developer.setEnabled(false);
- new RetrieveDeveloperAccountsAsyncTask(getApplicationContext(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- about_developer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://mastodon.etalab.gouv.fr/@tschneider"));
- startActivity(browserIntent);
- }
- });
+
about_license.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -120,32 +118,21 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA
}
});
- TextView about_thanks = (TextView) findViewById(R.id.about_thanks_dev);
- String currentText = about_thanks.getText().toString();
- SpannableString spanned_thanks = new SpannableString(currentText);
- int startPosition = spanned_thanks.toString().indexOf("@PhotonQyv");
- int endPosition = startPosition + "@PhotonQyv".length();
- spanned_thanks.setSpan(new ClickableSpan() {
- @Override
- public void onClick(View textView) {
- Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://mastodon.xyz/@PhotonQyv"));
- startActivity(browserIntent);
- }
- @Override
- public void updateDrawState(TextPaint ds) {
- super.updateDrawState(ds);
- }
- }, startPosition, endPosition, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- about_thanks.setText(spanned_thanks, TextView.BufferType.SPANNABLE);
- about_thanks.setMovementMethod(LinkMovementMethod.getInstance());
if( theme == Helper.THEME_LIGHT) {
- about_developer.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
about_code.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
about_thekinrar.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
about_translation.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
about_license.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
}
+
+ lv_contributors.setExpanded(true);
+ lv_developers.setExpanded(true);
+ accountSearchWebAdapterContributors = new AccountSearchDevAdapter(AboutActivity.this, contributors);
+ lv_contributors.setAdapter(accountSearchWebAdapterContributors);
+ accountSearchWebAdapterDeveloper = new AccountSearchDevAdapter(AboutActivity.this, developers);
+ lv_developers.setAdapter(accountSearchWebAdapterDeveloper);
+ new RetrieveDeveloperAccountsAsyncTask(getApplicationContext(), AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -160,22 +147,116 @@ public class AboutActivity extends AppCompatActivity implements OnRetrieveSearcA
}
}
+
@Override
- public void onRetrieveSearchAccounts(APIResponse apiResponse) {
- about_developer.setEnabled(true);
- final List accounts = apiResponse.getAccounts();
- if( accounts != null && accounts.size() > 0 && accounts.get(0) != null) {
- about_developer.setOnClickListener(null);
- about_developer.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(AboutActivity.this, ShowAccountActivity.class);
- Bundle b = new Bundle();
- b.putString("accountId", accounts.get(0).getId());
- intent.putExtras(b);
- startActivity(intent);
- }
- });
+ public void onRetrieveRemoteAccount(boolean error, String name, String username, String instance_name, boolean locked, String avatar, String bio, String statusCount, String followingCount, String followersCount) {
+ if( error){
+ return;
+ }
+ Account account = new Account();
+ account.setInstance(instance_name);
+ account.setAcct(username + "@" + instance_name);
+ account.setAvatar(avatar);
+ account.setDisplay_name(username);
+ account.setStatuses_count_str(statusCount);
+ account.setFollowers_count_str(followersCount);
+ account.setFollowing_count_str(followingCount);
+ account.setUsername(name);
+ account.setLocked(locked);
+ account.setNote(bio);
+ account.setFollowing(false);
+ account.setRemote(true);
+
+ if( username.equals("@tschneider")) {
+ developers.add(account);
+ accountSearchWebAdapterDeveloper.notifyDataSetChanged();
+ }else {
+ contributors.add(account);
+ accountSearchWebAdapterContributors.notifyDataSetChanged();
+ }
+
+ }
+
+ @Override
+ public void onRetrieveSearchDevelopersAccounts(ArrayList accounts) {
+ if( accounts == null || accounts.size() == 0) {
+ new RetrieveRemoteAccountsAsyncTask("tschneider", "mastodon.etalab.gouv.fr", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new RetrieveRemoteAccountsAsyncTask("PhotonQyv", "mastodon.xyz", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new RetrieveRemoteAccountsAsyncTask("angrytux", "social.tchncs.de", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ return;
+ }
+ boolean tschneider = false;
+ boolean PhotonQyv = false;
+ boolean angrytux = false;
+
+ for(Account account: accounts){
+ if( account.getUsername().equals("tschneider")){
+ account.setFollowing(false);
+ account.setRemote(false);
+ developers.add(account);
+ accountSearchWebAdapterDeveloper.notifyDataSetChanged();
+ tschneider = true;
+ new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ if( account.getUsername().equals("PhotonQyv")){
+ account.setFollowing(false);
+ account.setRemote(false);
+ contributors.add(account);
+ accountSearchWebAdapterContributors.notifyDataSetChanged();
+ PhotonQyv = true;
+ new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ if( account.getUsername().equals("angrytux")){
+ account.setFollowing(false);
+ account.setRemote(false);
+ contributors.add(account);
+ accountSearchWebAdapterContributors.notifyDataSetChanged();
+ angrytux = true;
+ new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
+ if( !tschneider)
+ new RetrieveRemoteAccountsAsyncTask("tschneider", "mastodon.etalab.gouv.fr", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if( !PhotonQyv)
+ new RetrieveRemoteAccountsAsyncTask("PhotonQyv", "mastodon.xyz", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ if( !angrytux)
+ new RetrieveRemoteAccountsAsyncTask("angrytux", "social.tchncs.de", AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ @Override
+ public void onResume(){
+ super.onResume();
+ if( developers != null && developers.size() > 0){
+ for(Account account: developers){
+ new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
+ if( contributors != null && contributors.size() > 0){
+ for(Account account: contributors){
+ new RetrieveRelationshipAsyncTask(getApplicationContext(), account.getId(),AboutActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
+ }
+ @Override
+ public void onRetrieveRelationship(Relationship relationship, Error error) {
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, "");
+ if( error != null){
+ return;
+ }
+ for( int i = 0 ; i < developers.size() ; i++){
+ if( contributors.get(i).getId() != null && developers.get(i).getId().equals(relationship.getId())){
+ developers.get(i).setFollowing(relationship.isFollowing() || userId.trim().equals(relationship.getId()));
+ accountSearchWebAdapterDeveloper.notifyDataSetChanged();
+ break;
+ }
+ }
+ for( int i = 0 ; i < contributors.size() ; i++){
+ if( contributors.get(i).getId() != null && contributors.get(i).getId().equals(relationship.getId())){
+ contributors.get(i).setFollowing(relationship.isFollowing() || userId.trim().equals(relationship.getId()));
+ accountSearchWebAdapterContributors.notifyDataSetChanged();
+ break;
+ }
}
}
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsProfileFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/EditProfileActivity.java
similarity index 62%
rename from app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsProfileFragment.java
rename to app/src/main/java/fr/gouv/etalab/mastodon/activities/EditProfileActivity.java
index d7395099e..dd4aef975 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsProfileFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/EditProfileActivity.java
@@ -1,4 +1,3 @@
-package fr.gouv.etalab.mastodon.fragments;
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Mastalab
@@ -13,25 +12,32 @@ package fr.gouv.etalab.mastodon.fragments;
*
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
* see . */
+package fr.gouv.etalab.mastodon.activities;
+
+
+import android.annotation.SuppressLint;
import android.app.Activity;
-import android.content.SharedPreferences;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AlertDialog;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.util.Base64;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -40,35 +46,43 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
+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.BufferedInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
-
-import fr.gouv.etalab.mastodon.activities.MainActivity;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountInfoAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.UpdateCredentialAsyncTask;
import fr.gouv.etalab.mastodon.client.APIResponse;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Error;
+import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountInterface;
import fr.gouv.etalab.mastodon.interfaces.OnUpdateCredentialInterface;
+import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
+import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import mastodon.etalab.gouv.fr.mastodon.R;
+
/**
- * Created by Thomas on 04/06/2017.
- * Fragment for profile settings
+ * Created by Thomas on 27/08/2017.
+ * Edit profile activity
*/
-public class SettingsProfileFragment extends Fragment implements OnRetrieveAccountInterface, OnUpdateCredentialInterface {
+
+public class EditProfileActivity extends AppCompatActivity implements OnRetrieveAccountInterface, OnUpdateCredentialInterface {
+
- private Context context;
private EditText set_profile_name, set_profile_description;
private ImageView set_profile_picture, set_header_picture;
private Button set_change_profile_picture, set_change_header_picture, set_profile_save;
@@ -79,59 +93,128 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
private static final int PICK_IMAGE_PROFILE = 6545;
private String profile_picture, header_picture, profile_username, profile_note;
private Bitmap profile_picture_bmp, profile_header_bmp;
+ private TextView title;
+ private ImageView pp_actionBar;
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
- View rootView = inflater.inflate(R.layout.fragment_settings_profile, container, false);
+ SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
+ int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
+ if( theme == Helper.THEME_LIGHT){
+ setTheme(R.style.AppTheme);
+ }else {
+ setTheme(R.style.AppThemeDark);
+ }
+ setContentView(R.layout.activity_edit_profile);
- set_profile_name = (EditText) rootView.findViewById(R.id.set_profile_name);
- set_profile_description = (EditText) rootView.findViewById(R.id.set_profile_description);
- set_profile_picture = (ImageView) rootView.findViewById(R.id.set_profile_picture);
- set_header_picture = (ImageView) rootView.findViewById(R.id.set_header_picture);
- set_change_profile_picture = (Button) rootView.findViewById(R.id.set_change_profile_picture);
- set_change_header_picture = (Button) rootView.findViewById(R.id.set_change_header_picture);
- set_profile_save = (Button) rootView.findViewById(R.id.set_profile_save);
- set_header_picture_overlay = (TextView) rootView.findViewById(R.id.set_header_picture_overlay);
+ ActionBar actionBar = getSupportActionBar();
+ if( actionBar != null) {
+ LayoutInflater inflater = (LayoutInflater) this.getSystemService(android.content.Context.LAYOUT_INFLATER_SERVICE);
+ View view = inflater.inflate(R.layout.conversation_action_bar, null);
+ actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+ title = (TextView) actionBar.getCustomView().findViewById(R.id.toolbar_title);
+ pp_actionBar = (ImageView) actionBar.getCustomView().findViewById(R.id.pp_actionBar);
+ title.setText(R.string.settings_title_profile);
+ ImageView close_conversation = (ImageView) actionBar.getCustomView().findViewById(R.id.close_conversation);
+ if( close_conversation != null){
+ close_conversation.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
+ }
+ }else{
+ setTitle(R.string.settings_title_profile);
+ }
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Account account = new AccountDAO(getApplicationContext(),db).getAccountByID(userId);
+ String url = account.getAvatar();
+ if( url.startsWith("/") ){
+ url = "https://" + Helper.getLiveInstance(getApplicationContext()) + account.getAvatar();
+ }
+ ImageLoader imageLoader = ImageLoader.getInstance();
+ File cacheDir = new File(getCacheDir(), getString(R.string.app_name));
+ ImageLoaderConfiguration configImg = new ImageLoaderConfiguration.Builder(this)
+ .imageDownloader(new PatchBaseImageDownloader(getApplicationContext()))
+ .threadPoolSize(5)
+ .threadPriority(Thread.MIN_PRIORITY + 3)
+ .denyCacheImageMultipleSizesInMemory()
+ .diskCache(new UnlimitedDiskCache(cacheDir))
+ .build();
+
+ this.imageLoader = ImageLoader.getInstance();
+ this.options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
+ .cacheOnDisk(true).resetViewBeforeLoading(true).build();
+
+ imageLoader.init(configImg);
+ DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
+ .cacheOnDisk(true).resetViewBeforeLoading(true).build();
+ imageLoader.loadImage(url, options, new SimpleImageLoadingListener(){
+ @Override
+ public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
+ super.onLoadingComplete(imageUri, view, loadedImage);
+ BitmapDrawable ppDrawable = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(loadedImage, (int) Helper.convertDpToPixel(25, getApplicationContext()), (int) Helper.convertDpToPixel(25, getApplicationContext()), true));
+ if( pp_actionBar != null){
+ pp_actionBar.setImageDrawable(ppDrawable);
+ } else if( getSupportActionBar() != null){
+
+ getSupportActionBar().setIcon(ppDrawable);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ }
+ }
+ @Override
+ public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
+
+ }});
+
+ set_profile_name = (EditText) findViewById(R.id.set_profile_name);
+ set_profile_description = (EditText) findViewById(R.id.set_profile_description);
+ set_profile_picture = (ImageView) findViewById(R.id.set_profile_picture);
+ set_header_picture = (ImageView) findViewById(R.id.set_header_picture);
+ set_change_profile_picture = (Button) findViewById(R.id.set_change_profile_picture);
+ set_change_header_picture = (Button) findViewById(R.id.set_change_header_picture);
+ set_profile_save = (Button) findViewById(R.id.set_profile_save);
+ set_header_picture_overlay = (TextView) findViewById(R.id.set_header_picture_overlay);
set_profile_save.setEnabled(false);
set_change_header_picture.setEnabled(false);
set_change_profile_picture.setEnabled(false);
set_profile_name.setEnabled(false);
set_profile_description.setEnabled(false);
- context = getContext();
- imageLoader = ImageLoader.getInstance();
- options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
- .cacheOnDisk(true).resetViewBeforeLoading(true).build();
- new RetrieveAccountInfoAsyncTask(context, SettingsProfileFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
- final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
+
+ new RetrieveAccountInfoAsyncTask(getApplicationContext(), EditProfileActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
if( theme == Helper.THEME_LIGHT) {
- set_profile_save.setTextColor(ContextCompat.getColor(context, R.color.white));
+ set_profile_save.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
}
- return rootView;
}
-
-
@Override
- public void onCreate(Bundle saveInstance) {
- super.onCreate(saveInstance);
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
}
-
-
@Override
- public void onAttach(Context context) {
- super.onAttach(context);
- this.context = context;
+ 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;
}
-
@Override
public void onRetrieveAccount(Account account, Error error) {
if( error != null ){
- Toast.makeText(context,R.string.toast_error, Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toast_error, Toast.LENGTH_LONG).show();
return;
}
set_profile_name.setText(account.getDisplay_name());
@@ -161,7 +244,7 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
String content = s.toString().substring(0,160);
set_profile_description.setText(content);
set_profile_description.setSelection(set_profile_description.getText().length());
- Toast.makeText(context,R.string.note_no_space,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.note_no_space,Toast.LENGTH_LONG).show();
}
}
});
@@ -177,7 +260,7 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
String content = s.toString().substring(0,30);
set_profile_name.setText(content);
set_profile_name.setSelection(set_profile_name.getText().length());
- Toast.makeText(context,R.string.username_no_space,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.username_no_space,Toast.LENGTH_LONG).show();
}
}
});
@@ -233,9 +316,9 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
else
profile_note = null;
- AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
- LayoutInflater inflater = ((MainActivity) context).getLayoutInflater();
- View dialogView = inflater.inflate(R.layout.dialog_profile, null);
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(EditProfileActivity.this);
+ LayoutInflater inflater = EditProfileActivity.this.getLayoutInflater();
+ @SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.dialog_profile, null);
dialogBuilder.setView(dialogView);
ImageView back_ground_image = (ImageView) dialogView.findViewById(R.id.back_ground_image);
@@ -248,7 +331,7 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
if( profile_note != null)
dialog_profile_description.setText(profile_note);
if( profile_header_bmp != null) {
- BitmapDrawable background = new BitmapDrawable(context.getResources(), profile_header_bmp);
+ BitmapDrawable background = new BitmapDrawable(getApplicationContext().getResources(), profile_header_bmp);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
//noinspection deprecation
back_ground_image.setBackgroundDrawable(background);
@@ -264,7 +347,7 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
}
}
if( profile_picture_bmp != null) {
- BitmapDrawable background = new BitmapDrawable(context.getResources(), profile_picture_bmp);
+ BitmapDrawable background = new BitmapDrawable(getApplicationContext().getResources(), profile_picture_bmp);
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
//noinspection deprecation
dialog_profile_picture.setBackgroundDrawable(background);
@@ -283,7 +366,7 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
@Override
public void onClick(DialogInterface dialog, int id) {
set_profile_save.setEnabled(false);
- new UpdateCredentialAsyncTask(context, profile_username, profile_note, profile_picture, header_picture, SettingsProfileFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ new UpdateCredentialAsyncTask(getApplicationContext(), profile_username, profile_note, profile_picture, header_picture, EditProfileActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
});
dialogBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@@ -305,16 +388,16 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_HEADER && resultCode == Activity.RESULT_OK) {
if (data == null) {
- Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
return;
}
try {
- InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
+ InputStream inputStream = getApplicationContext().getContentResolver().openInputStream(data.getData());
BufferedInputStream bufferedInputStream;
if (inputStream != null) {
bufferedInputStream = new BufferedInputStream(inputStream);
}else {
- Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
return;
}
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
@@ -326,21 +409,21 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
header_picture = "data:image/png;base64, " + Base64.encodeToString(byteArray, Base64.DEFAULT);
} catch (FileNotFoundException e) {
- Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}else if(requestCode == PICK_IMAGE_PROFILE && resultCode == Activity.RESULT_OK) {
if (data == null) {
- Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
return;
}
try {
- InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
+ InputStream inputStream = getApplicationContext().getContentResolver().openInputStream(data.getData());
BufferedInputStream bufferedInputStream;
if (inputStream != null) {
bufferedInputStream = new BufferedInputStream(inputStream);
}else {
- Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
return;
}
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
@@ -351,7 +434,7 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
byte[] byteArray = byteArrayOutputStream .toByteArray();
profile_picture = "data:image/png;base64, " + Base64.encodeToString(byteArray, Base64.DEFAULT);
} catch (FileNotFoundException e) {
- Toast.makeText(context,R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(),R.string.toot_select_image_error,Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
@@ -360,10 +443,11 @@ public class SettingsProfileFragment extends Fragment implements OnRetrieveAccou
@Override
public void onUpdateCredential(APIResponse apiResponse) {
if( apiResponse.getError() != null){
- Toast.makeText(context, R.string.toast_error, Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(), R.string.toast_error, Toast.LENGTH_LONG).show();
return;
}
- Toast.makeText(context, R.string.toast_update_credential_ok, Toast.LENGTH_LONG).show();
+ Toast.makeText(getApplicationContext(), R.string.toast_update_credential_ok, Toast.LENGTH_LONG).show();
set_profile_save.setEnabled(true);
}
+
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java
index 2a4e882cf..f1dced4a9 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/MediaActivity.java
@@ -362,6 +362,8 @@ public class MediaActivity extends AppCompatActivity {
@Override
public void onPrepared(MediaPlayer mp) {
loader.setVisibility(View.GONE);
+ mp.start();
+ mp.setLooping(true);
}
});
videoView.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java
index 55262e673..5e626391c 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/RemoteFollowActivity.java
@@ -261,7 +261,7 @@ public class RemoteFollowActivity extends AppCompatActivity implements OnRetriev
@Override
- public void onRetrieveRemoteAccount(boolean error, String name, String username, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount) {
+ public void onRetrieveRemoteAccount(boolean error, String name, String username, String instance_name, boolean locked, String avatar, String bio, String statusCount, String followingCount, String followersCount) {
loader.setVisibility(View.GONE);
rf_search.setEnabled(true);
if( error){
@@ -274,9 +274,9 @@ public class RemoteFollowActivity extends AppCompatActivity implements OnRetriev
account.setAcct(screen_name + "@" + instance_name);
account.setAvatar(avatar);
account.setDisplay_name(username);
- account.setStatuses_count(statusCount);
- account.setFollowers_count(followersCount);
- account.setFollowing_count(followingCount);
+ account.setStatuses_count_str(statusCount);
+ account.setFollowers_count_str(followersCount);
+ account.setFollowing_count_str(followingCount);
account.setUsername(name);
account.setLocked(locked);
account.setNote(bio);
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java
index e25e763c5..577cbcff8 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/ShowAccountActivity.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -89,6 +90,8 @@ import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAccountInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsAccountInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRelationshipInterface;
+import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
+import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import mastodon.etalab.gouv.fr.mastodon.R;
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
@@ -122,6 +125,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
private BroadcastReceiver hide_header;
private boolean isHiddingShowing = false;
private LinearLayout main_header_container;
+ private ImageView header_edit_profile;
public enum action{
FOLLOW,
@@ -149,6 +153,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
account_follow = (FloatingActionButton) findViewById(R.id.account_follow);
account_follow_request = (TextView) findViewById(R.id.account_follow_request);
main_header_container = (LinearLayout) findViewById(R.id.main_header_container);
+ header_edit_profile = (ImageView) findViewById(R.id.header_edit_profile);
account_follow.setEnabled(false);
if(b != null){
accountId = b.getString("accountId");
@@ -298,6 +303,14 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
LocalBroadcastManager.getInstance(this).registerReceiver(hide_header, new IntentFilter(Helper.HEADER_ACCOUNT + String.valueOf(instanceValue)));
}
+
+ header_edit_profile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(ShowAccountActivity.this, EditProfileActivity.class);
+ startActivity(intent);
+ }
+ });
}
@@ -520,6 +533,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
account_follow.setEnabled(true);
if( accountId != null && accountId.equals(userId)){
account_follow.setVisibility(View.GONE);
+ header_edit_profile.setVisibility(View.VISIBLE);
}else if( relationship.isBlocking()){
account_follow.setImageResource(R.drawable.ic_unlock_alt);
doAction = action.UNBLOCK;
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java
index f069213f4..c56c7ceee 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java
@@ -17,11 +17,14 @@ package fr.gouv.etalab.mastodon.activities;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.net.Uri;
+import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -49,6 +52,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
+import android.webkit.URLUtil;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
@@ -66,6 +70,8 @@ import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
+import com.loopj.android.http.AsyncHttpClient;
+import com.loopj.android.http.BinaryHttpResponseHandler;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
@@ -74,9 +80,13 @@ import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@@ -86,6 +96,7 @@ import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import cz.msebera.android.httpclient.Header;
import fr.gouv.etalab.mastodon.asynctasks.PostStatusAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveSearchAccountsAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.UploadActionAsyncTask;
@@ -136,7 +147,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
private EditText toot_cw_content;
private LinearLayout toot_reply_content_container;
private Status tootReply = null;
- private String sharedContent, sharedSubject;
+ private String sharedContent, sharedSubject, sharedContentIni;
private CheckBox toot_sensitive;
public long currentToId;
private long restored;
@@ -148,7 +159,9 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
private HorizontalScrollView picture_scrollview;
private int currentCursorPosition, searchLength;
private TextView toot_space_left;
+ private String initialContent;
private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 754;
+ private BroadcastReceiver receive_picture;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -240,6 +253,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
if(b != null) {
tootReply = b.getParcelable("tootReply");
sharedContent = b.getString("sharedContent", null);
+ sharedContentIni = b.getString("sharedContent", null);
sharedSubject = b.getString("sharedSubject", null);
// ACTION_SEND route
if (b.getInt("uriNumber", 0) == 1) {
@@ -261,6 +275,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
}
restored = b.getLong("restored", -1);
}
+ initialContent = toot_content.getText().toString();
if( restored != -1 ){
toot_it.setVisibility(View.GONE);
invalidateOptionsMenu();
@@ -299,21 +314,75 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
}});
if( sharedContent != null ){ //Shared content
+
if( sharedSubject != null){
sharedContent = sharedSubject + "\n\n" + sharedContent;
}
+ receive_picture = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String image = intent.getStringExtra("image");
+ String title = intent.getStringExtra("title");
+ String description = intent.getStringExtra("description");
+ if( description != null && description.length() > 20 ){
+ if( description.length() > 200 )
+ description = description.substring(0,199) + "…";
+ if( title != null)
+ sharedContent = title + "\n\n" + description + "\n\n" + sharedContentIni;
+ else
+ sharedContent = description + "\n\n" + sharedContentIni;
+ toot_content.setText(sharedContent);
+ toot_space_left.setText(String.valueOf(toot_content.length()));
+ toot_content.setSelection(toot_content.getText().length());
+ }
+ if( image != null){
+ AsyncHttpClient client = new AsyncHttpClient();
+ String[] allowedTypes = new String[] { "image/png","image/jpeg" };
+ client.get(image, new BinaryHttpResponseHandler(allowedTypes) {
+ @Override
+ public void onSuccess(int statusCode, Header[] headers, byte[] binaryData) {
+ OutputStream f;
+ try {
+ f = new FileOutputStream(getCacheDir() + URLUtil.guessFileName(image, null, null));
+ picture_scrollview.setVisibility(View.VISIBLE);
+ InputStream bis = new ByteArrayInputStream(binaryData);
+ loading_picture.setVisibility(View.VISIBLE);
+ toot_picture.setEnabled(false);
+ new UploadActionAsyncTask(getApplicationContext(),bis,TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ f.write(binaryData);
+ f.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error) {
+ error.printStackTrace();
+ }
+
+ });
+ }
+
+ }
+ };
+ LocalBroadcastManager.getInstance(this).registerReceiver(receive_picture, new IntentFilter(Helper.RECEIVE_PICTURE));
toot_content.setText( String.format("\n%s", sharedContent));
+ toot_space_left.setText(String.valueOf(toot_content.length()));
}
attachments = new ArrayList<>();
int charsInCw = 0;
int charsInToot = 0;
- uploadSharedImage(sharedUri);
+ if (!sharedUri.isEmpty()) {
+ uploadSharedImage(sharedUri);
+ }
boolean isAccountPrivate = account.isLocked();
if(isAccountPrivate){
if( tootReply == null) {
visibility = "private";
+ toot_visibility.setImageResource(R.drawable.ic_action_lock_closed);
}else {
if( visibility.equals("direct") ){
toot_visibility.setImageResource(R.drawable.ic_local_post_office);
@@ -523,6 +592,14 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
}
}
+ @Override
+ public void onDestroy(){
+ super.onDestroy();
+ if( receive_picture != null)
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_picture);
+ }
+
+
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[], @NonNull int[] grantResults) {
@@ -546,6 +623,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
mToast.show();
}
+
// Handles uploading shared images
public void uploadSharedImage(ArrayList uri)
{
@@ -769,6 +847,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
//Clear content
toot_content.setText("");
toot_cw_content.setText("");
+ toot_space_left.setText(0);
if( attachments != null) {
for (Attachment attachment : attachments) {
View namebar = findViewById(Integer.parseInt(attachment.getId()));
@@ -842,6 +921,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
//Adds the shorter text_url of attachment at the end of the toot
int selectionBefore = toot_content.getSelectionStart();
toot_content.setText(toot_content.getText().toString() + "\n" + attachment.getText_url());
+ toot_space_left.setText(String.valueOf(toot_content.length()));
//Moves the cursor
if (selectionBefore >= 0)
toot_content.setSelection(selectionBefore);
@@ -890,6 +970,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
//Clears the text_url at the end of the toot
for this attachment
int selectionBefore = toot_content.getSelectionStart();
toot_content.setText(toot_content.getText().toString().replace(attachment.getText_url(), ""));
+ toot_space_left.setText(String.valueOf(toot_content.length()));
//Moves the cursor
if (selectionBefore >= 0)
toot_content.setSelection(selectionBefore);
@@ -977,6 +1058,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
//Clear the toot
toot_content.setText("");
toot_cw_content.setText("");
+ toot_space_left.setText("0");
if( attachments != null) {
for (Attachment attachment : attachments) {
View namebar = findViewById(Integer.parseInt(attachment.getId()));
@@ -1059,6 +1141,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
if( currentCursorPosition < oldContent.length() - 1)
newContent += oldContent.substring(currentCursorPosition, oldContent.length()-1);
toot_content.setText(newContent);
+ toot_space_left.setText(String.valueOf(toot_content.length()));
toot_content.setSelection(newPosition);
AccountsSearchAdapter accountsListAdapter = new AccountsSearchAdapter(TootActivity.this, new ArrayList());
toot_content.setThreshold(1);
@@ -1132,6 +1215,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
}
String content = status.getContent();
toot_content.setText(content);
+ toot_space_left.setText(String.valueOf(toot_content.length()));
toot_content.setSelection(toot_content.getText().length());
switch (status.getVisibility()){
case "public":
@@ -1163,6 +1247,7 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
else
setTitle(R.string.toot_title);
}
+ initialContent = toot_content.getText().toString();
toot_space_left.setText(String.valueOf(toot_content.getText().length() + toot_cw_content.getText().length()));
}
@@ -1245,9 +1330,10 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
//Put a "dot" at the end of all mentioned account to force capitalization
toot_content.append(" . ");
}
-
+ toot_space_left.setText(String.valueOf(toot_content.length()));
toot_content.setSelection(toot_content.getText().length()); //Put cursor at the end
}
+ initialContent = toot_content.getText().toString();
}
@@ -1256,7 +1342,8 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
//Nothing to store here....
if(toot_content.getText().toString().trim().length() == 0 && (attachments == null || attachments.size() <1) && toot_cw_content.getText().toString().trim().length() == 0)
return;
-
+ if( initialContent.equals(toot_content.getText().toString()))
+ return;
Status toot = new Status();
toot.setSensitive(isSensitive);
toot.setMedia_attachments(attachments);
@@ -1311,6 +1398,4 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc
changeDrawableColor(TootActivity.this, R.drawable.ic_check, R.color.white);
}
}
-
-
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java
index dc3b5d287..985ebb20b 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/WebviewActivity.java
@@ -147,6 +147,20 @@ public class WebviewActivity extends AppCompatActivity {
this.url = newUrl;
}
+ @Override
+ public void onPause(){
+ super.onPause();
+ if( webView != null)
+ webView.onPause();
+ }
+
+ @Override
+ public void onResume(){
+ super.onResume();
+ if( webView != null)
+ webView.onResume();
+ }
+
@Override
public void onBackPressed() {
if (webView.canGoBack()){
@@ -159,6 +173,7 @@ public class WebviewActivity extends AppCompatActivity {
@Override
public void onDestroy(){
super.onDestroy();
-
+ if( webView != null)
+ webView.destroy();
}
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java
index caa29d57a..63afa5432 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveDeveloperAccountsAsyncTask.java
@@ -16,9 +16,13 @@ package fr.gouv.etalab.mastodon.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
+
+import java.util.ArrayList;
+
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.APIResponse;
-import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface;
+import fr.gouv.etalab.mastodon.client.Entities.Account;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchDevelopersAccountshInterface;
/**
@@ -29,23 +33,32 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface;
public class RetrieveDeveloperAccountsAsyncTask extends AsyncTask {
private Context context;
- private APIResponse apiResponse;
- private OnRetrieveSearcAccountshInterface listener;
+ private OnRetrieveSearchDevelopersAccountshInterface listener;
+ private ArrayList accounts;
- public RetrieveDeveloperAccountsAsyncTask(Context context, OnRetrieveSearcAccountshInterface onRetrieveSearcAccountshInterface){
+ public RetrieveDeveloperAccountsAsyncTask(Context context, OnRetrieveSearchDevelopersAccountshInterface onRetrieveSearchDevelopersAccountshInterface){
this.context = context;
- this.listener = onRetrieveSearcAccountshInterface;
+ this.listener = onRetrieveSearchDevelopersAccountshInterface;
}
@Override
protected Void doInBackground(Void... params) {
API api = new API(context);
- apiResponse = api.searchDeveloper();
+ accounts = new ArrayList<>();
+ APIResponse apiResponse = api.searchAccounts("@tschneider@mastodon.etalab.gouv.fr", 1);
+ if( apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0)
+ accounts.add(apiResponse.getAccounts().get(0));
+ apiResponse = api.searchAccounts("@PhotonQyv@mastodon.xyz",1);
+ if( apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0)
+ accounts.add(apiResponse.getAccounts().get(0));
+ apiResponse = api.searchAccounts("@angrytux@social.tchncs.de",1);
+ if( apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0)
+ accounts.add(apiResponse.getAccounts().get(0));
return null;
}
@Override
protected void onPostExecute(Void result) {
- listener.onRetrieveSearchAccounts(apiResponse);
+ listener.onRetrieveSearchDevelopersAccounts(accounts);
}
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java
index 4c913630e..99d93fd67 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java
@@ -15,10 +15,8 @@
package fr.gouv.etalab.mastodon.asynctasks;
import android.content.Context;
-import android.content.SharedPreferences;
import android.os.AsyncTask;
-
-import java.util.Date;
+import android.util.Log;
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.APIResponse;
@@ -61,8 +59,6 @@ public class RetrieveFeedsAsyncTask extends AsyncTask {
this.max_id = max_id;
this.listener = onRetrieveFeedsInterface;
this.refreshData = true;
- updateTimeRefresh();
-
}
public RetrieveFeedsAsyncTask(Context context, Type action, String targetedID, String max_id, boolean showMediaOnly, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
@@ -73,7 +69,6 @@ public class RetrieveFeedsAsyncTask extends AsyncTask {
this.targetedID = targetedID;
this.showMediaOnly = showMediaOnly;
this.refreshData = true;
- updateTimeRefresh();
}
public RetrieveFeedsAsyncTask(Context context, Type action, String tag, String targetedID, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
this.context = context;
@@ -83,21 +78,11 @@ public class RetrieveFeedsAsyncTask extends AsyncTask {
this.targetedID = targetedID;
this.tag = tag;
this.refreshData = true;
- updateTimeRefresh();
}
- public RetrieveFeedsAsyncTask(Context context, Type action, String max_id, boolean refreshData, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
- this.context = context;
- this.action = action;
- this.max_id = max_id;
- this.listener = onRetrieveFeedsInterface;
- this.refreshData = refreshData;
- updateTimeRefresh();
- }
@Override
protected Void doInBackground(Void... params) {
-
API api = new API(context);
switch (action){
case HOME:
@@ -134,14 +119,4 @@ public class RetrieveFeedsAsyncTask extends AsyncTask {
protected void onPostExecute(Void result) {
listener.onRetrieveFeeds(apiResponse, refreshData);
}
-
- private void updateTimeRefresh(){
- if( action == Type.HOME) {
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedpreferences.edit();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- editor.putString(Helper.LAST_BUBBLE_REFRESH_HOME + userId, Helper.dateToString(context, new Date()));
- editor.apply();
- }
- }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMetaDataAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMetaDataAsyncTask.java
new file mode 100644
index 000000000..788466cfc
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMetaDataAsyncTask.java
@@ -0,0 +1,75 @@
+/* Copyright 2017 Thomas Schneider
+ *
+ * This file is a part of Mastalab
+ *
+ * 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.
+ *
+ * Mastalab 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 Mastalab; if not,
+ * see . */
+package fr.gouv.etalab.mastodon.asynctasks;
+
+import android.os.AsyncTask;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.select.Elements;
+import java.io.IOException;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMetaDataInterface;
+
+
+/**
+ * Created by Thomas on 02/09/2017.
+ * Retrieves metadata of a remote page
+ */
+
+public class RetrieveMetaDataAsyncTask extends AsyncTask {
+
+ private OnRetrieveMetaDataInterface listener;
+ private String url;
+ private boolean error = false;
+ private String image, title, description;
+
+ public RetrieveMetaDataAsyncTask(String url, OnRetrieveMetaDataInterface onRetrieveRemoteAccountInterface){
+ this.url = url;
+ this.listener = onRetrieveRemoteAccountInterface;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ String userAgent = "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36";
+ try {
+ Document document = Jsoup.connect(url).userAgent(userAgent).get();
+ Elements metaOgTitle = document.select("meta[property=og:title]");
+ if (metaOgTitle != null) {
+ title = metaOgTitle.attr("content");
+ } else {
+ title = document.title();
+ }
+ Elements metaOgDescription = document.select("meta[property=og:description]");
+ if (metaOgDescription != null) {
+ description = metaOgDescription.attr("content");
+ } else {
+ description = "";
+ }
+ Elements metaOgImage = document.select("meta[property=og:image]");
+ if (metaOgImage != null) {
+ image = metaOgImage.attr("content");
+ }
+ } catch (IOException | IndexOutOfBoundsException e) {
+ error = true;
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ listener.onRetrieveMetaData(error, image, title, description);
+ }
+
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveNotificationsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveNotificationsAsyncTask.java
index e59bb8417..6b7a8b7c6 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveNotificationsAsyncTask.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveNotificationsAsyncTask.java
@@ -15,14 +15,9 @@
package fr.gouv.etalab.mastodon.asynctasks;
import android.content.Context;
-import android.content.SharedPreferences;
import android.os.AsyncTask;
-
-import java.util.Date;
-
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.APIResponse;
-import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
@@ -51,20 +46,8 @@ public class RetrieveNotificationsAsyncTask extends AsyncTask
this.userId = userId;
this.token = token;
this.refreshData = true;
- updateTimeRefresh();
}
- public RetrieveNotificationsAsyncTask(Context context, String instance, String token, String max_id, String acct, String userId, boolean refreshData, OnRetrieveNotificationsInterface onRetrieveNotificationsInterface){
- this.context = context;
- this.max_id = max_id;
- this.listener = onRetrieveNotificationsInterface;
- this.acct = acct;
- this.instance = instance;
- this.userId = userId;
- this.token = token;
- this.refreshData = refreshData;
- updateTimeRefresh();
- }
@Override
protected Void doInBackground(Void... params) {
@@ -82,10 +65,4 @@ public class RetrieveNotificationsAsyncTask extends AsyncTask
listener.onRetrieveNotifications(apiResponse, acct, userId, refreshData);
}
- private void updateTimeRefresh(){
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_BUBBLE_REFRESH_NOTIF+ userId,Helper.dateToString(context, new Date()));
- editor.apply();
- }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRelationshipAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRelationshipAsyncTask.java
index 8347f0df4..84c62d9ba 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRelationshipAsyncTask.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRelationshipAsyncTask.java
@@ -16,9 +16,11 @@ package fr.gouv.etalab.mastodon.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
+import android.util.Log;
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
+import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRelationshipInterface;
/**
@@ -42,7 +44,6 @@ public class RetrieveRelationshipAsyncTask extends AsyncTask {
@Override
protected Void doInBackground(Void... params) {
-
api = new API(context);
relationship = api.getRelationship(accountId);
return null;
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java
index 94141cbd1..f8b2ef714 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveRemoteAccountsAsyncTask.java
@@ -15,10 +15,11 @@
package fr.gouv.etalab.mastodon.asynctasks;
import android.os.AsyncTask;
+
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
-import java.io.IOException;
+
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRemoteAccountInterface;
@@ -32,7 +33,7 @@ public class RetrieveRemoteAccountsAsyncTask extends AsyncTask
private OnRetrieveRemoteAccountInterface listener;
private String url;
private String avatar, name, username, bio;
- private int statusCount, followingCount, followersCount;
+ private String statusCount, followingCount, followersCount;
private boolean islocked;
private boolean error = false;
private String instance;
@@ -56,23 +57,24 @@ public class RetrieveRemoteAccountsAsyncTask extends AsyncTask
Elements nameElement = document.getElementsByClass("name");
name = nameElement.get(0).getElementsByClass("p-name").get(0).html();
username = nameElement.get(0).getElementsByTag("span").get(1).html();
- islocked = nameElement.get(0).getElementsByClass("fa-lock") != null;
+ islocked = (nameElement.get(0).getElementsByClass("fa-lock") != null && nameElement.get(0).getElementsByClass("fa-lock").size() > 0);
Elements bioElement = document.getElementsByClass("bio");
bio = bioElement.get(0).html();
Elements countElement = document.getElementsByClass("counter-number");
- statusCount = Integer.parseInt(countElement.get(0).html());
- followingCount = Integer.parseInt(countElement.get(1).html());
- followersCount = Integer.parseInt(countElement.get(2).html());
- } catch (IOException | IndexOutOfBoundsException e) {
+ statusCount = countElement.get(0).html();
+ followingCount = countElement.get(1).html();
+ followersCount = countElement.get(2).html();
+ } catch (Exception e) {
error = true;
+ e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
- listener.onRetrieveRemoteAccount(error, name, username, islocked, avatar, bio, statusCount, followingCount, followersCount);
+ listener.onRetrieveRemoteAccount(error, name, username, instance, islocked, avatar, bio, statusCount, followingCount, followersCount);
}
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java
index e343d011c..d0cf7203c 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveScheduledTootsAsyncTask.java
@@ -18,6 +18,7 @@ import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.SystemClock;
+import android.util.Log;
import com.evernote.android.job.JobManager;
import com.evernote.android.job.JobRequest;
@@ -68,6 +69,7 @@ public class RetrieveScheduledTootsAsyncTask extends AsyncTask
}else{
jobIds = new int[]{};
}
+
if( storedStatuses != null && storedStatuses.size() > 0 ){
for(StoredStatus ss: storedStatuses){
if (!Helper.isJobPresent(jobIds, ss.getJobId())){
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java
index baa7b2d60..b16de7a9a 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java
@@ -188,12 +188,12 @@ public class API {
get("/accounts/verify_credentials", null, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- account = parseAccountResponse(response);
+ account = parseAccountResponse(context, response);
}
@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
try {
- account = parseAccountResponse(response.getJSONObject(0));
+ account = parseAccountResponse(context, response.getJSONObject(0));
} catch (JSONException e) {
e.printStackTrace();
}
@@ -217,12 +217,12 @@ public class API {
get(String.format("/accounts/%s",accountId), null, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- account = parseAccountResponse(response);
+ account = parseAccountResponse(context, response);
}
@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
try {
- account = parseAccountResponse(response.getJSONObject(0));
+ account = parseAccountResponse(context, response.getJSONObject(0));
} catch (JSONException e) {
e.printStackTrace();
}
@@ -330,7 +330,7 @@ public class API {
get(String.format("/accounts/%s/statuses", accountId), params, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Status status = parseStatuses(response);
+ Status status = parseStatuses(context, response);
statuses.add(status);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -365,7 +365,7 @@ public class API {
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
- Status status = parseStatuses(response);
+ Status status = parseStatuses(context, response);
statuses.add(status);
}
@Override
@@ -445,7 +445,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Status status = parseStatuses(response);
+ Status status = parseStatuses(context, response);
statuses.add(status);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -500,7 +500,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Status status = parseStatuses(response);
+ Status status = parseStatuses(context, response);
statuses.add(status);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -557,7 +557,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Status status = parseStatuses(response);
+ Status status = parseStatuses(context, response);
statuses.add(status);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -641,7 +641,7 @@ public class API {
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
- Account account = parseAccountResponse(response);
+ Account account = parseAccountResponse(context, response);
accounts.add(account);
}
@Override
@@ -692,7 +692,7 @@ public class API {
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
- Account account = parseAccountResponse(response);
+ Account account = parseAccountResponse(context, response);
accounts.add(account);
}
@Override
@@ -741,7 +741,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Status status = parseStatuses(response);
+ Status status = parseStatuses(context, response);
statuses.add(status);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -945,7 +945,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Status statusreturned = parseStatuses(response);
+ Status statusreturned = parseStatuses(context, response);
statuses.add(statusreturned);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -1041,7 +1041,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- Notification notification = parseNotificationResponse(response);
+ Notification notification = parseNotificationResponse(context, response);
notifications.add(notification);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -1118,37 +1118,6 @@ public class API {
return results;
}
- /**
- * Retrieves Developer account when searching (ie: via @...) *synchronously*
- *
- * @return APIResponse
- */
- public APIResponse searchDeveloper() {
- RequestParams params = new RequestParams();
- params.add("q", "tschneider");
- get("/accounts/search", params, new JsonHttpResponseHandler() {
- @Override
- public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- accounts = new ArrayList<>();
- account = parseAccountResponse(response);
- accounts.add(account);
- apiResponse.setSince_id(findSinceId(headers));
- apiResponse.setMax_id(findMaxId(headers));
- }
- @Override
- public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
- accounts = parseDeveloperResponse(response);
- apiResponse.setSince_id(findSinceId(headers));
- apiResponse.setMax_id(findMaxId(headers));
- }
- @Override
- public void onFailure(int statusCode, Header[] headers, Throwable error, JSONObject response){
- setError(statusCode, error);
- }
- });
- apiResponse.setAccounts(accounts);
- return apiResponse;
- }
/**
* Retrieves Accounts when searching (ie: via @...) *synchronously*
*
@@ -1170,7 +1139,7 @@ public class API {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
accounts = new ArrayList<>();
- account = parseAccountResponse(response);
+ account = parseAccountResponse(context, response);
accounts.add(account);
apiResponse.setSince_id(findSinceId(headers));
apiResponse.setMax_id(findMaxId(headers));
@@ -1236,7 +1205,7 @@ public class API {
while (i < jsonArray.length() ){
JSONObject resobj = jsonArray.getJSONObject(i);
- Status status = parseStatuses(resobj);
+ Status status = parseStatuses(context, resobj);
i++;
statuses.add(status);
}
@@ -1253,7 +1222,7 @@ public class API {
* @return Status
*/
@SuppressWarnings("InfiniteRecursion")
- private Status parseStatuses(JSONObject resobj){
+ public static Status parseStatuses(Context context, JSONObject resobj){
Status status = new Status();
try {
status.setId(resobj.get("id").toString());
@@ -1315,14 +1284,14 @@ public class API {
}
status.setTags(tags);
- status.setAccount(parseAccountResponse(resobj.getJSONObject("account")));
+ status.setAccount(parseAccountResponse(context, resobj.getJSONObject("account")));
status.setContent(resobj.get("content").toString());
status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString()));
status.setReblogs_count(Integer.valueOf(resobj.get("reblogs_count").toString()));
status.setReblogged(Boolean.valueOf(resobj.get("reblogged").toString()));
status.setFavourited(Boolean.valueOf(resobj.get("favourited").toString()));
try{
- status.setReblog(parseStatuses(resobj.getJSONObject("reblog")));
+ status.setReblog(parseStatuses(context, resobj.getJSONObject("reblog")));
}catch (Exception ignored){}
} catch (JSONException e) {
e.printStackTrace();
@@ -1355,7 +1324,7 @@ public class API {
* @param resobj JSONObject
* @return Account
*/
- private Account parseAccountResponse(JSONObject resobj){
+ private static Account parseAccountResponse(Context context, JSONObject resobj){
Account account = new Account();
try {
@@ -1392,7 +1361,7 @@ public class API {
int i = 0;
while (i < jsonArray.length() ) {
JSONObject resobj = jsonArray.getJSONObject(i);
- Account account = parseAccountResponse(resobj);
+ Account account = parseAccountResponse(context, resobj);
accounts.add(account);
i++;
}
@@ -1416,7 +1385,7 @@ public class API {
Account account = null;
while (i < jsonArray.length() ) {
JSONObject resobj = jsonArray.getJSONObject(i);
- account = parseAccountResponse(resobj);
+ account = parseAccountResponse(context, resobj);
if( account.getAcct().contains(Helper.DEVELOPER_INSTANCE))
accounts.add(account);
i++;
@@ -1500,16 +1469,16 @@ public class API {
* @param resobj JSONObject
* @return Account
*/
- private Notification parseNotificationResponse(JSONObject resobj){
+ public static Notification parseNotificationResponse(Context context, JSONObject resobj){
Notification notification = new Notification();
try {
notification.setId(resobj.get("id").toString());
notification.setType(resobj.get("type").toString());
notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString()));
- notification.setAccount(parseAccountResponse(resobj.getJSONObject("account")));
+ notification.setAccount(parseAccountResponse(context, resobj.getJSONObject("account")));
try{
- notification.setStatus(parseStatuses(resobj.getJSONObject("status")));
+ notification.setStatus(parseStatuses(context, resobj.getJSONObject("status")));
}catch (Exception ignored){}
notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString()));
} catch (JSONException e) {
@@ -1531,7 +1500,7 @@ public class API {
while (i < jsonArray.length() ) {
JSONObject resobj = jsonArray.getJSONObject(i);
- Notification notification = parseNotificationResponse(resobj);
+ Notification notification = parseNotificationResponse(context, resobj);
notifications.add(notification);
i++;
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java
index de8cdadb6..a587a3e63 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Account.java
@@ -35,6 +35,9 @@ public class Account implements Parcelable {
private int followers_count;
private int following_count;
private int statuses_count;
+ private String followers_count_str;
+ private String following_count_str;
+ private String statuses_count_str;
private String note;
private String url;
private String avatar;
@@ -43,6 +46,8 @@ public class Account implements Parcelable {
private String header_static;
private String token;
private String instance;
+ private boolean isFollowing;
+ private boolean isRemote;
protected Account(Parcel in) {
id = in.readString();
@@ -237,4 +242,44 @@ public class Account implements Parcelable {
dest.writeString(token);
dest.writeString(instance);
}
+
+ public boolean isFollowing() {
+ return isFollowing;
+ }
+
+ public void setFollowing(boolean following) {
+ isFollowing = following;
+ }
+
+ public boolean isRemote() {
+ return isRemote;
+ }
+
+ public void setRemote(boolean remote) {
+ isRemote = remote;
+ }
+
+ public String getFollowers_count_str() {
+ return followers_count_str;
+ }
+
+ public void setFollowers_count_str(String followers_count_str) {
+ this.followers_count_str = followers_count_str;
+ }
+
+ public String getFollowing_count_str() {
+ return following_count_str;
+ }
+
+ public void setFollowing_count_str(String following_count_str) {
+ this.following_count_str = following_count_str;
+ }
+
+ public String getStatuses_count_str() {
+ return statuses_count_str;
+ }
+
+ public void setStatuses_count_str(String statuses_count_str) {
+ this.statuses_count_str = statuses_count_str;
+ }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java
index a8cc8f74d..c415088dc 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Notification.java
@@ -15,13 +15,16 @@
package fr.gouv.etalab.mastodon.client.Entities;
+import android.os.Parcel;
+import android.os.Parcelable;
+
import java.util.Date;
/**
* Created by Thomas on 23/04/2017.
*/
-public class Notification {
+public class Notification implements Parcelable {
private String id;
private String type;
@@ -29,6 +32,27 @@ public class Notification {
private Account account;
private Status status;
+ protected Notification(Parcel in) {
+ id = in.readString();
+ type = in.readString();
+ account = in.readParcelable(Account.class.getClassLoader());
+ status = in.readParcelable(Status.class.getClassLoader());
+ }
+
+ public Notification(){};
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public Notification createFromParcel(Parcel in) {
+ return new Notification(in);
+ }
+
+ @Override
+ public Notification[] newArray(int size) {
+ return new Notification[size];
+ }
+ };
+
public String getId() {
return id;
}
@@ -68,4 +92,17 @@ public class Notification {
public void setStatus(Status status) {
this.status = status;
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(id);
+ dest.writeString(type);
+ dest.writeParcelable(account, flags);
+ dest.writeParcelable(status, flags);
+ }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java
index 4fd0cc909..1901c5ef7 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/Entities/Status.java
@@ -55,6 +55,7 @@ public class Status implements Parcelable {
private String language;
private boolean isTranslated = false;
private boolean isTranslationShown = false;
+ private boolean isNew = false;
protected Status(Parcel in) {
id = in.readString();
@@ -79,6 +80,7 @@ public class Status implements Parcelable {
spoilerShown = in.readByte() != 0;
isTranslated = in.readByte() != 0;
isTranslationShown = in.readByte() != 0;
+ isNew = in.readByte() != 0;
}
public Status(){}
@@ -294,6 +296,7 @@ public class Status implements Parcelable {
dest.writeByte((byte) (spoilerShown ? 1 : 0));
dest.writeByte((byte) (isTranslated ? 1 : 0));
dest.writeByte((byte) (isTranslationShown ? 1 : 0));
+ dest.writeByte((byte) (isNew ? 1 : 0));
}
public boolean isSpoilerShown() {
@@ -343,4 +346,12 @@ public class Status implements Parcelable {
public void setReplies(List replies) {
this.replies = replies;
}
+
+ public boolean isNew() {
+ return isNew;
+ }
+
+ public void setNew(boolean aNew) {
+ isNew = aNew;
+ }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/TLSSocketFactory.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/TLSSocketFactory.java
new file mode 100644
index 000000000..6cd21710f
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/TLSSocketFactory.java
@@ -0,0 +1,94 @@
+package fr.gouv.etalab.mastodon.client;
+
+import android.annotation.SuppressLint;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Created by Thomas on 29/08/2017.
+ *
+ */
+
+public class TLSSocketFactory extends SSLSocketFactory {
+
+ private final SSLContext sslContext = SSLContext.getInstance("TLS");
+
+ public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
+
+ X509TrustManager tm = new X509TrustManager() {
+ @SuppressLint("TrustAllX509TrustManager")
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @SuppressLint("TrustAllX509TrustManager")
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ };
+ sslContext.init(null, new TrustManager[]{tm}, null);
+
+ }
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return sslContext.getSocketFactory().getDefaultCipherSuites();
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return sslContext.getSocketFactory().getSupportedCipherSuites();
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return enableTLSOnSocket(sslContext.getSocketFactory().createSocket());
+ }
+
+ @Override
+ public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
+ return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(s, host, port, autoClose));
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
+ return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(host, port));
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
+ return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(host, port, localHost, localPort));
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(host, port));
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(address, port, localAddress, localPort));
+ }
+
+ private Socket enableTLSOnSocket(Socket socket) {
+ if(socket != null && (socket instanceof SSLSocket)) {
+ ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
+ }
+ return socket;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchDevAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchDevAdapter.java
new file mode 100644
index 000000000..993a445b4
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchDevAdapter.java
@@ -0,0 +1,213 @@
+package fr.gouv.etalab.mastodon.drawers;
+/* Copyright 2017 Thomas Schneider
+ *
+ * This file is a part of Mastalab
+ *
+ * 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.
+ *
+ * Mastalab 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 Mastalab; if not,
+ * see . */
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.content.ContextCompat;
+import android.text.Html;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+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.display.SimpleBitmapDisplayer;
+
+import java.io.File;
+import java.util.List;
+
+import fr.gouv.etalab.mastodon.activities.ShowAccountActivity;
+import fr.gouv.etalab.mastodon.asynctasks.PostActionAsyncTask;
+import fr.gouv.etalab.mastodon.client.API;
+import fr.gouv.etalab.mastodon.client.Entities.Account;
+import fr.gouv.etalab.mastodon.client.Entities.Error;
+import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
+import fr.gouv.etalab.mastodon.helper.Helper;
+import fr.gouv.etalab.mastodon.interfaces.OnPostActionInterface;
+import mastodon.etalab.gouv.fr.mastodon.R;
+
+import static fr.gouv.etalab.mastodon.helper.Helper.changeDrawableColor;
+
+
+/**
+ * Created by Thomas on 03/09/2017.
+ * Adapter for accounts from web
+ */
+public class AccountSearchDevAdapter extends BaseAdapter implements OnPostActionInterface {
+
+ private List accounts;
+ private LayoutInflater layoutInflater;
+ private Context context;
+ private ViewHolder holder;
+
+ public AccountSearchDevAdapter(Context context, List accounts){
+ this.context = context;
+ this.accounts = accounts;
+ layoutInflater = LayoutInflater.from(context);
+ }
+
+
+
+ @Override
+ public int getCount() {
+ return accounts.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return accounts.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+
+ @Override
+ public View getView(final int position, View convertView, ViewGroup parent) {
+
+ ImageLoader imageLoader = ImageLoader.getInstance();
+ File cacheDir = new File(context.getCacheDir(), context.getString(R.string.app_name));
+ ImageLoaderConfiguration configImg = new ImageLoaderConfiguration.Builder(context)
+ .imageDownloader(new PatchBaseImageDownloader(context))
+ .threadPoolSize(5)
+ .threadPriority(Thread.MIN_PRIORITY + 3)
+ .denyCacheImageMultipleSizesInMemory()
+ .diskCache(new UnlimitedDiskCache(cacheDir))
+ .build();
+ if( !imageLoader.isInited())
+ imageLoader.init(configImg);
+ DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
+ .cacheOnDisk(true).resetViewBeforeLoading(true).build();
+ final Account account = accounts.get(position);
+
+ if (convertView == null) {
+ convertView = layoutInflater.inflate(R.layout.drawer_account_search_dev, parent, false);
+ holder = new ViewHolder();
+ holder.account_pp = (ImageView) convertView.findViewById(R.id.account_pp);
+ holder.account_dn = (TextView) convertView.findViewById(R.id.account_dn);
+ holder.account_un = (TextView) convertView.findViewById(R.id.account_un);
+ holder.account_follow = (FloatingActionButton) convertView.findViewById(R.id.account_follow);
+ holder.acccount_container = (LinearLayout) convertView.findViewById(R.id.acccount_container);
+ convertView.setTag(holder);
+ } else {
+ holder = (ViewHolder) convertView.getTag();
+ }
+ //Redraws icon for locked accounts
+ final float scale = context.getResources().getDisplayMetrics().density;
+ if( account != null && account.isLocked()){
+ Drawable img = ContextCompat.getDrawable(context, R.drawable.ic_action_lock_closed);
+ img.setBounds(0,0,(int) (20 * scale + 0.5f),(int) (20 * scale + 0.5f));
+ holder.account_dn.setCompoundDrawables( null, null, img, null);
+ }else{
+ holder.account_dn.setCompoundDrawables( null, null, null, null);
+ }
+
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ holder.account_dn.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getDisplay_name(), true), Html.FROM_HTML_MODE_LEGACY));
+ holder.account_un.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getUsername(), true), Html.FROM_HTML_MODE_LEGACY));
+ }else {
+ //noinspection deprecation
+ holder.account_dn.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getDisplay_name(), true)));
+ holder.account_un.setText(Html.fromHtml(Helper.shortnameToUnicode(account.getUsername(), true)));
+ }
+ changeDrawableColor(context, R.drawable.ic_action_lock_closed,R.color.mastodonC4);
+ //Profile picture
+ imageLoader.displayImage(account.getAvatar(), holder.account_pp, options);
+
+ if( account.isFollowing()){
+ holder.account_follow.setVisibility(View.GONE);
+ }else{
+ holder.account_follow.setVisibility(View.VISIBLE);
+ }
+
+ if( account.isRemote()) {
+ holder.account_follow.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ holder.account_follow.setEnabled(false);
+ new PostActionAsyncTask(context, API.StatusAction.REMOTE_FOLLOW, account.getAcct(), AccountSearchDevAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ }else {
+ holder.account_follow.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ holder.account_follow.setEnabled(false);
+ new PostActionAsyncTask(context, API.StatusAction.FOLLOW, account.getId(), AccountSearchDevAdapter.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+ holder.acccount_container.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(context, ShowAccountActivity.class);
+ Bundle b = new Bundle();
+ b.putString("accountId", account.getId());
+ intent.putExtras(b);
+ context.startActivity(intent);
+ }
+ });
+ }
+
+ return convertView;
+ }
+
+ @Override
+ public void onPostAction(int statusCode, API.StatusAction statusAction, String userId, Error error) {
+ if( error != null){
+ final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ boolean show_error_messages = sharedpreferences.getBoolean(Helper.SET_SHOW_ERROR_MESSAGES, true);
+ if( show_error_messages)
+ Toast.makeText(context, error.getError(),Toast.LENGTH_LONG).show();
+ holder.account_follow.setEnabled(true);
+ return;
+ }
+ for( Account account: accounts){
+ if(account.getId().equals(userId)) {
+ account.setFollowing(true);
+ notifyDataSetChanged();
+ break;
+ }
+ }
+ holder.account_follow.setVisibility(View.GONE);
+ Toast.makeText(context, R.string.toast_follow, Toast.LENGTH_LONG).show();
+ }
+
+
+ private class ViewHolder {
+ LinearLayout acccount_container;
+ ImageView account_pp;
+ TextView account_dn;
+ TextView account_un;
+ FloatingActionButton account_follow;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchWebAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchWebAdapter.java
index d29923a48..44decec34 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchWebAdapter.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/AccountSearchWebAdapter.java
@@ -143,9 +143,9 @@ public class AccountSearchWebAdapter extends BaseAdapter implements OnPostAction
}
changeDrawableColor(context, R.drawable.ic_action_lock_closed,R.color.mastodonC4);
holder.account_ds.setAutoLinkMask(Linkify.WEB_URLS);
- holder.account_sc.setText(String.valueOf(account.getStatuses_count()));
- holder.account_fgc.setText(String.valueOf(account.getFollowing_count()));
- holder.account_frc.setText(String.valueOf(account.getFollowers_count()));
+ holder.account_sc.setText(String.valueOf(account.getStatuses_count_str()));
+ holder.account_fgc.setText(String.valueOf(account.getFollowing_count_str()));
+ holder.account_frc.setText(String.valueOf(account.getFollowers_count_str()));
//Profile picture
imageLoader.displayImage(account.getAvatar(), holder.account_pp, options);
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java
index aa91b19b1..7c41982b2 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/NotificationsListAdapter.java
@@ -88,7 +88,7 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
private NotificationsListAdapter notificationsListAdapter;
private int behaviorWithAttachments;
private boolean isOnWifi;
- private String targetedId;
+
public NotificationsListAdapter(Context context, boolean isOnWifi, int behaviorWithAttachments, List notifications){
this.context = context;
@@ -170,6 +170,8 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
final float scale = context.getResources().getDisplayMetrics().density;
String type = notification.getType();
String typeString = "";
+ int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
+ Drawable imgH = null;
switch (type){
case "mention":
holder.status_action_container.setVisibility(View.VISIBLE);
@@ -177,6 +179,12 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_mention));
else
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_mention));
+ if( theme == Helper.THEME_DARK){
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_dark_1));
+ }else {
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_light_1));
+ }
+ imgH = null;
break;
case "reblog":
holder.status_action_container.setVisibility(View.GONE);
@@ -184,6 +192,12 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_reblog));
else
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_reblog));
+ if( theme == Helper.THEME_DARK){
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_dark_2));
+ }else {
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_light_2));
+ }
+ imgH = ContextCompat.getDrawable(context, R.drawable.ic_retweet_notif_header);
break;
case "favourite":
holder.status_action_container.setVisibility(View.GONE);
@@ -191,6 +205,12 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_favourite));
else
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_favourite));
+ if( theme == Helper.THEME_DARK){
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_dark_3));
+ }else {
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_light_3));
+ }
+ imgH = ContextCompat.getDrawable(context, R.drawable.ic_fav_notif_header);
break;
case "follow":
holder.status_action_container.setVisibility(View.GONE);
@@ -198,10 +218,24 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_follow));
else
typeString = String.format("@%s %s", notification.getAccount().getAcct(),context.getString(R.string.notif_follow));
+ if( theme == Helper.THEME_DARK){
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_dark_4));
+ }else {
+ holder.card_status_container.setCardBackgroundColor(ContextCompat.getColor(context, R.color.notif_light_4));
+ }
+ imgH = ContextCompat.getDrawable(context, R.drawable.ic_follow_notif_header);
break;
}
-
+ changeDrawableColor(context, R.drawable.ic_retweet_notif_header,R.color.mastodonC4);
+ changeDrawableColor(context, R.drawable.ic_fav_notif_header,R.color.mastodonC4);
+ changeDrawableColor(context, R.drawable.ic_follow_notif_header,R.color.mastodonC4);
holder.notification_type.setText(typeString);
+ if( imgH != null) {
+ holder.notification_type.setCompoundDrawablePadding((int)Helper.convertDpToPixel(5, context));
+ imgH.setBounds(0, 0, (int) (20 * iconSizePercent / 100 * scale + 0.5f), (int) (20 * iconSizePercent / 100 * scale + 0.5f));
+ }
+ holder.notification_type.setCompoundDrawables( imgH, null, null, null);
+
holder.status_privacy.getLayoutParams().height = (int) Helper.convertDpToPixel((20*iconSizePercent/100), context);
holder.status_privacy.getLayoutParams().width = (int) Helper.convertDpToPixel((20*iconSizePercent/100), context);
holder.status_reply.getLayoutParams().height = (int) Helper.convertDpToPixel((20*iconSizePercent/100), context);
@@ -214,7 +248,6 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
//Manages theme for icon colors
- int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if( theme == Helper.THEME_DARK){
changeDrawableColor(context, R.drawable.ic_reply,R.color.dark_text);
changeDrawableColor(context, R.drawable.ic_action_more,R.color.dark_text);
@@ -260,8 +293,13 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
}else{
holder.notification_account_username.setCompoundDrawables( null, null, null, null);
}
+ String content = status.getContent();
+ content = content.replaceAll("
","
");
+ content = content.replaceAll("","");
+ if( content.endsWith("
") )
+ content = content.substring(0,content.length() -10);
- SpannableString spannableString = Helper.clickableElements(context, status.getContent(),
+ SpannableString spannableString = Helper.clickableElements(context, content,
status.getReblog() != null?status.getReblog().getMentions():status.getMentions(), true);
holder.notification_status_content.setText(spannableString, TextView.BufferType.SPANNABLE);
holder.notification_status_content.setMovementMethod(null);
@@ -402,7 +440,7 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
@Override
public void onClick(View v) {
- boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true);
+ boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION_FAV, false);
if( confirmation )
displayConfirmationDialog(FAVOURITE,status);
else
@@ -522,7 +560,7 @@ public class NotificationsListAdapter extends BaseAdapter implements OnPostActio
*/
private void displayConfirmationNotificationDialog(final Notification notification){
final ArrayList seletedItems = new ArrayList();
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle(R.string.delete_notification_ask)
.setMultiChoiceItems(new String[]{context.getString(R.string.delete_notification_ask_all)}, null, new DialogInterface.OnMultiChoiceClickListener() {
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java
index 6774963d2..57fb935bb 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/drawers/StatusListAdapter.java
@@ -14,6 +14,7 @@ package fr.gouv.etalab.mastodon.drawers;
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
* see . */
+import android.graphics.Paint;
import android.support.v7.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
@@ -90,6 +91,7 @@ import mastodon.etalab.gouv.fr.mastodon.R;
import static fr.gouv.etalab.mastodon.activities.MainActivity.currentLocale;
import static fr.gouv.etalab.mastodon.helper.Helper.changeDrawableColor;
+import static fr.gouv.etalab.mastodon.helper.Helper.shortnameToUnicode;
/**
@@ -197,7 +199,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
holder.status_prev4_container = (RelativeLayout) convertView.findViewById(R.id.status_prev4_container);
holder.status_reply = (ImageView) convertView.findViewById(R.id.status_reply);
holder.status_privacy = (ImageView) convertView.findViewById(R.id.status_privacy);
- holder.status_translate = (Button) convertView.findViewById(R.id.status_translate);
+ holder.status_translate = (TextView) convertView.findViewById(R.id.status_translate);
holder.status_content_translated_container = (LinearLayout) convertView.findViewById(R.id.status_content_translated_container);
holder.main_container = (LinearLayout) convertView.findViewById(R.id.main_container);
holder.status_spoiler_container = (LinearLayout) convertView.findViewById(R.id.status_spoiler_container);
@@ -205,9 +207,11 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
holder.status_spoiler = (TextView) convertView.findViewById(R.id.status_spoiler);
holder.status_spoiler_button = (Button) convertView.findViewById(R.id.status_spoiler_button);
holder.yandex_translate = (TextView) convertView.findViewById(R.id.yandex_translate);
+ holder.google_translate = (TextView) convertView.findViewById(R.id.google_translate);
holder.status_replies = (LinearLayout) convertView.findViewById(R.id.status_replies);
holder.status_replies_profile_pictures = (LinearLayout) convertView.findViewById(R.id.status_replies_profile_pictures);
holder.status_replies_text = (TextView) convertView.findViewById(R.id.status_replies_text);
+ holder.new_element = (ImageView) convertView.findViewById(R.id.new_element);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
@@ -217,7 +221,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
//Display a preview for accounts that have replied *if enabled and only for home timeline*
if( type == RetrieveFeedsAsyncTask.Type.HOME ) {
- boolean showPreview = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, true);
+ boolean showPreview = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, false);
if( showPreview){
boolean showPreviewPP = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES_PP, true);
if( status.getReplies() == null){
@@ -259,6 +263,11 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
}
}
+ changeDrawableColor(context, R.drawable.ic_fiber_new,R.color.mastodonC4);
+ if( status.isNew())
+ holder.new_element.setVisibility(View.VISIBLE);
+ else
+ holder.new_element.setVisibility(View.GONE);
int iconSizePercent = sharedpreferences.getInt(Helper.SET_ICON_SIZE, 130);
int textSizePercent = sharedpreferences.getInt(Helper.SET_TEXT_SIZE, 110);
@@ -301,6 +310,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
statusListAdapter.notifyDataSetChanged();
}
});
+ holder.status_translate.setPaintFlags(holder.status_translate.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
if( currentLocale != null && status.getLanguage() != null && !status.getLanguage().trim().equals(currentLocale) && !status.getLanguage().trim().equals("null")){
if (translator != Helper.TRANS_NONE)
holder.status_translate.setVisibility(View.VISIBLE);
@@ -310,10 +320,25 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
holder.status_translate.setVisibility(View.GONE);
}
- if( translator == Helper.TRANS_YANDEX)
- holder.yandex_translate.setVisibility(View.VISIBLE);
- else
- holder.yandex_translate.setVisibility(View.GONE);
+ switch (translator)
+ {
+ case Helper.TRANS_NONE:
+ holder.yandex_translate.setVisibility(View.GONE);
+ holder.google_translate.setVisibility(View.GONE);
+ break;
+ case Helper.TRANS_YANDEX:
+ holder.google_translate.setVisibility(View.GONE);
+ holder.yandex_translate.setVisibility(View.VISIBLE);
+ break;
+ case Helper.TRANS_GOOGLE:
+ holder.yandex_translate.setVisibility(View.GONE);
+ holder.google_translate.setVisibility(View.VISIBLE);
+ break;
+ default:
+ holder.yandex_translate.setVisibility(View.GONE);
+ holder.google_translate.setVisibility(View.GONE);
+ break;
+ }
holder.status_translate.setOnClickListener(new View.OnClickListener() {
@Override
@@ -340,6 +365,11 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
while (matcher.find()){
String key = "__u" + String.valueOf(i) + "__";
String value = matcher.group(0);
+ int end = matcher.end();
+ if (spannableString.charAt(end) == '/') {
+ text = spannableString.toString().substring(0, end).
+ concat(spannableString.toString().substring(end+1, spannableString.length()));
+ }
if( value != null) {
urlConversion.put(key, value);
text = text.replace(value, key);
@@ -361,9 +391,13 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
}
if (translator == Helper.TRANS_YANDEX)
new YandexQuery(StatusListAdapter.this).getYandexTextview(position, text, currentLocale);
- else if( translator == Helper.TRANS_GOOGLE)
- new GoogleTranslateQuery(StatusListAdapter.this).getGoogleTextview(position, text, currentLocale);
+ else if( translator == Helper.TRANS_GOOGLE) {
+ while( text.charAt(text.length() -1) == '\n' && text.length() > 0)
+ text = text.substring(0, text.length() -1);
+ text += ".";
+ new GoogleTranslateQuery(StatusListAdapter.this).getGoogleTextview(position, text.trim(), currentLocale);
+ }
}else {
status.setTranslationShown(!status.isTranslationShown());
statusListAdapter.notifyDataSetChanged();
@@ -381,6 +415,13 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
context.startActivity(browserIntent);
}
});
+ holder.google_translate.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://translate.google.com/"));
+ context.startActivity(browserIntent);
+ }
+ });
//Toot was translated and user asked to see it
if( status.isTranslationShown()){
holder.status_content.setVisibility(View.GONE);
@@ -480,7 +521,10 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
}
}
- final String content, displayName, username, ppurl;
+ String content;
+ final String displayName;
+ final String username;
+ final String ppurl;
if( status.getReblog() != null){
content = status.getReblog().getContent();
displayName = Helper.shortnameToUnicode(status.getReblog().getAccount().getDisplay_name(), true);
@@ -546,7 +590,10 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
});
holder.status_content_translated.setMovementMethod(LinkMovementMethod.getInstance());
}
-
+ content = content.replaceAll("
","
");
+ content = content.replaceAll("","");
+ if( content.endsWith("
") )
+ content = content.substring(0,content.length() -10);
final SpannableString spannableString = Helper.clickableElements(context,content,
status.getReblog() != null?status.getReblog().getMentions():status.getMentions(), true);
holder.status_content.setText(spannableString, TextView.BufferType.SPANNABLE);
@@ -712,7 +759,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
@Override
public void onClick(View v) {
- boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, true);
+ boolean confirmation = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION_FAV, false);
if( confirmation )
displayConfirmationDialog(FAVOURITE,status);
else
@@ -956,6 +1003,7 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
statuses.get(position).setContent_translated(aJsonString);
statusListAdapter.notifyDataSetChanged();
} catch (JSONException | UnsupportedEncodingException | IllegalArgumentException e) {
+ e.printStackTrace();
Toast.makeText(context, R.string.toast_error_translate, Toast.LENGTH_LONG).show();
}
}
@@ -965,6 +1013,16 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
JSONObject translationJson = new JSONObject(text);
JSONArray aJsonArray = translationJson.getJSONArray("text");
String aJsonString = aJsonArray.get(0).toString();
+
+ /* The one instance where I've seen this happen,
+ the special tag was originally a hashtag ("__t1__"),
+ that Yandex decided to change to a "__q1 - __".
+ */
+ aJsonString = aJsonString.replaceAll("__q(\\d+) - __", "__t$1__");
+
+ // Noticed this in the very same toot
+ aJsonString = aJsonString.replace("&", "&");
+
aJsonString = URLDecoder.decode(aJsonString, "UTF-8");
return aJsonString;
}
@@ -988,6 +1046,19 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
aJsonString = aJsonString.replace(" //","//");
aJsonString = aJsonString.replace(" www .","www.");
aJsonString = aJsonString.replace("www .","www.");
+
+ // This one might cause more trouble than it's worth
+ aJsonString = aJsonString.replaceAll("\\* \\.", "*.");
+
+ /*
+ Noticed that sometimes the special tags were getting messed up by Google,
+ might be other variants, only caught one so far.
+
+ But, pre-planning might save some time later...
+ */
+ aJsonString = aJsonString.replaceAll("__\\s?(u|t)\\s?(\\d+)\\s?__", "__$1$2__");
+ aJsonString = aJsonString.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
+ aJsonString = aJsonString.replaceAll("\\+", "%2B");
aJsonString = URLDecoder.decode(aJsonString, "UTF-8");
return aJsonString;
}
@@ -1026,16 +1097,19 @@ public class StatusListAdapter extends BaseAdapter implements OnPostActionInterf
RelativeLayout status_prev4_container;
ImageView status_reply;
ImageView status_privacy;
- Button status_translate;
+ TextView status_translate;
LinearLayout status_container2;
LinearLayout status_container3;
LinearLayout main_container;
TextView yandex_translate;
+ TextView google_translate;
LinearLayout status_replies;
LinearLayout status_replies_profile_pictures;
TextView status_replies_text;
LinearLayout loader_replies;
+
+ ImageView new_element;
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java
index afa16939d..3eb6b8f42 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java
@@ -31,13 +31,14 @@ import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import fr.gouv.etalab.mastodon.activities.MainActivity;
import fr.gouv.etalab.mastodon.client.APIResponse;
import fr.gouv.etalab.mastodon.client.Entities.Account;
+import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.drawers.NotificationsListAdapter;
+import fr.gouv.etalab.mastodon.drawers.StatusListAdapter;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
@@ -66,12 +67,9 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
private SwipeRefreshLayout swipeRefreshLayout;
private boolean swiped;
private ListView lv_notifications;
- private DisplayNotificationsFragment displayNotificationsFragment;
private TextView new_data;
- private String since_id;
public DisplayNotificationsFragment(){
- displayNotificationsFragment = this;
}
@Override
@@ -138,27 +136,28 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
new_data.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ notificationsTmp = Helper.getTempNotification(context, null);
if( notificationsTmp != null){
+ for(int i = notificationsTmp.size() -1 ; i >= 0 ; i--){
+ notifications.add(0,notificationsTmp.get(i));
+ }
boolean isOnWifi = Helper.isOnWIFI(context);
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
- notifications = new ArrayList<>();
- for(Notification notification: notificationsTmp){
- notifications.add(notification);
- }
- //The user clicked on the banner to refresh values so, the pointer is changed
- if( notificationsTmp.size() > 0 ) {
- SharedPreferences.Editor editor = sharedpreferences.edit();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_NOTIF + userId, notificationsTmp.get(0).getId());
- editor.apply();
- }
notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
lv_notifications.setAdapter(notificationsListAdapter);
+ if( notificationsTmp.size() > 0){
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, notificationsTmp.get(0).getId());
+ editor.apply();
+ }
if( notificationsTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
textviewNoAction.setVisibility(View.GONE);
}
new_data.setVisibility(View.GONE);
notificationsTmp = new ArrayList<>();
+ Helper.cacheNotificationsClear(context, null);
+ ((MainActivity) context).updateNotifCounter();
}
});
@@ -188,11 +187,42 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ //New data are available
+ notificationsTmp = Helper.getTempNotification(context, null);
+ if (getUserVisibleHint() && notificationsTmp != null && notificationsTmp.size() > 0 && notifications.size() > 0) {
+ ArrayList added = new ArrayList<>();
+ for(Notification notification : notifications){
+ added.add(notification.getId());
+ }
+ final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ boolean isOnWifi = Helper.isOnWIFI(context);
+ int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
+ for(int i = notificationsTmp.size() -1 ; i >= 0 ; i--){
+ if( !added.contains(notificationsTmp.get(i).getId())) {
+ this.notifications.add(0, notificationsTmp.get(i));
+ added.add(notificationsTmp.get(i).getId());
+ }
+ }
+ if( this.notifications.size() > 0 )
+ max_id = this.notifications.get(this.notifications.size()-1).getId();
+ notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
+ lv_notifications.setAdapter(notificationsListAdapter);
+ }
+ }
+
+ @Override
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ super.setUserVisibleHint(isVisibleToUser);
+ if( isVisibleToUser )
+ refresh();
+ }
+
@Override
public void onRetrieveNotifications(APIResponse apiResponse, String acct, String userId, boolean refreshData) {
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- //UserId will be null here, so it needs to be retrieved from shared preferences
- userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
mainLoader.setVisibility(View.GONE);
nextElementLoader.setVisibility(View.GONE);
if( apiResponse.getError() != null){
@@ -205,78 +235,34 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
return;
}
SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_BUBBLE_REFRESH_NOTIF+ userId,Helper.dateToString(context, new Date()));
- editor.apply();
- String bubble_max_id = sharedpreferences.getString(Helper.LAST_MAX_ID_BUBBLE_NOTIF + userId, null);
List notifications = apiResponse.getNotifications();
- since_id = apiResponse.getSince_id();
+ String since_id = apiResponse.getSince_id();
max_id = apiResponse.getMax_id();
//The initial call comes from a classic tab refresh
- if( refreshData ) {
- manageNotifications(notifications, max_id, since_id);
- //The current tab is displayed, so user is supposed to have seen the notifications
- if( since_id != null && displayNotificationsFragment.getUserVisibleHint()) {
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_NOTIF + userId, since_id);
- editor.apply();
- }else if(!displayNotificationsFragment.getUserVisibleHint()){
- //The refresh was done automatically, but the fragment was not displayed in viewpager
- //So the bubble counter will be displayed
- int countData = 0;
- //Retrieves new notification count
- if( bubble_max_id != null) {
- for (Notification nt : notifications) {
- if (nt.getId().trim().equals(bubble_max_id.trim()))
- break;
- countData++;
- }
- }
- ((MainActivity)context).updateNotifCounter(countData);
- }
- }else { //Here, new values have been retrieved on the onResume call (forced mode)
- int countData = 0;
- if( bubble_max_id != null) {
- for (Notification nt : notifications) {
- if (nt.getId().trim().equals(bubble_max_id.trim()))
- break;
- countData++;
- }
- }
- if( notifications != null && notifications.size() > 0 && countData > 0) {
- max_id = null;
- firstLoad = true;
- notificationsTmp = new ArrayList<>();
- for (Notification tmpNotification : notifications) {
- this.notificationsTmp.add(tmpNotification);
- }
- //New notifications will be counted
- //The fragment is not displayed, so the bubble counter should be shown
- if (!displayNotificationsFragment.getUserVisibleHint()) {
- ((MainActivity) context).updateNotifCounter(countData);
- } else { //The current fragment is visible, but for avoiding to populate with new values
- // a message will be displayed at the bottom requiring a click to display these new values
- new_data.setVisibility(View.VISIBLE);
- }
- }
- }
- }
-
- private void manageNotifications(List notifications, String max_id, String since_id){
flag_loading = (max_id == null );
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
if( !swiped && firstLoad && (notifications == null || notifications.size() == 0))
textviewNoAction.setVisibility(View.VISIBLE);
else
textviewNoAction.setVisibility(View.GONE);
if( swiped ){
+ Helper.cacheNotificationsClear(context,null);
+ ((MainActivity) context).updateNotifCounter();
boolean isOnWifi = Helper.isOnWIFI(context);
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, this.notifications);
lv_notifications.setAdapter(notificationsListAdapter);
swiped = false;
}
+ ArrayList added = new ArrayList<>();
+ for(Notification notification : this.notifications){
+ added.add(notification.getId());
+ }
if( notifications != null && notifications.size() > 0) {
for(Notification tmpNotification: notifications){
- this.notifications.add(tmpNotification);
+ if( !added.contains(tmpNotification.getId())) {
+ this.notifications.add(tmpNotification);
+ added.add(tmpNotification.getId());
+ }
}
notificationsListAdapter.notifyDataSetChanged();
}
@@ -284,52 +270,57 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
//Store last notification id to avoid to notify for those that have been already seen
if( notifications != null && notifications.size() > 0) {
//acct is null as userId when used in Fragment, data need to be retrieved via shared preferences and db
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Account currentAccount = new AccountDAO(context, db).getAccountByID(userId);
if( currentAccount != null && firstLoad && since_id != null){
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + currentAccount.getId(), since_id);
+ editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + currentAccount.getId(), notifications.get(0).getId());
editor.apply();
}
}
firstLoad = false;
}
+
public void scrollToTop(){
if( lv_notifications != null)
lv_notifications.setAdapter(notificationsListAdapter);
}
- public void update(){
- if( context != null){
- asyncTask = new RetrieveNotificationsAsyncTask(context, null, null, null, null, null, false, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+ public void showNewContent(){
+ new_data.setVisibility(View.VISIBLE);
+ }
+
+ public void refresh(){
+ if( context == null)
+ return;
+ notificationsTmp = Helper.getTempNotification(context, null);
+ if( notificationsTmp.size() > 0){
+ ArrayList added = new ArrayList<>();
+ for(Notification notification : notifications){
+ added.add(notification.getId());
+ }
+ for(int i = notificationsTmp.size() -1 ; i >= 0 ; i--){
+ if( !added.contains(notificationsTmp.get(i).getId())) {
+ this.notifications.add(0, notificationsTmp.get(i));
+ added.add(notificationsTmp.get(i).getId());
+ }
+ }
+ if( this.notifications.size() > 0 )
+ max_id = this.notifications.get(this.notifications.size()-1).getId();
+ boolean isOnWifi = Helper.isOnWIFI(context);
+ final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, notificationsTmp.get(0).getId());
+ editor.apply();
+ notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
+ lv_notifications.setAdapter(notificationsListAdapter);
+ if( textviewNoAction.getVisibility() == View.VISIBLE)
+ textviewNoAction.setVisibility(View.GONE);
}
- }
-
- public void refreshData(){
-
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
-
- if(context != null && this.notificationsTmp != null && this.notificationsTmp.size() > 0){
- boolean isOnWifi = Helper.isOnWIFI(context);
- int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
- notifications = new ArrayList<>();
- for(Notification notification: this.notificationsTmp){
- notifications.add(notification);
- }
- if( textviewNoAction.getVisibility() == View.VISIBLE)
- textviewNoAction.setVisibility(View.GONE);
- notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
- lv_notifications.setAdapter(notificationsListAdapter);
- this.notificationsTmp = new ArrayList<>();
- }
- if( since_id != null){
- //The user clicked on the tab to refresh values so, the pointer is changed
- SharedPreferences.Editor editor = sharedpreferences.edit();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_NOTIF + userId, since_id);
- editor.apply();
- }
- }
+ new_data.setVisibility(View.GONE);
+ }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java
index e08356a50..ffab4fe3d 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java
@@ -25,6 +25,7 @@ import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -75,20 +76,16 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
private boolean isOnWifi;
private int behaviorWithAttachments;
private boolean showMediaOnly;
- private DisplayStatusFragment displayStatusFragment;
private TextView new_data;
private int positionSpinnerTrans;
- private String since_id;
private boolean hideHeader;
private String instanceValue;
public DisplayStatusFragment(){
- displayStatusFragment = this;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-
View rootView = inflater.inflate(R.layout.fragment_status, container, false);
statuses = new ArrayList<>();
context = getContext();
@@ -204,7 +201,6 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
R.color.mastodonC2,
R.color.mastodonC3);
-
if( type == RetrieveFeedsAsyncTask.Type.USER)
asyncTask = new RetrieveFeedsAsyncTask(context, type, targetedId, max_id, showMediaOnly, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else if( type == RetrieveFeedsAsyncTask.Type.TAG)
@@ -222,27 +218,29 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
new_data.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ statusesTmp = Helper.getTempStatus(context, null);
if( statusesTmp != null){
+ for(int i = statusesTmp.size() -1 ; i >= 0 ; i--){
+ statuses.add(0,statusesTmp.get(i));
+ }
boolean isOnWifi = Helper.isOnWIFI(context);
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
- statuses = new ArrayList<>();
- for(Status status: statusesTmp){
- statuses.add(status);
- }
- //The user clicked on the banner to refresh values so, the pointer is changed
- if( statusesTmp.size() > 0 ) {
+ statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
+ lv_status.setAdapter(statusListAdapter);
+ if( statusesTmp.size() > 0){
SharedPreferences.Editor editor = sharedpreferences.edit();
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_HOME + userId, statusesTmp.get(0).getId());
+ editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statusesTmp.get(0).getId());
editor.apply();
}
if( statusesTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
textviewNoAction.setVisibility(View.GONE);
- statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
- lv_status.setAdapter(statusListAdapter);
- statusesTmp = new ArrayList<>();
}
new_data.setVisibility(View.GONE);
+ statusesTmp = new ArrayList<>();
+ Helper.cacheStatusClear(context, null);
+ ((MainActivity) context).updateHomeCounter();
+
}
});
@@ -261,24 +259,29 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
@Override
public void onResume() {
super.onResume();
- //New data are available
- if (getUserVisibleHint() && statusesTmp != null && statusesTmp.size() > 0 ) {
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- boolean isOnWifi = Helper.isOnWIFI(context);
- int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
- int positionSpinnerTrans = sharedpreferences.getInt(Helper.SET_TRANSLATOR, Helper.TRANS_YANDEX);
- statuses = new ArrayList<>();
- for(Status status: statusesTmp){
- statuses.add(status);
+ if( type == RetrieveFeedsAsyncTask.Type.HOME ) {
+ //New data are available
+ statusesTmp = Helper.getTempStatus(context, null);
+ if (getUserVisibleHint() && statusesTmp != null && statusesTmp.size() > 0 && statuses.size() > 0) {
+ ArrayList added = new ArrayList<>();
+ for (Status status : statuses) {
+ added.add(status.getId());
+ }
+ final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ boolean isOnWifi = Helper.isOnWIFI(context);
+ int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
+ int positionSpinnerTrans = sharedpreferences.getInt(Helper.SET_TRANSLATOR, Helper.TRANS_YANDEX);
+ for (int i = statusesTmp.size() - 1; i >= 0; i--) {
+ if (!added.contains(statusesTmp.get(i).getId())) {
+ this.statuses.add(0, statusesTmp.get(i));
+ added.add(statusesTmp.get(i).getId());
+ }
+ }
+ if (this.statuses.size() > 0)
+ max_id = this.statuses.get(this.statuses.size() - 1).getId();
+ statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
+ lv_status.setAdapter(statusListAdapter);
}
- //The user clicked on the tab to refresh values so, the pointer is changed
- SharedPreferences.Editor editor = sharedpreferences.edit();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_HOME + userId, statusesTmp.get(0).getId());
- editor.apply();
- statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
- lv_status.setAdapter(statusListAdapter);
- statusesTmp = new ArrayList<>();
}
}
@@ -313,87 +316,33 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
return;
}
List statuses = apiResponse.getStatuses();
- since_id = apiResponse.getSince_id();
+ String since_id = apiResponse.getSince_id();
max_id = apiResponse.getMax_id();
- //Special case for home timeline
- if( type == RetrieveFeedsAsyncTask.Type.HOME){
- //Retrieves some values
- SharedPreferences.Editor editor = sharedpreferences.edit();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- String bubble_max_id = sharedpreferences.getString(Helper.LAST_MAX_ID_BUBBLE_HOME + userId, null);
- //The initial call comes from a classic tab refresh
- if( refreshData ) {
-
- manageStatus(statuses, max_id, since_id);
- //The current tab is displayed, so user is supposed to have seen status
- if( since_id != null && displayStatusFragment.getUserVisibleHint()) {
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_HOME + userId, since_id);
- editor.apply();
- }else if(!displayStatusFragment.getUserVisibleHint()){
- //Current fragment was loaded but not displayed to the user.
- //So the bubble counter will be displayed
- int countData = 0;
- //Retrieves new status count
- if( bubble_max_id != null) {
- for (Status st : statuses) {
- if (st.getId().trim().equals(bubble_max_id.trim()))
- break;
- countData++;
- }
- }
- ((MainActivity)context).updateHomeCounter(countData);
- }
- }else { //Here, new values have been retrieved on the onResume call (forced mode)
- int countData = 0;
- if( bubble_max_id != null) {
- for (Status st : statuses) {
- if (st.getId().trim().equals(bubble_max_id.trim()))
- break;
- countData++;
- }
- }
-
- if( statuses != null && statuses.size() > 0 && countData > 0) {
- max_id = null;
- firstLoad = true;
- statusesTmp = new ArrayList<>();
- for (Status tmpStatus : statuses) {
- this.statusesTmp.add(tmpStatus);
- }
- //New status will be counted
- //The fragment is not displayed, so the bubble counter should be shown
- if (!displayStatusFragment.getUserVisibleHint()) {
- ((MainActivity) context).updateHomeCounter(countData);
- } else {
- //The current fragment is visible, but for avoiding to populate with new values
- //Values are put in temp and the banned is displayed
- new_data.setVisibility(View.VISIBLE);
- }
- }
- }
- }else {
- manageStatus(statuses, max_id, since_id);
- }
-
-
-
- }
-
- private void manageStatus(List statuses, String max_id, String since_id){
flag_loading = (max_id == null );
if( !swiped && firstLoad && (statuses == null || statuses.size() == 0))
textviewNoAction.setVisibility(View.VISIBLE);
else
textviewNoAction.setVisibility(View.GONE);
if( swiped ){
+ if( type == RetrieveFeedsAsyncTask.Type.HOME ) {
+ Helper.cacheStatusClear(context,null);
+ ((MainActivity) context).updateHomeCounter();
+ }
statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, this.statuses);
lv_status.setAdapter(statusListAdapter);
swiped = false;
}
+ ArrayList added = new ArrayList<>();
+ for(Status status : this.statuses){
+ added.add(status.getId());
+ }
if( statuses != null && statuses.size() > 0) {
for(Status tmpStatus: statuses){
- this.statuses.add(tmpStatus);
+ if( !added.contains(tmpStatus.getId())) {
+ this.statuses.add(tmpStatus);
+ added.add(tmpStatus.getId());
+ }
}
statusListAdapter.notifyDataSetChanged();
}
@@ -401,14 +350,13 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
//Store last toot id for home timeline to avoid to notify for those that have been already seen
if(statuses != null && statuses.size() > 0 && type == RetrieveFeedsAsyncTask.Type.HOME ){
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
//acct is null when used in Fragment, data need to be retrieved via shared preferences and db
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Account currentAccount = new AccountDAO(context, db).getAccountByID(userId);
if( currentAccount != null && firstLoad && since_id != null){
SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + currentAccount.getId(), since_id);
+ editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + currentAccount.getId(), statuses.get(0).getId());
editor.apply();
}
}
@@ -416,8 +364,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
//Retrieves replies
if(statuses != null && statuses.size() > 0 && type == RetrieveFeedsAsyncTask.Type.HOME ) {
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- boolean showPreview = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, true);
+ boolean showPreview = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, false);
//Retrieves attached replies to a toot
if (showPreview) {
new RetrieveRepliesAsyncTask(context, statuses, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@@ -425,6 +372,52 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
}
}
+ public void showNewContent(){
+ new_data.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ super.setUserVisibleHint(isVisibleToUser);
+ if( isVisibleToUser )
+ refresh();
+ }
+
+ public void refresh(){
+ //New data are available
+ if( type == RetrieveFeedsAsyncTask.Type.HOME ) {
+ if (context == null)
+ return;
+ statusesTmp = Helper.getTempStatus(context, null);
+ if (statusesTmp.size() > 0) {
+ ArrayList added = new ArrayList<>();
+ for (Status status : statuses) {
+ added.add(status.getId());
+ }
+ for (int i = statusesTmp.size() - 1; i >= 0; i--) {
+ if (!added.contains(statusesTmp.get(i).getId())) {
+ this.statuses.add(0, statusesTmp.get(i));
+ added.add(statusesTmp.get(i).getId());
+ }
+ }
+ if (this.statuses.size() > 0)
+ max_id = this.statuses.get(this.statuses.size() - 1).getId();
+ boolean isOnWifi = Helper.isOnWIFI(context);
+ final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statusesTmp.get(0).getId());
+ editor.apply();
+ statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
+ lv_status.setAdapter(statusListAdapter);
+ if (textviewNoAction.getVisibility() == View.VISIBLE)
+ textviewNoAction.setVisibility(View.GONE);
+ }
+ new_data.setVisibility(View.GONE);
+ }
+ }
+
public void scrollToTop(){
if( lv_status != null)
lv_status.setAdapter(statusListAdapter);
@@ -444,36 +437,4 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
}
statusListAdapter.notifyDataSetChanged();
}
- public void update() {
- if( context != null) {
- asyncTask = new RetrieveFeedsAsyncTask(context, type, null, false, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- }
-
- public void refreshData(){
- final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- if(context != null && this.statusesTmp != null && this.statusesTmp.size() > 0){
-
- boolean isOnWifi = Helper.isOnWIFI(context);
- int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
- int positionSpinnerTrans = sharedpreferences.getInt(Helper.SET_TRANSLATOR, Helper.TRANS_YANDEX);
-
- statuses = new ArrayList<>();
- for(Status status: statusesTmp){
- statuses.add(status);
- }
- if( textviewNoAction.getVisibility() == View.VISIBLE)
- textviewNoAction.setVisibility(View.GONE);
- statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
- lv_status.setAdapter(statusListAdapter);
- statusesTmp = new ArrayList<>();
- }
- if( since_id != null){
- //The user clicked on the tab to refresh values so, the pointer is changed
- SharedPreferences.Editor editor = sharedpreferences.edit();
- String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
- editor.putString(Helper.LAST_MAX_ID_BUBBLE_HOME + userId, since_id);
- editor.apply();
- }
- }
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsFragment.java
index 2783602f9..95f2e93a5 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsFragment.java
@@ -94,19 +94,6 @@ public class SettingsFragment extends Fragment {
}
});
- boolean bubble_counter = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
-
- final CheckBox set_bubble_counter = (CheckBox) rootView.findViewById(R.id.set_bubble_counter);
- set_bubble_counter.setChecked(bubble_counter);
- set_bubble_counter.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putBoolean(Helper.SET_BUBBLE_COUNTER, set_bubble_counter.isChecked());
- editor.apply();
- }
- });
-
boolean show_error_messages = sharedpreferences.getBoolean(Helper.SET_SHOW_ERROR_MESSAGES, true);
final CheckBox set_show_error_messages = (CheckBox) rootView.findViewById(R.id.set_show_error_messages);
set_show_error_messages.setChecked(show_error_messages);
@@ -133,7 +120,7 @@ public class SettingsFragment extends Fragment {
}
});
- boolean preview_reply = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, true);
+ boolean preview_reply = sharedpreferences.getBoolean(Helper.SET_PREVIEW_REPLIES, false);
final CheckBox set_preview_reply = (CheckBox) rootView.findViewById(R.id.set_preview_reply);
final LinearLayout set_preview_reply_pp_container = (LinearLayout) rootView.findViewById(R.id.set_preview_reply_pp_container);
final SwitchCompat set_preview_reply_pp = (SwitchCompat) rootView.findViewById(R.id.set_preview_reply_pp);
@@ -152,6 +139,7 @@ public class SettingsFragment extends Fragment {
}
}
});
+
if( !preview_reply){
set_preview_reply_pp_container.setVisibility(View.GONE);
}else{
@@ -181,6 +169,53 @@ public class SettingsFragment extends Fragment {
}
});
+ boolean notif_validation_fav = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION_FAV, false);
+ final CheckBox set_share_validation_fav = (CheckBox) rootView.findViewById(R.id.set_share_validation_fav);
+ set_share_validation_fav.setChecked(notif_validation_fav);
+
+ set_share_validation_fav.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putBoolean(Helper.SET_NOTIF_VALIDATION_FAV, set_share_validation_fav.isChecked());
+ editor.apply();
+ }
+ });
+
+ boolean display_local = sharedpreferences.getBoolean(Helper.SET_DISPLAY_LOCAL, true);
+ final CheckBox set_display_local = (CheckBox) rootView.findViewById(R.id.set_display_local);
+ set_display_local.setChecked(display_local);
+
+ set_display_local.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putBoolean(Helper.SET_DISPLAY_LOCAL, set_display_local.isChecked());
+ editor.apply();
+ getActivity().recreate();
+ Intent intent = new Intent(context, MainActivity.class);
+ intent.putExtra(INTENT_ACTION, CHANGE_THEME_INTENT);
+ startActivity(intent);
+ }
+ });
+
+
+ boolean display_global = sharedpreferences.getBoolean(Helper.SET_DISPLAY_GLOBAL, true);
+ final CheckBox set_display_global = (CheckBox) rootView.findViewById(R.id.set_display_global);
+ set_display_global.setChecked(display_global);
+
+ set_display_global.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putBoolean(Helper.SET_DISPLAY_GLOBAL, set_display_global.isChecked());
+ editor.apply();
+ getActivity().recreate();
+ Intent intent = new Intent(context, MainActivity.class);
+ intent.putExtra(INTENT_ACTION, CHANGE_THEME_INTENT);
+ startActivity(intent);
+ }
+ });
final CheckBox set_embedded_browser = (CheckBox) rootView.findViewById(R.id.set_embedded_browser);
final LinearLayout set_javascript_container = (LinearLayout) rootView.findViewById(R.id.set_javascript_container);
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsNotificationsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsNotificationsFragment.java
index a9abbeebd..098995f91 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsNotificationsFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/SettingsNotificationsFragment.java
@@ -26,10 +26,14 @@ import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
+import android.widget.Spinner;
+import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
@@ -49,6 +53,9 @@ public class SettingsNotificationsFragment extends Fragment {
private Context context;
private int style;
+
+ int count = 0;
+
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
@@ -217,6 +224,10 @@ public class SettingsNotificationsFragment extends Fragment {
}
});
+
+ final Spinner led_colour_spinner = (Spinner) rootView.findViewById(R.id.led_colour_spinner);
+ final TextView ledLabel = (TextView) rootView.findViewById(R.id.set_led_colour_label);
+
switchCompatSilent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -224,8 +235,55 @@ public class SettingsNotificationsFragment extends Fragment {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean(Helper.SET_NOTIF_SILENT, isChecked);
editor.apply();
+
+ if (isChecked) {
+ ledLabel.setEnabled(true);
+ led_colour_spinner.setEnabled(true);
+ } else {
+ ledLabel.setEnabled(false);
+ for (View lol : led_colour_spinner.getTouchables()) {
+ lol.setEnabled(false);
+ }
+ }
}
});
+
+ if (sharedpreferences.getBoolean(Helper.SET_NOTIF_SILENT, false)) {
+
+ ledLabel.setEnabled(true);
+ led_colour_spinner.setEnabled(true);
+
+ ArrayAdapter adapterLEDColour = ArrayAdapter.createFromResource(getActivity(),
+ R.array.led_colours, android.R.layout.simple_spinner_item);
+ led_colour_spinner.setAdapter(adapterLEDColour);
+ int positionSpinnerLEDColour = (sharedpreferences.getInt(Helper.SET_LED_COLOUR, Helper.LED_COLOUR));
+ led_colour_spinner.setSelection(positionSpinnerLEDColour);
+
+ led_colour_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ if (count > 0) {
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putInt(Helper.SET_LED_COLOUR, position);
+ editor.apply();
+ } else {
+ count++;
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+ }
+
+ else {
+ ledLabel.setEnabled(false);
+ for (View lol : led_colour_spinner.getTouchables()) {
+ lol.setEnabled(false);
+ }
+ }
+
if( theme == Helper.THEME_LIGHT) {
settings_time_from.setTextColor(ContextCompat.getColor(context, R.color.white));
settings_time_to.setTextColor(ContextCompat.getColor(context, R.color.white));
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java
index 687b5625f..654c58540 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/TabLayoutSettingsFragment.java
@@ -43,7 +43,6 @@ public class TabLayoutSettingsFragment extends Fragment {
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.settings)));
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.notifications)));
tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.optimization)));
- tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.profile)));
final ViewPager viewPager = (ViewPager) inflatedView.findViewById(R.id.viewpager);
viewPager.setAdapter(new PagerAdapter
@@ -90,8 +89,6 @@ public class TabLayoutSettingsFragment extends Fragment {
return new SettingsNotificationsFragment();
case 2:
return new SettingsOptimizationFragment();
- case 3:
- return new SettingsProfileFragment();
default:
return new SettingsNotificationsFragment();
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/ExpandableHeightListView.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ExpandableHeightListView.java
new file mode 100644
index 000000000..bf207a0f8
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ExpandableHeightListView.java
@@ -0,0 +1,64 @@
+package fr.gouv.etalab.mastodon.helper;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+/**
+ * Created by Thomas on 03/09/2017.
+ * Expanded listview
+ */
+
+public class ExpandableHeightListView extends ListView
+ {
+
+ boolean expanded = false;
+
+ public ExpandableHeightListView(Context context)
+ {
+ super(context);
+ }
+
+ public ExpandableHeightListView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ }
+
+ public ExpandableHeightListView(Context context, AttributeSet attrs,int defStyle)
+ {
+ super(context, attrs, defStyle);
+ }
+
+ public boolean isExpanded()
+ {
+ return expanded;
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ // HACK! TAKE THAT ANDROID!
+ if (isExpanded())
+ {
+ // Calculate entire height by providing a very large height hint.
+ // But do not use the highest 2 bits of this integer; those are
+ // reserved for the MeasureSpec mode.
+ int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, expandSpec);
+
+ ViewGroup.LayoutParams params = getLayoutParams();
+ params.height = getMeasuredHeight();
+ }
+ else
+ {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ public void setExpanded(boolean expanded)
+ {
+ this.expanded = expanded;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java
index 1e71beb5c..7f684d329 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java
@@ -18,6 +18,8 @@ package fr.gouv.etalab.mastodon.helper;
import android.app.Activity;
+import android.app.NotificationManager;
+import android.preference.PreferenceManager;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AlertDialog;
import android.app.DownloadManager;
@@ -81,6 +83,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
import com.loopj.android.http.BuildConfig;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
@@ -92,19 +95,23 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.lang.reflect.Type;
import java.net.InetAddress;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@@ -116,6 +123,7 @@ import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import fr.gouv.etalab.mastodon.activities.EditProfileActivity;
import fr.gouv.etalab.mastodon.activities.HashTagActivity;
import fr.gouv.etalab.mastodon.activities.LoginActivity;
import fr.gouv.etalab.mastodon.activities.MainActivity;
@@ -126,14 +134,13 @@ import fr.gouv.etalab.mastodon.asynctasks.RemoveAccountAsyncTask;
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Mention;
+import fr.gouv.etalab.mastodon.client.Entities.Notification;
import fr.gouv.etalab.mastodon.client.Entities.Status;
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;
-import static android.app.Notification.DEFAULT_VIBRATE;
-import static android.app.Notification.FLAG_SHOW_LIGHTS;
import static android.content.Context.DOWNLOAD_SERVICE;
@@ -177,10 +184,6 @@ public class Helper {
public static final String SHOW_BATTERY_SAVER_MESSAGE = "show_battery_saver_message";
public static final String LAST_NOTIFICATION_MAX_ID = "last_notification_max_id";
public static final String LAST_HOMETIMELINE_MAX_ID = "last_hometimeline_max_id";
- public static final String LAST_BUBBLE_REFRESH_NOTIF = "last_bubble_refresh_notif";
- public static final String LAST_BUBBLE_REFRESH_HOME = "last_bubble_refresh_home";
- public static final String LAST_MAX_ID_BUBBLE_NOTIF = "last_max_id_bubble_notif";
- public static final String LAST_MAX_ID_BUBBLE_HOME = "last_max_id_bubble_home";
public static final String CLIP_BOARD = "clipboard";
//Notifications
public static final int NOTIFICATION_INTENT = 1;
@@ -204,8 +207,10 @@ public class Helper {
public static final String SET_ICON_SIZE = "set_icon_size";
public static final String SET_PREVIEW_REPLIES = "set_preview_replies";
public static final String SET_PREVIEW_REPLIES_PP = "set_preview_replies_pp";
- public static final String SET_BUBBLE_COUNTER = "set_bubble_counter";
public static final String SET_TRANSLATOR = "set_translator";
+ public static final String SET_LED_COLOUR = "set_led_colour";
+ private static final String SET_TEMP_STATUS = "set_temp_status";
+ private static final String SET_TEMP_NOTIFICATIONS = "set_temp_notifications";
public static final int ATTACHMENT_ALWAYS = 1;
public static final int ATTACHMENT_WIFI = 2;
@@ -216,6 +221,8 @@ public class Helper {
public static final int THEME_MENU = 2;
public static final int THEME_MENU_TABS = 3;
+ public static final int LED_COLOUR = 0;
+
public static final int TRANS_YANDEX = 0;
public static final int TRANS_GOOGLE = 1;
public static final int TRANS_NONE = 2;
@@ -226,6 +233,7 @@ public class Helper {
public static final String SET_NOTIF_MENTION = "set_notif_follow_mention";
public static final String SET_NOTIF_SHARE = "set_notif_follow_share";
public static final String SET_NOTIF_VALIDATION = "set_share_validation";
+ public static final String SET_NOTIF_VALIDATION_FAV = "set_share_validation_fav";
public static final String SET_WIFI_ONLY = "set_wifi_only";
public static final String SET_NOTIF_HOMETIMELINE = "set_notif_hometimeline";
public static final String SET_NOTIF_SILENT = "set_notif_silent";
@@ -235,6 +243,8 @@ public class Helper {
public static final String SET_COOKIES = "set_cookies";
public static final String SET_FOLDER_RECORD = "set_folder_record";
public static final String SET_TOOT_VISIBILITY = "set_toot_visibility";
+ public static final String SET_DISPLAY_LOCAL = "set_display_local";
+ public static final String SET_DISPLAY_GLOBAL = "set_display_global";
//End points
public static final String EP_AUTHORIZE = "/oauth/authorize";
@@ -250,7 +260,8 @@ public class Helper {
//Receiver
public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account";
public static final String HEADER_ACCOUNT = "header_account";
-
+ public static final String RECEIVE_DATA = "receive_data";
+ public static final String RECEIVE_PICTURE = "receive_picture";
//User agent
public static final String USER_AGENT = "Mastalab/"+ BuildConfig.VERSION_NAME + " Android/"+ Build.VERSION.RELEASE;
@@ -258,7 +269,7 @@ public class Helper {
private static boolean menuAccountsOpened = false;
- private static final Pattern SHORTNAME_PATTERN = Pattern.compile(":([-+\\w]+):");
+ private static final Pattern SHORTNAME_PATTERN = Pattern.compile(":( |)([-+\\w]+):");
public static final Pattern urlPattern = Pattern.compile(
"(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,10}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))",
@@ -273,18 +284,26 @@ public class Helper {
*/
public static String shortnameToUnicode(String input, boolean removeIfUnsupported) {
Matcher matcher = SHORTNAME_PATTERN.matcher(input);
+
boolean supported = Build.VERSION.SDK_INT >= 16;
while (matcher.find()) {
- String unicode = emoji.get(matcher.group(1));
+ String unicode = emoji.get(matcher.group(2));
if (unicode == null) {
continue;
}
if (supported) {
- input = input.replace(":" + matcher.group(1) + ":", unicode);
+ if (matcher.group(1).equals(" "))
+ input = input.replace(": " + matcher.group(2) + ":", unicode);
+ else
+ input = input.replace(":" + matcher.group(2) + ":", unicode);
} else if (removeIfUnsupported) {
- input = input.replace(":" + matcher.group(1) + ":", "");
+ if (matcher.group(1).equals(" "))
+ input = input.replace(": " + matcher.group(2) + ":", unicode);
+ else
+ input = input.replace(":" + matcher.group(2) + ":", "");
}
}
+
return input;
}
//Emoji manager
@@ -596,16 +615,40 @@ public class Helper {
.setAutoCancel(true)
.setContentIntent(pIntent)
.setContentText(message);
-
- int notifDefaults = FLAG_SHOW_LIGHTS;
- notificationBuilder.setDefaults(notifDefaults);
if( sharedpreferences.getBoolean(Helper.SET_NOTIF_SILENT,false) ) {
- notificationBuilder.setDefaults(notifDefaults|DEFAULT_VIBRATE);
+ notificationBuilder.setVibrate(new long[] { 500, 500, 500});
}else {
String soundUri = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() +"/";
notificationBuilder.setSound(Uri.parse(soundUri + R.raw.boop));
}
- notificationBuilder.setLights(Color.BLUE, 500, 1000);
+
+ int ledColour = Color.BLUE;
+
+ switch (sharedpreferences.getInt(Helper.SET_LED_COLOUR, Helper.LED_COLOUR)) {
+ case 0: // BLUE
+ ledColour = Color.BLUE;
+ break;
+ case 1: // CYAN
+ ledColour = Color.CYAN;
+ break;
+ case 2: // MAGENTA
+ ledColour = Color.MAGENTA;
+ break;
+ case 3: // GREEN
+ ledColour = Color.GREEN;
+ break;
+ case 4: // RED
+ ledColour = Color.RED;
+ break;
+ case 5: // YELLOW
+ ledColour = Color.YELLOW;
+ break;
+ case 6: // WHITE
+ ledColour = Color.WHITE;
+ break;
+ }
+
+ notificationBuilder.setLights(ledColour, 500, 1000);
notificationBuilder.setContentTitle(title);
notificationBuilder.setLargeIcon(icon);
notificationManager.notify(notificationId, notificationBuilder.build());
@@ -964,6 +1007,8 @@ public class Helper {
TextView ownerStatus = (TextView) headerLayout.findViewById(R.id.owner_status);
TextView ownerFollowing = (TextView) headerLayout.findViewById(R.id.owner_following);
TextView ownerFollowers = (TextView) headerLayout.findViewById(R.id.owner_followers);
+ ImageView header_edit_profile = (ImageView) headerLayout.findViewById(R.id.header_edit_profile);
+ header_edit_profile.setOnClickListener(null);
if( account == null ) {
Helper.logout(activity);
Intent myIntent = new Intent(activity, LoginActivity.class);
@@ -1013,6 +1058,13 @@ public class Helper {
}
});
}
+ header_edit_profile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(activity, EditProfileActivity.class);
+ activity.startActivity(intent);
+ }
+ });
}
profilePicture.setOnClickListener(null);
profilePicture.setOnClickListener(new View.OnClickListener() {
@@ -1544,4 +1596,124 @@ public class Helper {
}
}
}
+
+
+ public static int getUnreadNotifications(Context context, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Gson gson = new Gson();
+ String json = sharedpreferences.getString(Helper.SET_TEMP_NOTIFICATIONS + userId, null);
+ Type type = new TypeToken>() {}.getType();
+ ArrayList notifications = gson.fromJson(json, type);
+ return (notifications == null)?0:notifications.size();
+ }
+
+
+
+ public static int getUnreadToots(Context context, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Gson gson = new Gson();
+ String json = sharedpreferences.getString(Helper.SET_TEMP_STATUS + userId, null);
+ Type type = new TypeToken>() {}.getType();
+ ArrayList statuses = gson.fromJson(json, type);
+ return (statuses == null)?0:statuses.size();
+ }
+
+
+ public static void cacheStatus(Context context, Status status, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ ArrayList statuses = getTempStatus(context, userId);
+ if( statuses == null)
+ statuses = new ArrayList<>();
+ if( status != null)
+ statuses.add(0,status);
+ Gson gson = new Gson();
+ String serializedAccounts = gson.toJson(statuses);
+ editor.putString(Helper.SET_TEMP_STATUS + userId, serializedAccounts);
+ editor.apply();
+ }
+
+ public static void cacheStatusClear(Context context, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ ArrayList statuses = new ArrayList<>();
+ Gson gson = new Gson();
+ String serializedAccounts = gson.toJson(statuses);
+ editor.putString(Helper.SET_TEMP_STATUS + userId, serializedAccounts);
+ editor.apply();
+ //noinspection EmptyTryBlock
+ try {
+ NotificationManager notificationManager = (NotificationManager) context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
+ long notif_id = Long.parseLong(userId);
+ int notificationId = ((notif_id + 2) > 2147483647) ? (int) (2147483647 - notif_id - 2) : (int) (notif_id + 2);
+ notificationManager.cancel(notificationId);
+ }catch (Exception ignored){}
+ }
+
+ public static ArrayList getTempStatus(Context context, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Gson gson = new Gson();
+ String json = sharedpreferences.getString(Helper.SET_TEMP_STATUS + userId, null);
+ Type type = new TypeToken>() {}.getType();
+ return gson.fromJson(json, type);
+ }
+
+
+ public static void cacheNotifications(Context context, Notification notification, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ ArrayList notifications = getTempNotification(context, userId);
+ if( notifications == null)
+ notifications = new ArrayList<>();
+ if( notification != null)
+ notifications.add(0,notification);
+ Gson gson = new Gson();
+ String serializedAccounts = gson.toJson(notifications);
+ editor.putString(Helper.SET_TEMP_NOTIFICATIONS + userId, serializedAccounts);
+ editor.apply();
+ }
+
+ public static void cacheNotificationsClear(Context context, String userId){
+
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ ArrayList notifications = new ArrayList<>();
+ Gson gson = new Gson();
+ String serializedAccounts = gson.toJson(notifications);
+ editor.putString(Helper.SET_TEMP_NOTIFICATIONS + userId, serializedAccounts);
+ editor.apply();
+ //noinspection EmptyTryBlock
+ try {
+ NotificationManager notificationManager = (NotificationManager) context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
+ long notif_id = Long.parseLong(userId);
+ int notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1);
+ notificationManager.cancel(notificationId);
+ }catch (Exception ignored){}
+
+ }
+
+ public static ArrayList getTempNotification(Context context, String userId){
+ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ if( userId == null)
+ userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Gson gson = new Gson();
+ String json = sharedpreferences.getString(Helper.SET_TEMP_NOTIFICATIONS + userId, null);
+ Type type = new TypeToken>() {}.getType();
+ return gson.fromJson(json, type);
+ }
+
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/ManageHeader.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ManageHeader.java
new file mode 100644
index 000000000..cca3a5574
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ManageHeader.java
@@ -0,0 +1,9 @@
+package fr.gouv.etalab.mastodon.helper;
+
+/**
+ * Created by Thomas on 02/09/2017.
+ */
+
+public class ManageHeader {
+
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMetaDataInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMetaDataInterface.java
new file mode 100644
index 000000000..c42aec9ac
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMetaDataInterface.java
@@ -0,0 +1,24 @@
+/* Copyright 2017 Thomas Schneider
+ *
+ * This file is a part of Mastalab
+ *
+ * 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.
+ *
+ * Mastalab 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 Mastalab; if not,
+ * see . */
+package fr.gouv.etalab.mastodon.interfaces;
+
+
+/**
+ * Created by Thomas on 02/09/2017.
+ * Interface for retrieving meta data
+ */
+public interface OnRetrieveMetaDataInterface {
+ void onRetrieveMetaData(boolean error, String image, String title, String description);
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java
index 4d984933e..200e7f3e0 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveRemoteAccountInterface.java
@@ -20,5 +20,5 @@ package fr.gouv.etalab.mastodon.interfaces;
* Interface for retrieving a remote account
*/
public interface OnRetrieveRemoteAccountInterface {
- void onRetrieveRemoteAccount(boolean error, String name, String username, boolean locked, String avatar, String bio, int statusCount, int followingCount, int followersCount);
+ void onRetrieveRemoteAccount(boolean error, String name, String username, String instance, boolean locked, String avatar, String bio, String statusCount, String followingCount, String followersCount);
}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchDevelopersAccountshInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchDevelopersAccountshInterface.java
new file mode 100644
index 000000000..12b1db865
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchDevelopersAccountshInterface.java
@@ -0,0 +1,28 @@
+/* Copyright 2017 Thomas Schneider
+ *
+ * This file is a part of Mastalab
+ *
+ * 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.
+ *
+ * Mastalab 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 Mastalab; if not,
+ * see . */
+package fr.gouv.etalab.mastodon.interfaces;
+
+import java.util.ArrayList;
+
+import fr.gouv.etalab.mastodon.client.Entities.Account;
+
+
+/**
+ * Created by Thomas on 03/09/2017.
+ * Interface for search dev accounts
+ */
+public interface OnRetrieveSearchDevelopersAccountshInterface {
+ void onRetrieveSearchDevelopersAccounts(ArrayList accounts);
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java
index 19cd2d843..59b29caa1 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/HomeTimelineSyncJob.java
@@ -127,24 +127,17 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
@Override
- public void onRetrieveHomeTimelineService(APIResponse apiResponse, String acct, String userId) {
- List statuses = apiResponse.getStatuses();
+ public void onRetrieveHomeTimelineService(APIResponse apiResponse, String acct, final String userId) {
+ final List statuses = apiResponse.getStatuses();
if( apiResponse.getError() != null || statuses == null || statuses.size() == 0)
return;
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
final String max_id = sharedpreferences.getString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, null);
- if( max_id == null){
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, apiResponse.getSince_id());
- editor.apply();
- return;
- }
+
//No previous notifications in cache, so no notification will be sent
String message;
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, apiResponse.getSince_id());
- editor.apply();
+
for(Status status: statuses){
//The notification associated to max_id is discarded as it is supposed to have already been sent
//Also, if the toot comes from the owner, we will avoid to warn him/her...
@@ -189,11 +182,17 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
notify_user(getContext(), intent, notificationId, loadedImage, finalTitle, finalMessage);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statuses.get(0).getId());
+ editor.apply();
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
notify_user(getContext(), intent, notificationId, BitmapFactory.decodeResource(getContext().getResources(),
- R.drawable.mastodonlogo), finalTitle, finalMessage);
+ R.drawable.mastodonlogo), finalTitle, finalMessage);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statuses.get(0).getId());
+ editor.apply();
}});
}
@@ -201,4 +200,4 @@ public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineSe
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java
index 49603c1c1..bca8fe414 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/NotificationsSyncJob.java
@@ -133,8 +133,8 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
@Override
- public void onRetrieveNotifications(APIResponse apiResponse, String acct, String userId, boolean refreshData) {
- List notifications = apiResponse.getNotifications();
+ public void onRetrieveNotifications(APIResponse apiResponse, String acct, final String userId, boolean refreshData) {
+ final List notifications = apiResponse.getNotifications();
if( apiResponse.getError() != null || notifications == null || notifications.size() == 0)
return;
Bitmap icon_notification = null;
@@ -144,12 +144,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true);
boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true);
final String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + userId, null);
- if( max_id == null){
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, apiResponse.getSince_id());
- editor.apply();
- return;
- }
+
//No previous notifications in cache, so no notification will be sent
int newFollows = 0;
@@ -176,7 +171,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
title = String.format("@%s %s", notification.getAccount().getUsername(),getContext().getString(R.string.notif_mention));
}
}
- break;
+ break;
case "reblog":
if(notif_share){
newShare++;
@@ -217,9 +212,7 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
default:
}
}
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, apiResponse.getSince_id());
- editor.apply();
+
int allNotifCount = newFollows + newAdds + newAsks + newMentions + newShare;
if( allNotifCount > 0){
//Some others notification
@@ -254,18 +247,26 @@ public class NotificationsSyncJob extends Job implements OnRetrieveNotifications
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
- if( max_id != null)
+ if( max_id != null) {
notify_user(getContext(), intent, notificationId, loadedImage, finalTitle, message);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, notifications.get(0).getId());
+ editor.apply();
+ }
}
@Override
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
- if( max_id != null)
+ if( max_id != null) {
notify_user(getContext(), intent, notificationId, BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.mastodonlogo), finalTitle, message);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, notifications.get(0).getId());
+ editor.apply();
+ }
}});
}
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledTootsSyncJob.java b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledTootsSyncJob.java
index 5bc7eb5bf..a995d5b1e 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledTootsSyncJob.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/jobs/ScheduledTootsSyncJob.java
@@ -17,7 +17,6 @@ package fr.gouv.etalab.mastodon.jobs;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
-import android.util.Log;
import com.evernote.android.job.Job;
import com.evernote.android.job.JobRequest;
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/services/BootService.java b/app/src/main/java/fr/gouv/etalab/mastodon/services/BootService.java
new file mode 100644
index 000000000..147ef37a0
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/services/BootService.java
@@ -0,0 +1,38 @@
+package fr.gouv.etalab.mastodon.services;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.sqlite.SQLiteDatabase;
+
+import java.util.List;
+
+import fr.gouv.etalab.mastodon.client.Entities.Account;
+import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
+import fr.gouv.etalab.mastodon.sqlite.Sqlite;
+
+/**
+ * Created by Thomas on 29/08/2017.
+ * BroadcastReceiver to start service when device boot
+ */
+
+public class BootService extends BroadcastReceiver {
+
+ public BootService() {
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ List accounts = new AccountDAO(context, db).getAllAccount();
+ if( accounts != null){
+ for (Account account: accounts) {
+ Intent intentService = new Intent(context, StreamingService.class);
+ intentService.putExtra("acccountId", account.getId());
+ intentService.putExtra("accountAcct", account.getAcct());
+ context.startService(intentService);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/services/StreamingService.java b/app/src/main/java/fr/gouv/etalab/mastodon/services/StreamingService.java
new file mode 100644
index 000000000..6c26e9683
--- /dev/null
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/services/StreamingService.java
@@ -0,0 +1,503 @@
+package fr.gouv.etalab.mastodon.services;
+/* Copyright 2017 Thomas Schneider
+ *
+ * This file is a part of Mastalab
+ *
+ * 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.
+ *
+ * Mastalab 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 Mastalab; if not,
+ * see . */
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.support.annotation.Nullable;
+import android.support.v4.content.LocalBroadcastManager;
+import android.text.Html;
+import android.util.Log;
+import android.view.View;
+
+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 org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import fr.gouv.etalab.mastodon.activities.MainActivity;
+import fr.gouv.etalab.mastodon.client.API;
+import fr.gouv.etalab.mastodon.client.Entities.Account;
+import fr.gouv.etalab.mastodon.client.Entities.Notification;
+import fr.gouv.etalab.mastodon.client.Entities.Status;
+import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
+import fr.gouv.etalab.mastodon.client.TLSSocketFactory;
+import fr.gouv.etalab.mastodon.helper.Helper;
+import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
+import fr.gouv.etalab.mastodon.sqlite.Sqlite;
+import mastodon.etalab.gouv.fr.mastodon.R;
+
+import static fr.gouv.etalab.mastodon.helper.Helper.HOME_TIMELINE_INTENT;
+import static fr.gouv.etalab.mastodon.helper.Helper.INTENT_ACTION;
+import static fr.gouv.etalab.mastodon.helper.Helper.NOTIFICATION_INTENT;
+import static fr.gouv.etalab.mastodon.helper.Helper.PREF_KEY_ID;
+import static fr.gouv.etalab.mastodon.helper.Helper.canNotify;
+import static fr.gouv.etalab.mastodon.helper.Helper.notify_user;
+
+/**
+ * Created by Thomas on 28/08/2017.
+ * Manage service for streaming api and new notifications
+ */
+
+public class StreamingService extends Service {
+
+ private String message;
+ private int notificationId;
+ private Intent intent;
+ private String lastPreviousContent;
+ private static HashMap connectionHashMap = new HashMap<>();
+ private static HashMap isConnectingHashMap = new HashMap<>();
+ private EventStreaming lastEvent;
+ public enum EventStreaming{
+ UPDATE,
+ NOTIFICATION,
+ DELETE,
+ NONE
+ }
+
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if( intent != null){
+ String accountId = intent.getStringExtra("accountId");
+ String accountAcct = intent.getStringExtra("accountAcct");
+ if( accountId != null && accountAcct != null){
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ Account account = new AccountDAO(getApplicationContext(), db).getAccountByIDAcct(accountId, accountAcct);
+ if( account != null)
+ callAsynchronousTask(account);
+ }else {
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ List accounts = new AccountDAO(getApplicationContext(), db).getAllAccount();
+ if( accounts != null){
+ for (Account account: accounts) {
+ intent = new Intent(getApplicationContext(), StreamingService.class);
+ intent.putExtra("accountId", account.getId());
+ intent.putExtra("accountAcct", account.getAcct());
+ startService(intent);
+ }
+ }
+ }
+ }
+ return START_STICKY;
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+
+ /**
+ * Task in background starts here.
+ */
+ private void callAsynchronousTask(final Account account) {
+ //If an Internet connection and user agrees with notification refresh
+ final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ //Check which notifications the user wants to see
+ boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true);
+ boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true);
+ boolean notif_ask = sharedpreferences.getBoolean(Helper.SET_NOTIF_ASK, true);
+ boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true);
+ boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true);
+ //User disagree with all notifications
+ if( !notif_follow && !notif_add && !notif_ask && !notif_mention && !notif_share)
+ return; //Nothing is done
+ //No account connected, the service is stopped
+ if(!Helper.isLoggedIn(getApplicationContext()))
+ return;
+ //If WIFI only and on WIFI OR user defined any connections to use the service.
+ if( isConnectingHashMap.get(account.getAcct()+account.getId()) != null && isConnectingHashMap.get(account.getAcct()+account.getId()))
+ return;
+ if(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getApplicationContext())) {
+ Thread readThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ boolean connectionAlive = false;
+ isConnectingHashMap.put(account.getAcct()+account.getId(), true);
+ if( connectionHashMap.get(account.getAcct()+account.getId()) != null) {
+ try {
+ connectionAlive = (connectionHashMap.get(account.getAcct()+account.getId()).getResponseCode() == 200);
+ } catch (Exception e) {
+ connectionAlive = false;
+ }
+ }
+ if( connectionAlive) {
+ HttpsURLConnection httpsURLConnection = connectionHashMap.get(account.getAcct() + account.getId());
+ if( httpsURLConnection != null)
+ httpsURLConnection.disconnect();
+ }
+ try {
+ URL url = new URL("https://" + account.getInstance() + "/api/v1/streaming/user");
+ HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
+ urlConnection.setRequestProperty("Content-Type", "application/json");
+ urlConnection.setRequestProperty("Authorization", "Bearer " + account.getToken());
+ urlConnection.setRequestProperty("Connection", "Keep-Alive");
+ urlConnection.setRequestProperty("Keep-Alive", "header");
+ urlConnection.setRequestProperty("Connection", "close");
+ urlConnection.setSSLSocketFactory(new TLSSocketFactory());
+ connectionHashMap.put(account.getAcct()+account.getId(), urlConnection);
+ InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
+ readStream(inputStream, account);
+ } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
+ e.printStackTrace();
+ forceRestart(account);
+ }
+ } catch (Exception ignored) {
+ }
+ }
+ });
+ readThread.start();
+ }
+ }
+
+
+
+
+
+
+
+ @SuppressWarnings("ConstantConditions")
+ private String readStream(InputStream inputStream, final Account account) {
+ BufferedReader reader = null;
+ try{
+ reader = new BufferedReader(new InputStreamReader(inputStream));
+ String event;
+ EventStreaming eventStreaming = null;
+ //noinspection InfiniteLoopStatement
+ while(true){
+ try {
+ event = reader.readLine();
+ }catch (Exception e){
+ e.printStackTrace();
+ forceRestart(account);
+ break;
+ }
+ if (event !=null){
+ if( (lastEvent == EventStreaming.NONE || lastEvent == null) && !event.startsWith("data: ")) {
+ switch (event.trim()) {
+ case "event: update":
+ lastEvent = EventStreaming.UPDATE;
+ break;
+ case "event: notification":
+ lastEvent = EventStreaming.NOTIFICATION;
+ break;
+ case "event: delete":
+ lastEvent = EventStreaming.DELETE;
+ break;
+ default:
+ lastEvent = EventStreaming.NONE;
+ }
+ }else{
+ if( !event.startsWith("data: ")){
+ lastEvent = EventStreaming.NONE;
+ continue;
+ }
+ event = event.substring(6);
+ if(lastEvent == EventStreaming.UPDATE) {
+ eventStreaming = EventStreaming.UPDATE;
+ }else if(lastEvent == EventStreaming.NOTIFICATION) {
+ eventStreaming = EventStreaming.NOTIFICATION;
+ }else if( lastEvent == EventStreaming.DELETE) {
+ eventStreaming = EventStreaming.DELETE;
+ event = "{id:" + event + "}";
+ }else {
+ eventStreaming = EventStreaming.UPDATE;
+ }
+ lastEvent = EventStreaming.NONE;
+ try {
+ JSONObject eventJson = new JSONObject(event);
+ onRetrieveStreaming(eventStreaming, eventJson, account.getAcct(), account.getId());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }finally {
+ if(reader != null){
+ try{
+ reader.close();
+ }catch (IOException e){
+ e.printStackTrace();
+ }
+ }
+ forceRestart(account);
+ }
+ return null;
+ }
+
+ private void forceRestart(Account account){
+ isConnectingHashMap.put(account.getAcct()+account.getId(), false);
+ SystemClock.sleep(1000);
+ Intent intent = new Intent(getApplicationContext(), StreamingService.class);
+ intent.putExtra("accountId", account.getId());
+ intent.putExtra("accountAcct", account.getAcct());
+ startService(intent);
+ }
+
+ @Override
+ public void onTaskRemoved(Intent rootIntent) {
+ Intent intent = new Intent(getApplicationContext(), StreamingService.class);
+ PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
+ AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
+ super.onTaskRemoved(rootIntent);
+ }
+
+
+ public void onRetrieveStreaming(EventStreaming event, JSONObject response, String acct, String userId) {
+ if( response == null )
+ return;
+ final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true);
+ 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);
+
+ //No previous notifications in cache, so no notification will be sent
+ boolean notify = false;
+ String notificationUrl = null;
+ String title = null;
+ Status status = null;
+ Notification notification = null;
+ String dataId = null;
+ if( event == EventStreaming.NOTIFICATION){
+ notification = API.parseNotificationResponse(getApplicationContext(), response);
+ switch (notification.getType()){
+ case "mention":
+ if(notif_mention){
+ lastPreviousContent = notification.getStatus().getContent();
+ notify = true;
+ notificationUrl = notification.getAccount().getAvatar();
+ if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0 )
+ title = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),getString(R.string.notif_mention));
+ else
+ title = String.format("%s %s", notification.getAccount().getUsername(),getString(R.string.notif_mention));
+ }
+ break;
+ case "reblog":
+ if(notif_share){
+ notify = true;
+ notificationUrl = notification.getAccount().getAvatar();
+ if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0 )
+ title = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),getString(R.string.notif_reblog));
+ else
+ title = String.format("%s %s", notification.getAccount().getUsername(),getString(R.string.notif_reblog));
+ }
+ break;
+ case "favourite":
+ if(notif_add){
+ notify = true;
+ notificationUrl = notification.getAccount().getAvatar();
+ if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0 )
+ title = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),getString(R.string.notif_favourite));
+ else
+ title = String.format("%s %s", notification.getAccount().getUsername(),getString(R.string.notif_favourite));
+ }
+ break;
+ case "follow":
+ if(notif_follow){
+ notify = true;
+ notificationUrl = notification.getAccount().getAvatar();
+ if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0 )
+ title = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),getString(R.string.notif_follow));
+ else
+ title = String.format("%s %s", notification.getAccount().getUsername(),getString(R.string.notif_follow));
+ }
+ break;
+ default:
+ break;
+ }
+ Helper.cacheNotifications(getApplicationContext(), notification, userId);
+ if( notification.getStatus().getContent()!= null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ message = Html.fromHtml(notification.getStatus().getContent(), Html.FROM_HTML_MODE_LEGACY).toString();
+ else
+ //noinspection deprecation
+ message = Html.fromHtml(notification.getStatus().getContent()).toString();
+ message = message.substring(0, message.length()>49?49:message.length());
+ message = message + "…";
+ }else{
+ message = "";
+ }
+
+ }else if ( event == EventStreaming.UPDATE){
+ status = API.parseStatuses(getApplicationContext(), response);
+ status.setReplies(new ArrayList()); //Force to don't display replies
+ status.setNew(true);
+ Helper.cacheStatus(getApplicationContext(), status, userId);
+ if( status.getContent() != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ message = Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_LEGACY).toString();
+ else
+ //noinspection deprecation
+ message = Html.fromHtml(status.getContent()).toString();
+ message = message.substring(0, message.length()>49?49:message.length());
+ message = message + "…";
+ }else{
+ message = "";
+ }
+ title = getString(R.string.notif_pouet, status.getAccount().getUsername());
+ notificationUrl = status.getAccount().getAvatar();
+ }else if( event == EventStreaming.DELETE){
+ try {
+ dataId = response.getString("id");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ //Check which user is connected and if activity is to front
+ boolean activityVisible = false;
+ try{
+ activityVisible = MainActivity.isActivityVisible();
+ }catch (Exception ignored){}
+ String connectedUser = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ Account account = new AccountDAO(getApplicationContext(), db).getAccountByID(connectedUser);
+ //User receiving the notification is connected
+ if( isCurrentAccountLoggedIn(acct, userId)){
+ notify = false;
+ Intent intentBC = new Intent(Helper.RECEIVE_DATA);
+ intentBC.putExtra("eventStreaming", event);
+ LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intentBC);
+ }
+ //User receiving the notification is connected and application is to front, notification won't be pushed
+ //Instead, the interaction is done in the activity
+ if( activityVisible && isCurrentAccountLoggedIn(acct, userId)){
+ notify = false;
+ }else if(event == EventStreaming.NOTIFICATION ){
+ notify = true;
+ }else if(event == EventStreaming.UPDATE ){
+ //lastPreviousContent contains the content of the last notification, if it was a mention it will avoid to push two notifications
+ if( account == null || (lastPreviousContent != null && lastPreviousContent.equals(status.getContent()))) {
+ notify = false;
+ }else {
+ notify = true;
+ //Retrieve users in db that owner has, and if the toot matches one of them we don't notify
+ List accounts = new AccountDAO(getApplicationContext(),db).getAllAccount();
+ for(Account act_tmp: accounts) {
+ if(notify && act_tmp.getAcct().trim().equals(status.getAccount().getAcct()) && act_tmp.getId().trim().equals(status.getAccount().getId().trim())){
+ notify = false;
+ }
+ }
+ //Here we check if the user wants home timeline notifications
+ if( notify )
+ notify = sharedpreferences.getBoolean(Helper.SET_NOTIF_HOMETIMELINE, true);
+ }
+ lastPreviousContent = status.getContent();
+ }
+ //All is good here for a notification, we will know check if it can be done depending of the hour
+ if( notify)
+ notify = canNotify(getApplicationContext());
+ if( notify && event == EventStreaming.NOTIFICATION){
+ intent = new Intent(getApplicationContext(), MainActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
+ intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT);
+ intent.putExtra(PREF_KEY_ID, userId);
+ long notif_id = Long.parseLong(userId);
+ notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1);
+ SharedPreferences.Editor editor = sharedpreferences.edit();
+ editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, notification.getId());
+ editor.apply();
+ }
+ if( notify && event == EventStreaming.UPDATE) {
+ intent = new Intent(getApplicationContext(), 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);
+ 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, status.getId());
+ editor.apply();
+ }
+
+ if( notify){
+ if( notificationUrl != null){
+ ImageLoader imageLoaderNoty = ImageLoader.getInstance();
+ File cacheDir = new File(getApplicationContext().getCacheDir(), getString(R.string.app_name));
+ ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
+ .imageDownloader(new PatchBaseImageDownloader(getApplicationContext()))
+ .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);
+ notify_user(getApplicationContext(), intent, notificationId, loadedImage, finalTitle, message);
+
+ }
+ @Override
+ public void onLoadingFailed(String imageUri, View view, FailReason failReason){
+ notify_user(getApplicationContext(), intent, notificationId, BitmapFactory.decodeResource(getApplicationContext().getResources(),
+ R.drawable.mastodonlogo), finalTitle, message);
+ }});
+ }
+ }
+ }
+
+ private boolean isCurrentAccountLoggedIn(String acct, String userId){
+ final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
+ String userconnected = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ Account account = new AccountDAO(getApplicationContext(), db).getAccountByID(userconnected);
+ return acct.trim().equals(account.getAcct().trim()) && userId.trim().equals(account.getId().trim());
+ }
+}
diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/AccountDAO.java b/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/AccountDAO.java
index e0d46ebc8..4477d2f0e 100644
--- a/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/AccountDAO.java
+++ b/app/src/main/java/fr/gouv/etalab/mastodon/sqlite/AccountDAO.java
@@ -133,6 +133,21 @@ public class AccountDAO {
}
}
+ /**
+ * Returns an Account by its id and acct
+ * @param accountId String
+ * @param accountAcct String
+ * @return Account
+ */
+ public Account getAccountByIDAcct(String accountId, String accountAcct){
+ try {
+ Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_USER_ID + " = '" + accountId + "' AND " + Sqlite.COL_ACCT + " = '" + accountAcct + "'", null, null, null, null, "1");
+ return cursorToUser(c);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
/**
* Returns an Account by id and instance
* @param accountId String
diff --git a/app/src/main/res/drawable-hdpi/ic_edit.png b/app/src/main/res/drawable-hdpi/ic_edit.png
new file mode 100644
index 000000000..e19f4dd91
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_edit.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_fav_header.png b/app/src/main/res/drawable-hdpi/ic_fav_header.png
new file mode 100644
index 000000000..0e8c7e9a1
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_fav_header.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_fav_notif_header.png b/app/src/main/res/drawable-hdpi/ic_fav_notif_header.png
new file mode 100644
index 000000000..0e8c7e9a1
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_fav_notif_header.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_fiber_new.png b/app/src/main/res/drawable-hdpi/ic_fiber_new.png
new file mode 100644
index 000000000..ec7fdc454
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_fiber_new.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_follow_header.png b/app/src/main/res/drawable-hdpi/ic_follow_header.png
new file mode 100644
index 000000000..46cfb9fe8
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_follow_header.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_follow_notif_header.png b/app/src/main/res/drawable-hdpi/ic_follow_notif_header.png
new file mode 100644
index 000000000..46cfb9fe8
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_follow_notif_header.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_retweet_header.png b/app/src/main/res/drawable-hdpi/ic_retweet_header.png
new file mode 100644
index 000000000..8aa0ff8dd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_retweet_header.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_retweet_notif_header.png b/app/src/main/res/drawable-hdpi/ic_retweet_notif_header.png
new file mode 100644
index 000000000..8aa0ff8dd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_retweet_notif_header.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_edit.png b/app/src/main/res/drawable-ldpi/ic_edit.png
new file mode 100644
index 000000000..1d75bd154
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_edit.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_fav_header.png b/app/src/main/res/drawable-ldpi/ic_fav_header.png
new file mode 100644
index 000000000..b69764624
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_fav_header.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_fav_notif_header.png b/app/src/main/res/drawable-ldpi/ic_fav_notif_header.png
new file mode 100644
index 000000000..b69764624
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_fav_notif_header.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_fiber_new.png b/app/src/main/res/drawable-ldpi/ic_fiber_new.png
new file mode 100644
index 000000000..45be937c6
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_fiber_new.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_follow_header.png b/app/src/main/res/drawable-ldpi/ic_follow_header.png
new file mode 100644
index 000000000..805a8d518
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_follow_header.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_follow_notif_header.png b/app/src/main/res/drawable-ldpi/ic_follow_notif_header.png
new file mode 100644
index 000000000..805a8d518
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_follow_notif_header.png differ
diff --git a/app/src/main/res/drawable-ldpi/ic_retweet_notif_header.png b/app/src/main/res/drawable-ldpi/ic_retweet_notif_header.png
new file mode 100644
index 000000000..5ec2cfb26
Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_retweet_notif_header.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_edit.png b/app/src/main/res/drawable-mdpi/ic_edit.png
new file mode 100644
index 000000000..5f68300d4
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_edit.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_fav_header.png b/app/src/main/res/drawable-mdpi/ic_fav_header.png
new file mode 100644
index 000000000..8b4b7ec79
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_fav_header.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_fav_notif_header.png b/app/src/main/res/drawable-mdpi/ic_fav_notif_header.png
new file mode 100644
index 000000000..8b4b7ec79
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_fav_notif_header.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_fiber_new.png b/app/src/main/res/drawable-mdpi/ic_fiber_new.png
new file mode 100644
index 000000000..589f71501
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_fiber_new.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_follow_header.png b/app/src/main/res/drawable-mdpi/ic_follow_header.png
new file mode 100644
index 000000000..3f6c75c56
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_follow_header.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_follow_notif_header.png b/app/src/main/res/drawable-mdpi/ic_follow_notif_header.png
new file mode 100644
index 000000000..3f6c75c56
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_follow_notif_header.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_retweet_notif_header.png b/app/src/main/res/drawable-mdpi/ic_retweet_notif_header.png
new file mode 100644
index 000000000..d12a55f15
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_retweet_notif_header.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_edit.png b/app/src/main/res/drawable-xhdpi/ic_edit.png
new file mode 100644
index 000000000..3ecfd46f1
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_edit.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_fav_header.png b/app/src/main/res/drawable-xhdpi/ic_fav_header.png
new file mode 100644
index 000000000..71d0bfab0
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_fav_header.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_fav_notif_header.png b/app/src/main/res/drawable-xhdpi/ic_fav_notif_header.png
new file mode 100644
index 000000000..71d0bfab0
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_fav_notif_header.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_fiber_new.png b/app/src/main/res/drawable-xhdpi/ic_fiber_new.png
new file mode 100644
index 000000000..08208c303
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_fiber_new.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_follow_header.png b/app/src/main/res/drawable-xhdpi/ic_follow_header.png
new file mode 100644
index 000000000..77c482e5b
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_follow_header.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_follow_notif_header.png b/app/src/main/res/drawable-xhdpi/ic_follow_notif_header.png
new file mode 100644
index 000000000..77c482e5b
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_follow_notif_header.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_retweet_notif_header.png b/app/src/main/res/drawable-xhdpi/ic_retweet_notif_header.png
new file mode 100644
index 000000000..79c8052c9
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_retweet_notif_header.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_edit.png b/app/src/main/res/drawable-xxhdpi/ic_edit.png
new file mode 100644
index 000000000..bfd9e3b60
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_edit.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_fav_header.png b/app/src/main/res/drawable-xxhdpi/ic_fav_header.png
new file mode 100644
index 000000000..70f761c8d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_fav_header.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_fav_notif_header.png b/app/src/main/res/drawable-xxhdpi/ic_fav_notif_header.png
new file mode 100644
index 000000000..70f761c8d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_fav_notif_header.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_fiber_new.png b/app/src/main/res/drawable-xxhdpi/ic_fiber_new.png
new file mode 100644
index 000000000..160387cdd
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_fiber_new.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_follow_header.png b/app/src/main/res/drawable-xxhdpi/ic_follow_header.png
new file mode 100644
index 000000000..e1f60cc22
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_follow_header.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_follow_notif_header.png b/app/src/main/res/drawable-xxhdpi/ic_follow_notif_header.png
new file mode 100644
index 000000000..e1f60cc22
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_follow_notif_header.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_retweet_notif_header.png b/app/src/main/res/drawable-xxhdpi/ic_retweet_notif_header.png
new file mode 100644
index 000000000..0fc18c78a
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_retweet_notif_header.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_edit.png b/app/src/main/res/drawable-xxxhdpi/ic_edit.png
new file mode 100644
index 000000000..29046d95c
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_edit.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_fav_header.png b/app/src/main/res/drawable-xxxhdpi/ic_fav_header.png
new file mode 100644
index 000000000..154f6c446
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_fav_header.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_fav_notif_header.png b/app/src/main/res/drawable-xxxhdpi/ic_fav_notif_header.png
new file mode 100644
index 000000000..154f6c446
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_fav_notif_header.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_fiber_new.png b/app/src/main/res/drawable-xxxhdpi/ic_fiber_new.png
new file mode 100644
index 000000000..30dacde3c
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_fiber_new.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_follow_header.png b/app/src/main/res/drawable-xxxhdpi/ic_follow_header.png
new file mode 100644
index 000000000..ffa613901
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_follow_header.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_follow_notif_header.png b/app/src/main/res/drawable-xxxhdpi/ic_follow_notif_header.png
new file mode 100644
index 000000000..ffa613901
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_follow_notif_header.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_retweet.png b/app/src/main/res/drawable-xxxhdpi/ic_retweet_notif_header.png
similarity index 100%
rename from app/src/main/res/drawable-xxxhdpi/ic_retweet.png
rename to app/src/main/res/drawable-xxxhdpi/ic_retweet_notif_header.png
diff --git a/app/src/main/res/layout-sw600dp/activity_about.xml b/app/src/main/res/layout-sw600dp/activity_about.xml
index 1ebba5a63..f6cde8384 100644
--- a/app/src/main/res/layout-sw600dp/activity_about.xml
+++ b/app/src/main/res/layout-sw600dp/activity_about.xml
@@ -16,9 +16,9 @@
see .
-->
-
+
+
-
-
-
-
+
+
+
+
-
-
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|center_horizontal"
+ android:layout_marginLeft="150dp"
+ android:layout_marginRight="150dp"
+ android:divider="@null"
+ android:scrollbars="none"/>
+
+ android:layout_width="165dp"
+ android:layout_height="wrap_content"
+ android:text="@string/about_license_action"/>
@@ -111,12 +121,13 @@
android:gravity="center"
android:layout_width="200dp"
android:layout_height="wrap_content" />
+
+ android:layout_width="165dp"
+ android:layout_height="wrap_content"
+ android:text="@string/about_code_action"/>
@@ -136,12 +147,13 @@
android:layout_width="200dp"
android:text="@string/about_thekinrar"
android:layout_height="wrap_content" />
+
+ android:layout_width="165dp"
+ android:layout_height="wrap_content"
+ android:text="@string/about_thekinrar_action"/>
@@ -158,12 +170,13 @@
android:gravity="center"
android:layout_width="200dp"
android:layout_height="wrap_content" />
+
+ android:layout_width="165dp"
+ android:layout_height="wrap_content"
+ android:text="@string/about_yandex_action"/>
-
+ android:orientation="horizontal">
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
.
-->
-
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ >
+
+
+
+
+
+
-
-
+ android:textSize="16sp"/>
+
-
-
-
-
-
-
-
-
+ android:text="@string/thanks_text_dev"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ android:scrollbars="none"
+ android:divider="@null"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/fragment_settings_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml
similarity index 100%
rename from app/src/main/res/layout/fragment_settings_profile.xml
rename to app/src/main/res/layout/activity_edit_profile.xml
diff --git a/app/src/main/res/layout/activity_show_account.xml b/app/src/main/res/layout/activity_show_account.xml
index e7d621685..855778518 100644
--- a/app/src/main/res/layout/activity_show_account.xml
+++ b/app/src/main/res/layout/activity_show_account.xml
@@ -68,16 +68,32 @@
android:maxLines="1"
android:textSize="16sp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
-
+ android:orientation="horizontal">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_notification.xml b/app/src/main/res/layout/drawer_notification.xml
index f96ee8a07..df96784c4 100644
--- a/app/src/main/res/layout/drawer_notification.xml
+++ b/app/src/main/res/layout/drawer_notification.xml
@@ -35,7 +35,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/main_container"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ card_view:ignore="DisableBaselineAlignment">
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index 31c4440d1..99a6e462a 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -40,6 +40,12 @@
android:text="@string/set_share_validation"
android:layout_height="wrap_content" />
+
+
-
+
+
+
+
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml
index 0b9791aaf..d5b971d21 100644
--- a/app/src/main/res/layout/nav_header_main.xml
+++ b/app/src/main/res/layout/nav_header_main.xml
@@ -22,116 +22,130 @@
style="?attr/headerbg"
android:id="@+id/main_header_container"
android:gravity="bottom"
- android:orientation="vertical"
+ android:orientation="horizontal"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
-
+ android:orientation="vertical"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content">
+ android:layout_gravity="center_vertical"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
-
+
-
+ android:orientation="horizontal">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index cffc0e456..75f4ff56d 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -44,7 +44,7 @@
Bitte sag etwas
Sorry! Dein Gerät unterstützt keine Spracheingabe!
Alles löschen
-
+ Übersetzen toot.
Planen
Text- und Symbolgröße
@@ -281,6 +281,8 @@
Mehr anzeigen…
Sensibler Inhalt
Zeige vorherige Nachricht beim Antworten
+ Lokale Zeitleiste anzeigen
+ Öffentliche Zeitlinie anzeigen
Pfad:
Speichere Entwürfe automatisch
Benachrichtigen wenn …
@@ -291,6 +293,7 @@
ich erwähnt werde
Füge die URL bei Anhängen in toots hinzu
Zeige Bestätigungsdialog vor dem Teilen
+ Zeige Bestätigungsdialog vor dem zu favoriten hinzufügen
Erweiterte Einstellungen
Nur bei WLAN benachrichtigen
Leise Benachrichtigungen
@@ -335,6 +338,18 @@
- Nein
+ LED Farbe auswählen:
+
+
+ - Blue
+ - Cyan
+ - Magenta
+ - Green
+ - Red
+ - Yellow
+ - White
+
+
Blockiere
Nicht mehr blockieren
Stummschalten
@@ -408,7 +423,7 @@
Danke an Stéphane für das Logo.
- Danke an @PhotonQyv für seine Beiträge.
+ Danke an:
Neue Daten verfügbar sind! Wollen Sie Sie anzeigen?
Display-Zähler
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 66e3aa8db..e2c1fc2e4 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -44,6 +44,7 @@
Veuillez dire quelque chose
Désolé ! Votre appareil ne supporte pas la commande vocale !
Tout effacer
+ Traduire ce pouet.
Programmer
Taille du texte et des icônes
Modifier la taille du texte :
@@ -283,6 +284,8 @@
Afficher le contenu ?
Charger les images sensibles
Afficher le message précédent lors d\'une réponse
+ Afficher le fil local
+ Afficher le fil public
Destination :
Enregistrer les brouillons automatiquement
Afficher les compteurs
@@ -294,6 +297,7 @@
Notifier lorsque quelqu’un ajoute mes pouets à ses favoris
Notifier lorsque quelqu’un me mentionne
Confirmer avant de partager
+ Confirmer avant d\'ajouter aux favoris
Options avancées
Notifier en WIFI seulement
Utiliser le vibreur
@@ -329,6 +333,19 @@
- Google
- Non
+
+ Couleur de la LED :
+
+
+ - Bleu
+ - Cyan
+ - Magenta
+ - Vert
+ - Rouge
+ - Jaune
+ - Blanc
+
+
Actualités
Notifier lors de nouveaux pouets sur la page d\'accueil
Afficher les messages d\'erreur
@@ -406,6 +423,6 @@
- Merci à @PhotonQyv pour ses contributions.
+ Merci à :
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 1cad9380a..93a9ea743 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -133,6 +133,16 @@
@color/mastodonC3
+ #282c37
+ #313543
+ #393f4f
+ #494f5f
+
+ #efefef
+ #ebf3fa
+ #d9e1e8
+ #c9d1d8
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5c5cfe75b..ede1b727d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -44,7 +44,7 @@
Please, say something
Sorry! Your device does not support the voice input!
Delete all
-
+ Translate this toot.
Schedule
Text and icon sizes
Change the current text size:
@@ -288,6 +288,8 @@
Show more…
Sensitive content
Display previous message in responses
+ Display local timeline
+ Display federated timeline
Path:
Save drafts automatically
Display counters
@@ -299,6 +301,7 @@
Notify when someone favourites your status
Notify when someone mentions you
Show confirmation dialog before boosting
+ Show confirmation dialog before adding to favourites
Advanced settings
Notify in WIFI only
Silent Notifications
@@ -336,6 +339,18 @@
- No
+ Set LED colour:
+
+
+ - Blue
+ - Cyan
+ - Magenta
+ - Green
+ - Red
+ - Yellow
+ - White
+
+
News
Notify for new toots on the home timeline
Display error messages
@@ -416,6 +431,6 @@
- Thank you to @PhotonQyv for his contributions.
+ Thank you to:
\ No newline at end of file
diff --git a/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java
index 6e493ff4c..20f7f9061 100644
--- a/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java
+++ b/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java
@@ -15,26 +15,30 @@
package fr.gouv.etalab.mastodon.activities;
import android.annotation.SuppressLint;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
+import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SwitchCompat;
+import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.support.design.widget.NavigationView;
@@ -63,12 +67,13 @@ import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import java.io.File;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Stack;
-import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import fr.gouv.etalab.mastodon.asynctasks.RetrieveMetaDataAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
@@ -77,7 +82,9 @@ import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment;
import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment;
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
import fr.gouv.etalab.mastodon.helper.Helper;
+import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMetaDataInterface;
import fr.gouv.etalab.mastodon.interfaces.OnUpdateAccountInfoInterface;
+import fr.gouv.etalab.mastodon.services.StreamingService;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
@@ -102,7 +109,7 @@ import android.support.v4.app.FragmentStatePagerAdapter;
public class MainActivity extends AppCompatActivity
- implements NavigationView.OnNavigationItemSelectedListener, OnUpdateAccountInfoInterface, ProviderInstaller.ProviderInstallListener {
+ implements NavigationView.OnNavigationItemSelectedListener, OnUpdateAccountInfoInterface, ProviderInstaller.ProviderInstallListener, OnRetrieveMetaDataInterface {
private FloatingActionButton toot;
private HashMap tagTile = new HashMap<>();
@@ -122,6 +129,8 @@ public class MainActivity extends AppCompatActivity
private DisplayStatusFragment homeFragment;
private DisplayNotificationsFragment notificationsFragment;
private static final int ERROR_DIALOG_REQUEST_CODE = 97;
+ private BroadcastReceiver receive_data;
+ private boolean display_local, display_global;
public MainActivity() {
}
@@ -129,8 +138,48 @@ public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+
+ final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
+ receive_data = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Bundle b = intent.getExtras();
+ StreamingService.EventStreaming eventStreaming = (StreamingService.EventStreaming) intent.getSerializableExtra("eventStreaming");
+ if( eventStreaming == StreamingService.EventStreaming.NOTIFICATION){
+ if(notificationsFragment != null){
+ if(notificationsFragment.getUserVisibleHint() && isActivityVisible()){
+ notificationsFragment.showNewContent();
+ }else{
+ notificationsFragment.refresh();
+ }
+ }
+ }else if(eventStreaming == StreamingService.EventStreaming.UPDATE){
+ if( homeFragment != null){
+ if(homeFragment.getUserVisibleHint() && isActivityVisible()){
+ homeFragment.showNewContent();
+ }else{
+ homeFragment.refresh();
+ }
+ }
+ }else if(eventStreaming == StreamingService.EventStreaming.DELETE){
+ String id = b.getString("id");
+ if(notificationsFragment != null) {
+ if (notificationsFragment.getUserVisibleHint()) {
+
+ } else {
+
+ }
+ }
+ }
+ updateNotifCounter();
+ updateHomeCounter();
+ }
+ };
+ LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA));
+
+
ProviderInstaller.installIfNeededAsync(this, this);
- final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if( theme == Helper.THEME_LIGHT){
@@ -140,6 +189,9 @@ public class MainActivity extends AppCompatActivity
}
setContentView(R.layout.activity_main);
+ display_local = sharedpreferences.getBoolean(Helper.SET_DISPLAY_LOCAL, true);
+ display_global = sharedpreferences.getBoolean(Helper.SET_DISPLAY_GLOBAL, true);
+
//Test if user is still log in
if( ! Helper.isLoggedIn(getApplicationContext())) {
//It is not, the user is redirected to the login page
@@ -148,7 +200,16 @@ public class MainActivity extends AppCompatActivity
finish();
return;
}
-
+ SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
+ List accounts = new AccountDAO(getApplicationContext(), db).getAllAccount();
+ if( accounts != null){
+ for (Account account: accounts) {
+ Intent intent = new Intent(getApplicationContext(), StreamingService.class);
+ intent.putExtra("accountId", account.getId());
+ intent.putExtra("accountAcct", account.getAcct());
+ startService(intent);
+ }
+ }
Helper.fillMapEmoji(getApplicationContext());
//Here, the user is authenticated
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
@@ -197,8 +258,10 @@ public class MainActivity extends AppCompatActivity
tabLayout.addTab(tabHome);
tabLayout.addTab(tabNotif);
- tabLayout.addTab(tabLocal);
- tabLayout.addTab(tabPublic);
+ if( display_local)
+ tabLayout.addTab(tabLocal);
+ if( display_global)
+ tabLayout.addTab(tabPublic);
viewPager = (ViewPager) findViewById(R.id.viewpager);
main_app_container = (RelativeLayout) findViewById(R.id.main_app_container);
@@ -206,7 +269,6 @@ public class MainActivity extends AppCompatActivity
(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
- final boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
@@ -225,29 +287,32 @@ public class MainActivity extends AppCompatActivity
main_app_container.setVisibility(View.GONE);
viewPager.setVisibility(View.VISIBLE);
Helper.switchLayout(MainActivity.this);
- switch (tab.getPosition()){
- case 0:
- item = navigationView.getMenu().findItem(R.id.nav_home);
- fragmentTag = "HOME_TIMELINE";
- if( bubbles && homeFragment != null)
- homeFragment.refreshData();
- updateHomeCounter(0);
- break;
- case 1:
- fragmentTag = "NOTIFICATIONS";
- item = navigationView.getMenu().findItem(R.id.nav_notification);
- updateNotifCounter(0);
- if( bubbles && notificationsFragment != null)
- notificationsFragment.refreshData();
- break;
- case 2:
- fragmentTag = "LOCAL_TIMELINE";
- item = navigationView.getMenu().findItem(R.id.nav_local);
- break;
- case 3:
+ if( tab.getPosition() == 0) {
+ item = navigationView.getMenu().findItem(R.id.nav_home);
+ fragmentTag = "HOME_TIMELINE";
+ if (homeFragment != null && Helper.getUnreadToots(getApplicationContext(), null) > 0) {
+ homeFragment.refresh();
+ }
+ Helper.cacheStatusClear(getApplicationContext(), null);
+ updateHomeCounter();
+ }else if( tab.getPosition() == 1) {
+ fragmentTag = "NOTIFICATIONS";
+ item = navigationView.getMenu().findItem(R.id.nav_notification);
+ if (notificationsFragment != null && Helper.getUnreadNotifications(getApplicationContext(), null) > 0) {
+ notificationsFragment.refresh();
+ }
+ Helper.cacheNotificationsClear(getApplicationContext(), null);
+ updateNotifCounter();
+ }else if( tab.getPosition() == 2 && display_local) {
+
+ fragmentTag = "LOCAL_TIMELINE";
+ item = navigationView.getMenu().findItem(R.id.nav_local);
+ }else if( tab.getPosition() == 2 && !display_local) {
item = navigationView.getMenu().findItem(R.id.nav_global);
fragmentTag = "PUBLIC_TIMELINE";
- break;
+ }else if( tab.getPosition() == 3){
+ item = navigationView.getMenu().findItem(R.id.nav_global);
+ fragmentTag = "PUBLIC_TIMELINE";
}
if( item != null){
toolbarTitle.setText(item.getTitle());
@@ -284,9 +349,15 @@ public class MainActivity extends AppCompatActivity
Fragment fragment = (Fragment) viewPager.getAdapter().instantiateItem(viewPager, tab.getPosition());
switch (tab.getPosition()){
case 0:
+ DisplayStatusFragment displayStatusFragment = ((DisplayStatusFragment) fragment);
+ if( displayStatusFragment != null )
+ displayStatusFragment.scrollToTop();
+ Helper.cacheStatusClear(getApplicationContext(), null);
+ updateHomeCounter();
+ break;
case 2:
case 3:
- DisplayStatusFragment displayStatusFragment = ((DisplayStatusFragment) fragment);
+ displayStatusFragment = ((DisplayStatusFragment) fragment);
if( displayStatusFragment != null )
displayStatusFragment.scrollToTop();
break;
@@ -294,6 +365,8 @@ public class MainActivity extends AppCompatActivity
DisplayNotificationsFragment displayNotificationsFragment = ((DisplayNotificationsFragment) fragment);
if( displayNotificationsFragment != null )
displayNotificationsFragment.scrollToTop();
+ Helper.cacheNotificationsClear(getApplicationContext(), null);
+ updateNotifCounter();
break;
}
}
@@ -357,7 +430,11 @@ public class MainActivity extends AppCompatActivity
Intent intent = new Intent(MainActivity.this, SearchResultActivity.class);
intent.putExtra("search", query);
startActivity(intent);
- return true;
+ toolbar_search.setQuery("", false);
+ toolbar_search.setIconified(true);
+ toolbarTitle.setVisibility(View.VISIBLE);
+ pp_actionBar.setVisibility(View.VISIBLE);
+ return false;
}
@Override
public boolean onQueryTextChange(String newText) {
@@ -424,15 +501,14 @@ public class MainActivity extends AppCompatActivity
.diskCache(new UnlimitedDiskCache(cacheDir))
.build();
imageLoader.init(configImg);
- SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
options = new DisplayImageOptions.Builder().displayer(new RoundedBitmapDisplayer(90)).cacheInMemory(false)
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
headerLayout = navigationView.getHeaderView(0);
- String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
- Account account = new AccountDAO(getApplicationContext(), db).getAccountByToken(prefKeyOauthTokenT);
+ String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
+ Account account = new AccountDAO(getApplicationContext(), db).getAccountByID(userId);
updateHeaderAccountInfo(MainActivity.this, account, headerLayout, imageLoader, options);
loadPPInActionBar(MainActivity.this, account.getAvatar());
//Locked account can see follow request
@@ -548,6 +624,21 @@ public class MainActivity extends AppCompatActivity
String sharedSubject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
+ /* Some apps don't send the URL as the first part of the EXTRA_TEXT,
+ the BBC News app being one such, in this case find where the URL
+ is and strip that out into sharedText.
+ */
+ Matcher matcher;
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
+ matcher = Patterns.WEB_URL.matcher(sharedText);
+ else
+ matcher = Helper.urlPattern.matcher(sharedText);
+ while (matcher.find()){
+ int matchStart = matcher.start(1);
+ int matchEnd = matcher.end();
+ sharedText = sharedText.substring(matchStart, matchEnd);
+ }
+ new RetrieveMetaDataAsyncTask(sharedText, MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Intent intentToot = new Intent(getApplicationContext(), TootActivity.class);
Bundle b = new Bundle();
b.putString("sharedSubject", sharedSubject);
@@ -602,6 +693,7 @@ public class MainActivity extends AppCompatActivity
//Hide search bar on back pressed
if( !toolbar_search.isIconified()){
toolbar_search.setIconified(true);
+ return;
}
if( viewPager.getVisibility() == View.VISIBLE){
if (stackBack.size() > 1) {
@@ -803,22 +895,25 @@ public class MainActivity extends AppCompatActivity
@Override
public void onResume(){
super.onResume();
- SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
- if( bubbles){
- Handler handler = new Handler();
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {refreshData();}
- }, 1000);
- }
+ MainActivity.activityResumed();
+ updateNotifCounter();
+ updateHomeCounter();
//Proceeds to update of the authenticated account
if(Helper.isLoggedIn(getApplicationContext()))
new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ @Override
+ protected void onPause() {
+ super.onPause();
+ MainActivity.activityPaused();
+ }
-
+ @Override
+ public void onDestroy(){
+ super.onDestroy();
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data);
+ }
@SuppressWarnings("StatementWithEmptyBody")
@Override
@@ -841,20 +936,25 @@ public class MainActivity extends AppCompatActivity
}
toolbarTitle.setText(item.getTitle());
if (id == R.id.nav_home) {
- //noinspection ConstantConditions
- tabLayout.getTabAt(0).select();
+ if( tabLayout.getSelectedTabPosition() != 0)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(0).select();
return true;
} else if( id == R.id.nav_notification){
- //noinspection ConstantConditions
- tabLayout.getTabAt(1).select();
+ if( tabLayout.getSelectedTabPosition() != 1)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(1).select();
return true;
}else if (id == R.id.nav_local) {
- //noinspection ConstantConditions
- tabLayout.getTabAt(2).select();
+
+ if( tabLayout.getSelectedTabPosition() != 2)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(2).select();
return true;
} else if (id == R.id.nav_global) {
- //noinspection ConstantConditions
- tabLayout.getTabAt(3).select();
+ if( tabLayout.getSelectedTabPosition() != 3)
+ //noinspection ConstantConditions
+ tabLayout.getTabAt(3).select();
return true;
}
DisplayStatusFragment statusFragment;
@@ -998,6 +1098,17 @@ public class MainActivity extends AppCompatActivity
}
+ @Override
+ public void onRetrieveMetaData(boolean error, String image, String title, String description) {
+ if( !error) {
+ Intent intentSendImage = new Intent(Helper.RECEIVE_PICTURE);
+ intentSendImage.putExtra("image", image);
+ intentSendImage.putExtra("title", title);
+ intentSendImage.putExtra("description", description);
+ LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intentSendImage);
+ }
+ }
+
/**
* Page Adapter for settings
@@ -1021,26 +1132,29 @@ public class MainActivity extends AppCompatActivity
//Selection comes from another menu, no action to do
DisplayStatusFragment statusFragment;
Bundle bundle = new Bundle();
- switch (position) {
- case 0:
- homeFragment = new DisplayStatusFragment();
- bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.HOME);
- homeFragment.setArguments(bundle);
- return homeFragment;
- case 1:
- notificationsFragment = new DisplayNotificationsFragment();
- return notificationsFragment;
- case 2:
+ if (position == 0) {
+ homeFragment = new DisplayStatusFragment();
+ bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.HOME);
+ homeFragment.setArguments(bundle);
+ return homeFragment;
+ }else if( position == 1) {
+ notificationsFragment = new DisplayNotificationsFragment();
+ return notificationsFragment;
+ }else if( position == 2 && display_local) {
statusFragment = new DisplayStatusFragment();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.LOCAL);
statusFragment.setArguments(bundle);
return statusFragment;
- case 3:
+ }else if( position == 2 && !display_local){
statusFragment = new DisplayStatusFragment();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PUBLIC);
statusFragment.setArguments(bundle);
return statusFragment;
-
+ }else if (position == 3){
+ statusFragment = new DisplayStatusFragment();
+ bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.PUBLIC);
+ statusFragment.setArguments(bundle);
+ return statusFragment;
}
return null;
}
@@ -1051,40 +1165,8 @@ public class MainActivity extends AppCompatActivity
}
}
- private void refreshData(){
- final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
- String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
- SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
- Account account = new AccountDAO(getApplicationContext(), db).getAccountByToken(prefKeyOauthTokenT);
- if( account != null){
- String last_refresh = sharedpreferences.getString(Helper.LAST_BUBBLE_REFRESH_NOTIF + account.getId(), null);
- Date last_refresh_date = Helper.stringToDate(getApplicationContext(), last_refresh);
- if (last_refresh_date == null || (new Date().getTime() - last_refresh_date.getTime()) >= TimeUnit.SECONDS.toMillis(60)) {
-
- if( notificationsFragment != null ){
- notificationsFragment.update();
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_BUBBLE_REFRESH_NOTIF+ account.getId(),Helper.dateToString(getApplicationContext(), new Date()));
- editor.apply();
- }
- }
-
- last_refresh = sharedpreferences.getString(Helper.LAST_BUBBLE_REFRESH_HOME + account.getId(), null);
- last_refresh_date = Helper.stringToDate(getApplicationContext(), last_refresh);
-
- if (last_refresh_date == null || (new Date().getTime() - last_refresh_date.getTime()) >= TimeUnit.SECONDS.toMillis(60)) {
- if( homeFragment != null ){
- homeFragment.update();
- SharedPreferences.Editor editor = sharedpreferences.edit();
- editor.putString(Helper.LAST_BUBBLE_REFRESH_HOME+ account.getId(),Helper.dateToString(getApplicationContext(), new Date()));
- editor.apply();
- }
- }
- }
- }
-
- public void updateHomeCounter(int newHomeCount){
+ public void updateHomeCounter(){
if( tabLayout.getTabAt(0) == null )
return;
//noinspection ConstantConditions
@@ -1092,20 +1174,17 @@ public class MainActivity extends AppCompatActivity
if( tabHome == null)
return;
TextView tabCounterHome = (TextView) tabHome.findViewById(R.id.tab_counter);
- tabCounterHome.setText(String.valueOf(newHomeCount));
- if( newHomeCount > 0){
+ tabCounterHome.setText(String.valueOf(Helper.getUnreadToots(getApplicationContext(), null)));
+ if( Helper.getUnreadToots(getApplicationContext(), null) > 0){
//New data are available
//The fragment is not displayed, so the counter is displayed
- if( tabLayout.getSelectedTabPosition() != 0)
- tabCounterHome.setVisibility(View.VISIBLE);
- else
- tabCounterHome.setVisibility(View.GONE);
+ tabCounterHome.setVisibility(View.VISIBLE);
}else {
tabCounterHome.setVisibility(View.GONE);
}
}
- public void updateNotifCounter(int newNotifCount){
+ public void updateNotifCounter(){
if(tabLayout.getTabAt(1) == null)
return;
//noinspection ConstantConditions
@@ -1113,15 +1192,25 @@ public class MainActivity extends AppCompatActivity
if( tabNotif == null)
return;
TextView tabCounterNotif = (TextView) tabNotif.findViewById(R.id.tab_counter);
- tabCounterNotif.setText(String.valueOf(newNotifCount));
- if( newNotifCount > 0){
- if( tabLayout.getSelectedTabPosition() != 1)
- tabCounterNotif.setVisibility(View.VISIBLE);
- else
- tabCounterNotif.setVisibility(View.GONE);
+ tabCounterNotif.setText(String.valueOf(Helper.getUnreadNotifications(getApplicationContext(), null)));
+ if( Helper.getUnreadNotifications(getApplicationContext(), null) > 0){
+ tabCounterNotif.setVisibility(View.VISIBLE);
}else {
tabCounterNotif.setVisibility(View.GONE);
}
}
+ public static boolean isActivityVisible() {
+ return activityVisible;
+ }
+
+ private static void activityResumed() {
+ activityVisible = true;
+ }
+
+ private static void activityPaused() {
+ activityVisible = false;
+ }
+
+ private static boolean activityVisible;
}