commit
84f4357ce0
|
@ -15,9 +15,11 @@
|
||||||
package fr.gouv.etalab.mastodon.activities;
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -31,6 +33,7 @@ import android.support.design.widget.TabLayout;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
|
@ -67,8 +70,11 @@ import java.util.Locale;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.StreamingUserAsyncTask;
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask;
|
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
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.PatchBaseImageDownloader;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment;
|
||||||
|
@ -76,6 +82,7 @@ import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
import fr.gouv.etalab.mastodon.interfaces.OnUpdateAccountInfoInterface;
|
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.sqlite.Sqlite;
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
@ -119,14 +126,53 @@ public class MainActivity extends AppCompatActivity
|
||||||
|
|
||||||
private DisplayStatusFragment homeFragment;
|
private DisplayStatusFragment homeFragment;
|
||||||
private DisplayNotificationsFragment notificationsFragment;
|
private DisplayNotificationsFragment notificationsFragment;
|
||||||
|
private BroadcastReceiver receive_data;
|
||||||
|
private int newNotif, newHome;
|
||||||
public MainActivity() {
|
public MainActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
receive_data = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
Bundle b = intent.getExtras();
|
||||||
|
StreamingUserAsyncTask.EventStreaming eventStreaming = (StreamingUserAsyncTask.EventStreaming) intent.getSerializableExtra("eventStreaming");
|
||||||
|
|
||||||
|
if( eventStreaming == StreamingUserAsyncTask.EventStreaming.NOTIFICATION){
|
||||||
|
Notification notification = b.getParcelable("data");
|
||||||
|
if(notificationsFragment != null && notificationsFragment.getUserVisibleHint()){
|
||||||
|
notificationsFragment.updateData(notification);
|
||||||
|
}else{
|
||||||
|
newNotif++;
|
||||||
|
updateNotifCounter();
|
||||||
|
notificationsFragment.updateData(notification);
|
||||||
|
}
|
||||||
|
}else if(eventStreaming == StreamingUserAsyncTask.EventStreaming.UPDATE){
|
||||||
|
Status status = b.getParcelable("data");
|
||||||
|
if(homeFragment != null && homeFragment.getUserVisibleHint()){
|
||||||
|
homeFragment.updateData(status);
|
||||||
|
}else{
|
||||||
|
newHome++;
|
||||||
|
updateHomeCounter();
|
||||||
|
homeFragment.updateData(status);
|
||||||
|
}
|
||||||
|
}else if(eventStreaming == StreamingUserAsyncTask.EventStreaming.DELETE){
|
||||||
|
String id = b.getString("id");
|
||||||
|
if(notificationsFragment != null && notificationsFragment.getUserVisibleHint()){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA));
|
||||||
|
|
||||||
|
newNotif = 0;
|
||||||
|
newHome = 0;
|
||||||
|
|
||||||
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
|
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
|
||||||
|
|
||||||
final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
|
||||||
|
@ -145,7 +191,7 @@ public class MainActivity extends AppCompatActivity
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
startService(new Intent(getApplicationContext(), StreamingService.class));
|
||||||
Helper.fillMapEmoji(getApplicationContext());
|
Helper.fillMapEmoji(getApplicationContext());
|
||||||
//Here, the user is authenticated
|
//Here, the user is authenticated
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
|
@ -203,7 +249,6 @@ public class MainActivity extends AppCompatActivity
|
||||||
(getSupportFragmentManager(), tabLayout.getTabCount());
|
(getSupportFragmentManager(), tabLayout.getTabCount());
|
||||||
viewPager.setAdapter(adapter);
|
viewPager.setAdapter(adapter);
|
||||||
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
||||||
final boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
|
|
||||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTabSelected(TabLayout.Tab tab) {
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
|
@ -226,16 +271,19 @@ public class MainActivity extends AppCompatActivity
|
||||||
case 0:
|
case 0:
|
||||||
item = navigationView.getMenu().findItem(R.id.nav_home);
|
item = navigationView.getMenu().findItem(R.id.nav_home);
|
||||||
fragmentTag = "HOME_TIMELINE";
|
fragmentTag = "HOME_TIMELINE";
|
||||||
if( bubbles && homeFragment != null)
|
newHome = 0;
|
||||||
homeFragment.refreshData();
|
if( homeFragment != null)
|
||||||
updateHomeCounter(0);
|
homeFragment.refresh();
|
||||||
|
updateHomeCounter();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fragmentTag = "NOTIFICATIONS";
|
fragmentTag = "NOTIFICATIONS";
|
||||||
item = navigationView.getMenu().findItem(R.id.nav_notification);
|
item = navigationView.getMenu().findItem(R.id.nav_notification);
|
||||||
updateNotifCounter(0);
|
newNotif = 0;
|
||||||
if( bubbles && notificationsFragment != null)
|
|
||||||
notificationsFragment.refreshData();
|
if( notificationsFragment != null)
|
||||||
|
notificationsFragment.refresh();
|
||||||
|
updateNotifCounter();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
fragmentTag = "LOCAL_TIMELINE";
|
fragmentTag = "LOCAL_TIMELINE";
|
||||||
|
@ -805,22 +853,23 @@ public class MainActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
public void onResume(){
|
public void onResume(){
|
||||||
super.onResume();
|
super.onResume();
|
||||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
MainActivity.activityResumed();
|
||||||
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);
|
|
||||||
}
|
|
||||||
//Proceeds to update of the authenticated account
|
//Proceeds to update of the authenticated account
|
||||||
if(Helper.isLoggedIn(getApplicationContext()))
|
if(Helper.isLoggedIn(getApplicationContext()))
|
||||||
new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
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")
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
@Override
|
@Override
|
||||||
|
@ -1008,40 +1057,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);
|
public void updateHomeCounter(){
|
||||||
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){
|
|
||||||
if( tabLayout.getTabAt(0) == null )
|
if( tabLayout.getTabAt(0) == null )
|
||||||
return;
|
return;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
@ -1049,8 +1066,8 @@ public class MainActivity extends AppCompatActivity
|
||||||
if( tabHome == null)
|
if( tabHome == null)
|
||||||
return;
|
return;
|
||||||
TextView tabCounterHome = (TextView) tabHome.findViewById(R.id.tab_counter);
|
TextView tabCounterHome = (TextView) tabHome.findViewById(R.id.tab_counter);
|
||||||
tabCounterHome.setText(String.valueOf(newHomeCount));
|
tabCounterHome.setText(String.valueOf(newHome));
|
||||||
if( newHomeCount > 0){
|
if( newHome > 0){
|
||||||
//New data are available
|
//New data are available
|
||||||
//The fragment is not displayed, so the counter is displayed
|
//The fragment is not displayed, so the counter is displayed
|
||||||
if( tabLayout.getSelectedTabPosition() != 0)
|
if( tabLayout.getSelectedTabPosition() != 0)
|
||||||
|
@ -1062,7 +1079,7 @@ public class MainActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateNotifCounter(int newNotifCount){
|
public void updateNotifCounter(){
|
||||||
if(tabLayout.getTabAt(1) == null)
|
if(tabLayout.getTabAt(1) == null)
|
||||||
return;
|
return;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
@ -1070,8 +1087,8 @@ public class MainActivity extends AppCompatActivity
|
||||||
if( tabNotif == null)
|
if( tabNotif == null)
|
||||||
return;
|
return;
|
||||||
TextView tabCounterNotif = (TextView) tabNotif.findViewById(R.id.tab_counter);
|
TextView tabCounterNotif = (TextView) tabNotif.findViewById(R.id.tab_counter);
|
||||||
tabCounterNotif.setText(String.valueOf(newNotifCount));
|
tabCounterNotif.setText(String.valueOf(newNotif));
|
||||||
if( newNotifCount > 0){
|
if( newNotif > 0){
|
||||||
if( tabLayout.getSelectedTabPosition() != 1)
|
if( tabLayout.getSelectedTabPosition() != 1)
|
||||||
tabCounterNotif.setVisibility(View.VISIBLE);
|
tabCounterNotif.setVisibility(View.VISIBLE);
|
||||||
else
|
else
|
||||||
|
@ -1081,4 +1098,18 @@ public class MainActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isActivityVisible() {
|
||||||
|
return activityVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void activityResumed() {
|
||||||
|
activityVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void activityPaused() {
|
||||||
|
activityVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean activityVisible;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher"
|
android:roundIcon="@mipmap/ic_launcher"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppThemeDark">
|
android:theme="@style/AppThemeDark">
|
||||||
|
<service
|
||||||
|
android:name="fr.gouv.etalab.mastodon.services.StreamingService"
|
||||||
|
android:exported="false"/>
|
||||||
<activity
|
<activity
|
||||||
android:name="fr.gouv.etalab.mastodon.activities.MainActivity"
|
android:name="fr.gouv.etalab.mastodon.activities.MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
|
|
@ -17,8 +17,7 @@ import android.app.Application;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import com.evernote.android.job.JobManager;
|
import com.evernote.android.job.JobManager;
|
||||||
import fr.gouv.etalab.mastodon.jobs.ApplicationJob;
|
import fr.gouv.etalab.mastodon.jobs.ApplicationJob;
|
||||||
import fr.gouv.etalab.mastodon.jobs.HomeTimelineSyncJob;
|
import fr.gouv.etalab.mastodon.jobs.StreamingSyncJob;
|
||||||
import fr.gouv.etalab.mastodon.jobs.NotificationsSyncJob;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Thomas on 29/04/2017.
|
* Created by Thomas on 29/04/2017.
|
||||||
|
@ -33,8 +32,7 @@ public class MainApplication extends Application{
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
JobManager.create(this).addJobCreator(new ApplicationJob());
|
JobManager.create(this).addJobCreator(new ApplicationJob());
|
||||||
JobManager.instance().getConfig().setVerbose(false);
|
JobManager.instance().getConfig().setVerbose(false);
|
||||||
NotificationsSyncJob.schedule(false);
|
StreamingSyncJob.schedule(true);
|
||||||
HomeTimelineSyncJob.schedule(false);
|
|
||||||
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
|
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
|
||||||
StrictMode.setVmPolicy(builder.build());
|
StrictMode.setVmPolicy(builder.build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,9 @@
|
||||||
package fr.gouv.etalab.mastodon.asynctasks;
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import fr.gouv.etalab.mastodon.client.API;
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
import fr.gouv.etalab.mastodon.client.APIResponse;
|
import fr.gouv.etalab.mastodon.client.APIResponse;
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
|
||||||
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,8 +56,6 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
this.max_id = max_id;
|
this.max_id = max_id;
|
||||||
this.listener = onRetrieveFeedsInterface;
|
this.listener = onRetrieveFeedsInterface;
|
||||||
this.refreshData = true;
|
this.refreshData = true;
|
||||||
updateTimeRefresh();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RetrieveFeedsAsyncTask(Context context, Type action, String targetedID, String max_id, boolean showMediaOnly, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
public RetrieveFeedsAsyncTask(Context context, Type action, String targetedID, String max_id, boolean showMediaOnly, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
||||||
|
@ -73,7 +66,6 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
this.targetedID = targetedID;
|
this.targetedID = targetedID;
|
||||||
this.showMediaOnly = showMediaOnly;
|
this.showMediaOnly = showMediaOnly;
|
||||||
this.refreshData = true;
|
this.refreshData = true;
|
||||||
updateTimeRefresh();
|
|
||||||
}
|
}
|
||||||
public RetrieveFeedsAsyncTask(Context context, Type action, String tag, String targetedID, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
public RetrieveFeedsAsyncTask(Context context, Type action, String tag, String targetedID, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface){
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -83,17 +75,8 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
this.targetedID = targetedID;
|
this.targetedID = targetedID;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.refreshData = true;
|
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
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
|
@ -134,14 +117,4 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
protected void onPostExecute(Void result) {
|
protected void onPostExecute(Void result) {
|
||||||
listener.onRetrieveFeeds(apiResponse, refreshData);
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,9 @@
|
||||||
package fr.gouv.etalab.mastodon.asynctasks;
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import fr.gouv.etalab.mastodon.client.API;
|
import fr.gouv.etalab.mastodon.client.API;
|
||||||
import fr.gouv.etalab.mastodon.client.APIResponse;
|
import fr.gouv.etalab.mastodon.client.APIResponse;
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
|
||||||
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,20 +46,8 @@ public class RetrieveNotificationsAsyncTask extends AsyncTask<Void, Void, Void>
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.refreshData = true;
|
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
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
|
@ -82,10 +65,4 @@ public class RetrieveNotificationsAsyncTask extends AsyncTask<Void, Void, Void>
|
||||||
listener.onRetrieveNotifications(apiResponse, acct, userId, refreshData);
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
/* 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 <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.asynctasks;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveStreamingInterface;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 28/08/2017.
|
||||||
|
* Calls user streaming api
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class StreamingUserAsyncTask extends AsyncTask {
|
||||||
|
|
||||||
|
private String instance, token, acct, userId;
|
||||||
|
private OnRetrieveStreamingInterface listener;
|
||||||
|
private static HashMap<String, HttpURLConnection> connectionHashMap;
|
||||||
|
private EventStreaming lastEvent;
|
||||||
|
|
||||||
|
|
||||||
|
public StreamingUserAsyncTask(String instance, String token, String acct, String userId, OnRetrieveStreamingInterface onRetrieveStreamingInterface){
|
||||||
|
this.instance = instance;
|
||||||
|
this.token = token;
|
||||||
|
this.acct = acct;
|
||||||
|
this.userId = userId;
|
||||||
|
this.listener = onRetrieveStreamingInterface;
|
||||||
|
}
|
||||||
|
public enum EventStreaming{
|
||||||
|
UPDATE,
|
||||||
|
NOTIFICATION,
|
||||||
|
DELETE,
|
||||||
|
NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object doInBackground(Object[] params){
|
||||||
|
if( connectionHashMap == null)
|
||||||
|
connectionHashMap = new HashMap<>();
|
||||||
|
|
||||||
|
boolean connectionAlive = false;
|
||||||
|
if( connectionHashMap.get(acct+userId) != null) {
|
||||||
|
try {
|
||||||
|
connectionAlive = (connectionHashMap.get(acct + userId).getResponseCode() == 200);
|
||||||
|
} catch (IOException e) {
|
||||||
|
connectionAlive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !connectionAlive) {
|
||||||
|
try {
|
||||||
|
URL url = new URL("https://" + this.instance + "/api/v1/streaming/user");
|
||||||
|
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||||
|
urlConnection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
urlConnection.setRequestProperty("Authorization", "Bearer " + this.token);
|
||||||
|
urlConnection.setRequestProperty("Connection", "Keep-Alive");
|
||||||
|
urlConnection.setRequestProperty("Keep-Alive", "header");
|
||||||
|
connectionHashMap.put(acct+userId, urlConnection);
|
||||||
|
|
||||||
|
InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
|
||||||
|
readStream(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readStream(InputStream inputStream) {
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try{
|
||||||
|
reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
String event;
|
||||||
|
EventStreaming eventStreaming = null;
|
||||||
|
while((event = reader.readLine()) != null){
|
||||||
|
if( lastEvent == EventStreaming.NONE || lastEvent == null) {
|
||||||
|
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{
|
||||||
|
event = event.replace("data: ","");
|
||||||
|
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 + "}";
|
||||||
|
}
|
||||||
|
lastEvent = EventStreaming.NONE;
|
||||||
|
try {
|
||||||
|
JSONObject eventJson = new JSONObject(event);
|
||||||
|
listener.onRetrieveStreaming(eventStreaming, eventJson, acct, userId);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}finally {
|
||||||
|
if(reader != null){
|
||||||
|
try{
|
||||||
|
reader.close();
|
||||||
|
}catch (IOException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -188,12 +188,12 @@ public class API {
|
||||||
get("/accounts/verify_credentials", null, new JsonHttpResponseHandler() {
|
get("/accounts/verify_credentials", null, new JsonHttpResponseHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
account = parseAccountResponse(response);
|
account = parseAccountResponse(context, response);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
|
||||||
try {
|
try {
|
||||||
account = parseAccountResponse(response.getJSONObject(0));
|
account = parseAccountResponse(context, response.getJSONObject(0));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -217,12 +217,12 @@ public class API {
|
||||||
get(String.format("/accounts/%s",accountId), null, new JsonHttpResponseHandler() {
|
get(String.format("/accounts/%s",accountId), null, new JsonHttpResponseHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
account = parseAccountResponse(response);
|
account = parseAccountResponse(context, response);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
|
||||||
try {
|
try {
|
||||||
account = parseAccountResponse(response.getJSONObject(0));
|
account = parseAccountResponse(context, response.getJSONObject(0));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ public class API {
|
||||||
get(String.format("/accounts/%s/statuses", accountId), params, new JsonHttpResponseHandler() {
|
get(String.format("/accounts/%s/statuses", accountId), params, new JsonHttpResponseHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Status status = parseStatuses(response);
|
Status status = parseStatuses(context, response);
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -365,7 +365,7 @@ public class API {
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
Status status = parseStatuses(response);
|
Status status = parseStatuses(context, response);
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -445,7 +445,7 @@ public class API {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Status status = parseStatuses(response);
|
Status status = parseStatuses(context, response);
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -500,7 +500,7 @@ public class API {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Status status = parseStatuses(response);
|
Status status = parseStatuses(context, response);
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -557,7 +557,7 @@ public class API {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Status status = parseStatuses(response);
|
Status status = parseStatuses(context, response);
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -641,7 +641,7 @@ public class API {
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
Account account = parseAccountResponse(response);
|
Account account = parseAccountResponse(context, response);
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -692,7 +692,7 @@ public class API {
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
Account account = parseAccountResponse(response);
|
Account account = parseAccountResponse(context, response);
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
@ -741,7 +741,7 @@ public class API {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Status status = parseStatuses(response);
|
Status status = parseStatuses(context, response);
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -945,7 +945,7 @@ public class API {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Status statusreturned = parseStatuses(response);
|
Status statusreturned = parseStatuses(context, response);
|
||||||
statuses.add(statusreturned);
|
statuses.add(statusreturned);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -1041,7 +1041,7 @@ public class API {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
Notification notification = parseNotificationResponse(response);
|
Notification notification = parseNotificationResponse(context, response);
|
||||||
notifications.add(notification);
|
notifications.add(notification);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -1130,7 +1130,7 @@ public class API {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
accounts = new ArrayList<>();
|
accounts = new ArrayList<>();
|
||||||
account = parseAccountResponse(response);
|
account = parseAccountResponse(context, response);
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -1170,7 +1170,7 @@ public class API {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
accounts = new ArrayList<>();
|
accounts = new ArrayList<>();
|
||||||
account = parseAccountResponse(response);
|
account = parseAccountResponse(context, response);
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
apiResponse.setSince_id(findSinceId(headers));
|
apiResponse.setSince_id(findSinceId(headers));
|
||||||
apiResponse.setMax_id(findMaxId(headers));
|
apiResponse.setMax_id(findMaxId(headers));
|
||||||
|
@ -1236,7 +1236,7 @@ public class API {
|
||||||
while (i < jsonArray.length() ){
|
while (i < jsonArray.length() ){
|
||||||
|
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
Status status = parseStatuses(resobj);
|
Status status = parseStatuses(context, resobj);
|
||||||
i++;
|
i++;
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
}
|
}
|
||||||
|
@ -1253,7 +1253,7 @@ public class API {
|
||||||
* @return Status
|
* @return Status
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("InfiniteRecursion")
|
@SuppressWarnings("InfiniteRecursion")
|
||||||
private Status parseStatuses(JSONObject resobj){
|
public static Status parseStatuses(Context context, JSONObject resobj){
|
||||||
Status status = new Status();
|
Status status = new Status();
|
||||||
try {
|
try {
|
||||||
status.setId(resobj.get("id").toString());
|
status.setId(resobj.get("id").toString());
|
||||||
|
@ -1315,14 +1315,14 @@ public class API {
|
||||||
}
|
}
|
||||||
status.setTags(tags);
|
status.setTags(tags);
|
||||||
|
|
||||||
status.setAccount(parseAccountResponse(resobj.getJSONObject("account")));
|
status.setAccount(parseAccountResponse(context, resobj.getJSONObject("account")));
|
||||||
status.setContent(resobj.get("content").toString());
|
status.setContent(resobj.get("content").toString());
|
||||||
status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString()));
|
status.setFavourites_count(Integer.valueOf(resobj.get("favourites_count").toString()));
|
||||||
status.setReblogs_count(Integer.valueOf(resobj.get("reblogs_count").toString()));
|
status.setReblogs_count(Integer.valueOf(resobj.get("reblogs_count").toString()));
|
||||||
status.setReblogged(Boolean.valueOf(resobj.get("reblogged").toString()));
|
status.setReblogged(Boolean.valueOf(resobj.get("reblogged").toString()));
|
||||||
status.setFavourited(Boolean.valueOf(resobj.get("favourited").toString()));
|
status.setFavourited(Boolean.valueOf(resobj.get("favourited").toString()));
|
||||||
try{
|
try{
|
||||||
status.setReblog(parseStatuses(resobj.getJSONObject("reblog")));
|
status.setReblog(parseStatuses(context, resobj.getJSONObject("reblog")));
|
||||||
}catch (Exception ignored){}
|
}catch (Exception ignored){}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -1355,7 +1355,7 @@ public class API {
|
||||||
* @param resobj JSONObject
|
* @param resobj JSONObject
|
||||||
* @return Account
|
* @return Account
|
||||||
*/
|
*/
|
||||||
private Account parseAccountResponse(JSONObject resobj){
|
private static Account parseAccountResponse(Context context, JSONObject resobj){
|
||||||
|
|
||||||
Account account = new Account();
|
Account account = new Account();
|
||||||
try {
|
try {
|
||||||
|
@ -1392,7 +1392,7 @@ public class API {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < jsonArray.length() ) {
|
while (i < jsonArray.length() ) {
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
Account account = parseAccountResponse(resobj);
|
Account account = parseAccountResponse(context, resobj);
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -1416,7 +1416,7 @@ public class API {
|
||||||
Account account = null;
|
Account account = null;
|
||||||
while (i < jsonArray.length() ) {
|
while (i < jsonArray.length() ) {
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
account = parseAccountResponse(resobj);
|
account = parseAccountResponse(context, resobj);
|
||||||
if( account.getAcct().contains(Helper.DEVELOPER_INSTANCE))
|
if( account.getAcct().contains(Helper.DEVELOPER_INSTANCE))
|
||||||
accounts.add(account);
|
accounts.add(account);
|
||||||
i++;
|
i++;
|
||||||
|
@ -1500,16 +1500,16 @@ public class API {
|
||||||
* @param resobj JSONObject
|
* @param resobj JSONObject
|
||||||
* @return Account
|
* @return Account
|
||||||
*/
|
*/
|
||||||
private Notification parseNotificationResponse(JSONObject resobj){
|
public static Notification parseNotificationResponse(Context context, JSONObject resobj){
|
||||||
|
|
||||||
Notification notification = new Notification();
|
Notification notification = new Notification();
|
||||||
try {
|
try {
|
||||||
notification.setId(resobj.get("id").toString());
|
notification.setId(resobj.get("id").toString());
|
||||||
notification.setType(resobj.get("type").toString());
|
notification.setType(resobj.get("type").toString());
|
||||||
notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").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{
|
try{
|
||||||
notification.setStatus(parseStatuses(resobj.getJSONObject("status")));
|
notification.setStatus(parseStatuses(context, resobj.getJSONObject("status")));
|
||||||
}catch (Exception ignored){}
|
}catch (Exception ignored){}
|
||||||
notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString()));
|
notification.setCreated_at(Helper.mstStringToDate(context, resobj.get("created_at").toString()));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -1531,7 +1531,7 @@ public class API {
|
||||||
while (i < jsonArray.length() ) {
|
while (i < jsonArray.length() ) {
|
||||||
|
|
||||||
JSONObject resobj = jsonArray.getJSONObject(i);
|
JSONObject resobj = jsonArray.getJSONObject(i);
|
||||||
Notification notification = parseNotificationResponse(resobj);
|
Notification notification = parseNotificationResponse(context, resobj);
|
||||||
notifications.add(notification);
|
notifications.add(notification);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,16 @@
|
||||||
package fr.gouv.etalab.mastodon.client.Entities;
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Thomas on 23/04/2017.
|
* Created by Thomas on 23/04/2017.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Notification {
|
public class Notification implements Parcelable {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String type;
|
private String type;
|
||||||
|
@ -29,6 +32,27 @@ public class Notification {
|
||||||
private Account account;
|
private Account account;
|
||||||
private Status status;
|
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<Notification> CREATOR = new Creator<Notification>() {
|
||||||
|
@Override
|
||||||
|
public Notification createFromParcel(Parcel in) {
|
||||||
|
return new Notification(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Notification[] newArray(int size) {
|
||||||
|
return new Notification[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -68,4 +92,17 @@ public class Notification {
|
||||||
public void setStatus(Status status) {
|
public void setStatus(Status status) {
|
||||||
this.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.util.List;
|
||||||
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
||||||
import fr.gouv.etalab.mastodon.client.APIResponse;
|
import fr.gouv.etalab.mastodon.client.APIResponse;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
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.NotificationsListAdapter;
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
||||||
|
@ -145,13 +146,6 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
|
||||||
for(Notification notification: notificationsTmp){
|
for(Notification notification: notificationsTmp){
|
||||||
notifications.add(notification);
|
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);
|
notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
|
||||||
lv_notifications.setAdapter(notificationsListAdapter);
|
lv_notifications.setAdapter(notificationsListAdapter);
|
||||||
if( notificationsTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
|
if( notificationsTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
|
||||||
|
@ -205,64 +199,11 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
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<Notification> notifications = apiResponse.getNotifications();
|
List<Notification> notifications = apiResponse.getNotifications();
|
||||||
since_id = apiResponse.getSince_id();
|
since_id = apiResponse.getSince_id();
|
||||||
max_id = apiResponse.getMax_id();
|
max_id = apiResponse.getMax_id();
|
||||||
//The initial call comes from a classic tab refresh
|
//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() && firstLoad) {
|
|
||||||
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<Notification> notifications, String max_id, String since_id){
|
|
||||||
flag_loading = (max_id == null );
|
flag_loading = (max_id == null );
|
||||||
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
|
||||||
if( !swiped && firstLoad && (notifications == null || notifications.size() == 0))
|
if( !swiped && firstLoad && (notifications == null || notifications.size() == 0))
|
||||||
textviewNoAction.setVisibility(View.VISIBLE);
|
textviewNoAction.setVisibility(View.VISIBLE);
|
||||||
else
|
else
|
||||||
|
@ -284,11 +225,10 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
|
||||||
//Store last notification id to avoid to notify for those that have been already seen
|
//Store last notification id to avoid to notify for those that have been already seen
|
||||||
if( notifications != null && notifications.size() > 0) {
|
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
|
//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();
|
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
Account currentAccount = new AccountDAO(context, db).getAccountByID(userId);
|
Account currentAccount = new AccountDAO(context, db).getAccountByID(userId);
|
||||||
if( currentAccount != null && firstLoad && since_id != null){
|
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(), since_id);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
@ -296,40 +236,40 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve
|
||||||
firstLoad = false;
|
firstLoad = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void scrollToTop(){
|
public void scrollToTop(){
|
||||||
if( lv_notifications != null)
|
if( lv_notifications != null)
|
||||||
lv_notifications.setAdapter(notificationsListAdapter);
|
lv_notifications.setAdapter(notificationsListAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(){
|
|
||||||
if( context != null){
|
public void updateData(Notification notification){
|
||||||
asyncTask = new RetrieveNotificationsAsyncTask(context, null, null, null, null, null, false, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
if( notificationsTmp != null && notificationsTmp.size() > 0){
|
||||||
|
notificationsTmp.add(0,notification);
|
||||||
|
}else {
|
||||||
|
notificationsTmp = new ArrayList<>();
|
||||||
|
for(Notification notificationTmp: this.notifications){
|
||||||
|
notificationsTmp.add(notificationTmp);
|
||||||
}
|
}
|
||||||
|
notificationsTmp.add(0,notification);
|
||||||
}
|
}
|
||||||
|
new_data.setVisibility(View.VISIBLE);
|
||||||
public void refreshData(){
|
}
|
||||||
|
public void refresh(){
|
||||||
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
if( notificationsTmp != null){
|
||||||
|
|
||||||
if(context != null && this.notificationsTmp != null && this.notificationsTmp.size() > 0){
|
|
||||||
boolean isOnWifi = Helper.isOnWIFI(context);
|
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);
|
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
|
||||||
notifications = new ArrayList<>();
|
notifications = new ArrayList<>();
|
||||||
for(Notification notification: this.notificationsTmp){
|
for(Notification notification: notificationsTmp){
|
||||||
notifications.add(notification);
|
notifications.add(notification);
|
||||||
}
|
}
|
||||||
if( textviewNoAction.getVisibility() == View.VISIBLE)
|
|
||||||
textviewNoAction.setVisibility(View.GONE);
|
|
||||||
notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
|
notificationsListAdapter = new NotificationsListAdapter(context,isOnWifi, behaviorWithAttachments, notifications);
|
||||||
lv_notifications.setAdapter(notificationsListAdapter);
|
lv_notifications.setAdapter(notificationsListAdapter);
|
||||||
this.notificationsTmp = new ArrayList<>();
|
if( notificationsTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
|
||||||
}
|
textviewNoAction.setVisibility(View.GONE);
|
||||||
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);
|
||||||
|
notificationsTmp = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,13 +229,6 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
||||||
for(Status status: statusesTmp){
|
for(Status status: statusesTmp){
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
}
|
}
|
||||||
//The user clicked on the banner to refresh values so, the pointer is changed
|
|
||||||
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.apply();
|
|
||||||
}
|
|
||||||
if( statusesTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
|
if( statusesTmp.size() > 0 && textviewNoAction.getVisibility() == View.VISIBLE)
|
||||||
textviewNoAction.setVisibility(View.GONE);
|
textviewNoAction.setVisibility(View.GONE);
|
||||||
statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
|
statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
|
||||||
|
@ -271,11 +264,6 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
||||||
for(Status status: statusesTmp){
|
for(Status status: statusesTmp){
|
||||||
statuses.add(status);
|
statuses.add(status);
|
||||||
}
|
}
|
||||||
//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);
|
statusListAdapter = new StatusListAdapter(context, type, targetedId, isOnWifi, behaviorWithAttachments, positionSpinnerTrans, statuses);
|
||||||
lv_status.setAdapter(statusListAdapter);
|
lv_status.setAdapter(statusListAdapter);
|
||||||
statusesTmp = new ArrayList<>();
|
statusesTmp = new ArrayList<>();
|
||||||
|
@ -315,72 +303,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
||||||
List<Status> statuses = apiResponse.getStatuses();
|
List<Status> statuses = apiResponse.getStatuses();
|
||||||
since_id = apiResponse.getSince_id();
|
since_id = apiResponse.getSince_id();
|
||||||
max_id = apiResponse.getMax_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() && firstLoad) {
|
|
||||||
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<Status> statuses, String max_id, String since_id){
|
|
||||||
flag_loading = (max_id == null );
|
flag_loading = (max_id == null );
|
||||||
if( !swiped && firstLoad && (statuses == null || statuses.size() == 0))
|
if( !swiped && firstLoad && (statuses == null || statuses.size() == 0))
|
||||||
textviewNoAction.setVisibility(View.VISIBLE);
|
textviewNoAction.setVisibility(View.VISIBLE);
|
||||||
|
@ -401,7 +324,6 @@ 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
|
//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 ){
|
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
|
//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);
|
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
|
||||||
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
@ -416,7 +338,6 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
||||||
|
|
||||||
//Retrieves replies
|
//Retrieves replies
|
||||||
if(statuses != null && statuses.size() > 0 && type == RetrieveFeedsAsyncTask.Type.HOME ) {
|
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, true);
|
||||||
//Retrieves attached replies to a toot
|
//Retrieves attached replies to a toot
|
||||||
if (showPreview) {
|
if (showPreview) {
|
||||||
|
@ -425,6 +346,37 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateData(Status status){
|
||||||
|
if( statusesTmp != null && statusesTmp.size() > 0){
|
||||||
|
statusesTmp.add(0,status);
|
||||||
|
}else {
|
||||||
|
statusesTmp = new ArrayList<>();
|
||||||
|
for(Status statusTmp: this.statuses){
|
||||||
|
statusesTmp.add(statusTmp);
|
||||||
|
}
|
||||||
|
statusesTmp.add(0,status);
|
||||||
|
}
|
||||||
|
new_data.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(){
|
||||||
|
if( statusesTmp != null){
|
||||||
|
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);
|
||||||
|
statuses = new ArrayList<>();
|
||||||
|
for(Status status: statusesTmp){
|
||||||
|
statuses.add(status);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
public void scrollToTop(){
|
public void scrollToTop(){
|
||||||
if( lv_status != null)
|
if( lv_status != null)
|
||||||
lv_status.setAdapter(statusListAdapter);
|
lv_status.setAdapter(statusListAdapter);
|
||||||
|
@ -444,36 +396,4 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
|
||||||
}
|
}
|
||||||
statusListAdapter.notifyDataSetChanged();
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
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);
|
final CheckBox set_show_error_messages = (CheckBox) rootView.findViewById(R.id.set_show_error_messages);
|
||||||
set_show_error_messages.setChecked(show_error_messages);
|
set_show_error_messages.setChecked(show_error_messages);
|
||||||
|
|
|
@ -178,10 +178,6 @@ public class Helper {
|
||||||
public static final String SHOW_BATTERY_SAVER_MESSAGE = "show_battery_saver_message";
|
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_NOTIFICATION_MAX_ID = "last_notification_max_id";
|
||||||
public static final String LAST_HOMETIMELINE_MAX_ID = "last_hometimeline_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";
|
public static final String CLIP_BOARD = "clipboard";
|
||||||
//Notifications
|
//Notifications
|
||||||
public static final int NOTIFICATION_INTENT = 1;
|
public static final int NOTIFICATION_INTENT = 1;
|
||||||
|
@ -205,7 +201,6 @@ public class Helper {
|
||||||
public static final String SET_ICON_SIZE = "set_icon_size";
|
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 = "set_preview_replies";
|
||||||
public static final String SET_PREVIEW_REPLIES_PP = "set_preview_replies_pp";
|
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_TRANSLATOR = "set_translator";
|
||||||
|
|
||||||
public static final int ATTACHMENT_ALWAYS = 1;
|
public static final int ATTACHMENT_ALWAYS = 1;
|
||||||
|
@ -242,8 +237,7 @@ public class Helper {
|
||||||
|
|
||||||
|
|
||||||
//Refresh job
|
//Refresh job
|
||||||
public static final int MINUTES_BETWEEN_NOTIFICATIONS_REFRESH = 15;
|
public static final int MINUTES_BETWEEN_STREAMING_CHECK_ALIVE = 15;
|
||||||
public static final int MINUTES_BETWEEN_HOME_TIMELINE = 30;
|
|
||||||
|
|
||||||
//Intent
|
//Intent
|
||||||
public static final String INTENT_ACTION = "intent_action";
|
public static final String INTENT_ACTION = "intent_action";
|
||||||
|
@ -251,6 +245,7 @@ public class Helper {
|
||||||
//Receiver
|
//Receiver
|
||||||
public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account";
|
public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account";
|
||||||
public static final String HEADER_ACCOUNT = "header_account";
|
public static final String HEADER_ACCOUNT = "header_account";
|
||||||
|
public static final String RECEIVE_DATA = "receive_data";
|
||||||
|
|
||||||
//User agent
|
//User agent
|
||||||
public static final String USER_AGENT = "Mastalab/"+ BuildConfig.VERSION_NAME + " Android/"+ Build.VERSION.RELEASE;
|
public static final String USER_AGENT = "Mastalab/"+ BuildConfig.VERSION_NAME + " Android/"+ Build.VERSION.RELEASE;
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses>. */
|
||||||
|
package fr.gouv.etalab.mastodon.interfaces;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.StreamingUserAsyncTask;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 28/08/2017.
|
||||||
|
* Interface when event from streaming api has been retrieved
|
||||||
|
*/
|
||||||
|
public interface OnRetrieveStreamingInterface {
|
||||||
|
void onRetrieveStreaming(StreamingUserAsyncTask.EventStreaming event, JSONObject response, String acct, String userId);
|
||||||
|
}
|
|
@ -26,10 +26,8 @@ public class ApplicationJob implements JobCreator {
|
||||||
@Override
|
@Override
|
||||||
public Job create(String tag) {
|
public Job create(String tag) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case NotificationsSyncJob.NOTIFICATION_REFRESH:
|
case StreamingSyncJob.STREAMING:
|
||||||
return new NotificationsSyncJob();
|
return new StreamingSyncJob();
|
||||||
case HomeTimelineSyncJob.HOME_TIMELINE:
|
|
||||||
return new HomeTimelineSyncJob();
|
|
||||||
case ScheduledTootsSyncJob.SCHEDULED_TOOT:
|
case ScheduledTootsSyncJob.SCHEDULED_TOOT:
|
||||||
return new ScheduledTootsSyncJob();
|
return new ScheduledTootsSyncJob();
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,204 +0,0 @@
|
||||||
package fr.gouv.etalab.mastodon.jobs;
|
|
||||||
/* 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 <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
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.AsyncTask;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.evernote.android.job.Job;
|
|
||||||
import com.evernote.android.job.JobManager;
|
|
||||||
import com.evernote.android.job.JobRequest;
|
|
||||||
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
|
||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
|
||||||
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
|
||||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.RetrieveHomeTimelineServiceAsyncTask;
|
|
||||||
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.client.PatchBaseImageDownloader;
|
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
|
||||||
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveHomeTimelineServiceInterface;
|
|
||||||
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.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 20/05/2017.
|
|
||||||
* Notifications for home timeline job
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class HomeTimelineSyncJob extends Job implements OnRetrieveHomeTimelineServiceInterface{
|
|
||||||
|
|
||||||
static final String HOME_TIMELINE = "home_timeline";
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
protected Result onRunJob(Params params) {
|
|
||||||
callAsynchronousTask();
|
|
||||||
return Result.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static int schedule(boolean updateCurrent){
|
|
||||||
|
|
||||||
Set<JobRequest> jobRequests = JobManager.instance().getAllJobRequestsForTag(HOME_TIMELINE);
|
|
||||||
if (!jobRequests.isEmpty() && !updateCurrent) {
|
|
||||||
return jobRequests.iterator().next().getJobId();
|
|
||||||
}
|
|
||||||
return new JobRequest.Builder(HomeTimelineSyncJob.HOME_TIMELINE)
|
|
||||||
.setPeriodic(TimeUnit.MINUTES.toMillis(Helper.MINUTES_BETWEEN_HOME_TIMELINE), TimeUnit.MINUTES.toMillis(5))
|
|
||||||
.setPersisted(true)
|
|
||||||
.setUpdateCurrent(updateCurrent)
|
|
||||||
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
|
|
||||||
.setRequirementsEnforced(false)
|
|
||||||
.build()
|
|
||||||
.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Task in background starts here.
|
|
||||||
*/
|
|
||||||
private void callAsynchronousTask() {
|
|
||||||
|
|
||||||
if( !canNotify(getContext()))
|
|
||||||
return;
|
|
||||||
final SharedPreferences sharedpreferences = getContext().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
|
||||||
boolean notif_hometimeline = sharedpreferences.getBoolean(Helper.SET_NOTIF_HOMETIMELINE, true);
|
|
||||||
//User disagree with home timeline refresh
|
|
||||||
if( !notif_hometimeline)
|
|
||||||
return; //Nothing is done
|
|
||||||
//No account connected, the service is stopped
|
|
||||||
if(!Helper.isLoggedIn(getContext()))
|
|
||||||
return;
|
|
||||||
SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
|
||||||
//If an Internet connection and user agrees with notification refresh
|
|
||||||
//If WIFI only and on WIFI OR user defined any connections to use the service.
|
|
||||||
if(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getContext())) {
|
|
||||||
List<Account> accounts = new AccountDAO(getContext(),db).getAllAccount();
|
|
||||||
//It means there is no user in DB.
|
|
||||||
if( accounts == null )
|
|
||||||
return;
|
|
||||||
//Retrieve users in db that owner has.
|
|
||||||
for (Account account: accounts) {
|
|
||||||
String since_id = sharedpreferences.getString(Helper.LAST_HOMETIMELINE_MAX_ID + account.getId(), null);
|
|
||||||
new RetrieveHomeTimelineServiceAsyncTask(getContext(), account.getInstance(), account.getToken(), since_id, account.getAcct(), account.getId(), HomeTimelineSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRetrieveHomeTimelineService(APIResponse apiResponse, String acct, String userId) {
|
|
||||||
List<Status> 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...
|
|
||||||
if( (status.getId().equals(max_id)) || (acct != null && status.getAccount().getAcct().trim().equals(acct.trim()) ))
|
|
||||||
continue;
|
|
||||||
String notificationUrl = status.getAccount().getAvatar();
|
|
||||||
|
|
||||||
if(statuses.size() > 0 )
|
|
||||||
message = getContext().getResources().getQuantityString(R.plurals.other_notif_hometimeline, statuses.size(), statuses.size());
|
|
||||||
else
|
|
||||||
message = "";
|
|
||||||
final Intent intent = new Intent(getContext(), MainActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
|
||||||
intent.putExtra(INTENT_ACTION, HOME_TIMELINE_INTENT);
|
|
||||||
intent.putExtra(PREF_KEY_ID, userId);
|
|
||||||
long notif_id = Long.parseLong(userId);
|
|
||||||
final int notificationId = ((notif_id + 2) > 2147483647) ? (int) (2147483647 - notif_id - 2) : (int) (notif_id + 2);
|
|
||||||
|
|
||||||
if( notificationUrl != null){
|
|
||||||
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
|
|
||||||
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
|
|
||||||
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
|
|
||||||
.imageDownloader(new PatchBaseImageDownloader(getContext()))
|
|
||||||
.threadPoolSize(5)
|
|
||||||
.threadPriority(Thread.MIN_PRIORITY + 3)
|
|
||||||
.denyCacheImageMultipleSizesInMemory()
|
|
||||||
.diskCache(new UnlimitedDiskCache(cacheDir))
|
|
||||||
.build();
|
|
||||||
imageLoaderNoty.init(config);
|
|
||||||
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
|
||||||
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
|
||||||
final String finalMessage = message;
|
|
||||||
String title;
|
|
||||||
if( status.getAccount().getDisplay_name() != null && status.getAccount().getDisplay_name().length() > 0 )
|
|
||||||
title = getContext().getResources().getString(R.string.notif_pouet, Helper.shortnameToUnicode(status.getAccount().getDisplay_name(), true));
|
|
||||||
else
|
|
||||||
title = getContext().getResources().getString(R.string.notif_pouet, status.getAccount().getUsername());
|
|
||||||
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(getContext(), intent, notificationId, loadedImage, finalTitle, finalMessage);
|
|
||||||
}
|
|
||||||
@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);
|
|
||||||
}});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,271 +0,0 @@
|
||||||
package fr.gouv.etalab.mastodon.jobs;
|
|
||||||
/* 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 <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
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.AsyncTask;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.evernote.android.job.Job;
|
|
||||||
import com.evernote.android.job.JobManager;
|
|
||||||
import com.evernote.android.job.JobRequest;
|
|
||||||
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
|
||||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
|
||||||
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
|
||||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
|
||||||
import fr.gouv.etalab.mastodon.client.APIResponse;
|
|
||||||
import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader;
|
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
|
||||||
import mastodon.etalab.gouv.fr.mastodon.R;
|
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.RetrieveNotificationsAsyncTask;
|
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
|
||||||
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface;
|
|
||||||
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
|
|
||||||
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
|
|
||||||
|
|
||||||
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 29/04/2017.
|
|
||||||
* Notifications refresh job
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class NotificationsSyncJob extends Job implements OnRetrieveNotificationsInterface{
|
|
||||||
|
|
||||||
static final String NOTIFICATION_REFRESH = "job_notification";
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
protected Result onRunJob(Params params) {
|
|
||||||
//Code refresh here
|
|
||||||
callAsynchronousTask();
|
|
||||||
return Result.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static int schedule(boolean updateCurrent){
|
|
||||||
|
|
||||||
Set<JobRequest> jobRequests = JobManager.instance().getAllJobRequestsForTag(NOTIFICATION_REFRESH);
|
|
||||||
if (!jobRequests.isEmpty() && !updateCurrent) {
|
|
||||||
return jobRequests.iterator().next().getJobId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new JobRequest.Builder(NotificationsSyncJob.NOTIFICATION_REFRESH)
|
|
||||||
.setPeriodic(TimeUnit.MINUTES.toMillis(Helper.MINUTES_BETWEEN_NOTIFICATIONS_REFRESH), TimeUnit.MINUTES.toMillis(5))
|
|
||||||
.setPersisted(true)
|
|
||||||
.setUpdateCurrent(updateCurrent)
|
|
||||||
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
|
|
||||||
.setRequirementsEnforced(false)
|
|
||||||
.build()
|
|
||||||
.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Task in background starts here.
|
|
||||||
*/
|
|
||||||
private void callAsynchronousTask() {
|
|
||||||
if( !canNotify(getContext()))
|
|
||||||
return;
|
|
||||||
SQLiteDatabase db = Sqlite.getInstance(getContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
|
||||||
//If an Internet connection and user agrees with notification refresh
|
|
||||||
final SharedPreferences sharedpreferences = getContext().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(getContext()))
|
|
||||||
return;
|
|
||||||
//If WIFI only and on WIFI OR user defined any connections to use the service.
|
|
||||||
if(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getContext())) {
|
|
||||||
List<Account> accounts = new AccountDAO(getContext(),db).getAllAccount();
|
|
||||||
//It means there is no user in DB.
|
|
||||||
if( accounts == null )
|
|
||||||
return;
|
|
||||||
//Retrieve users in db that owner has.
|
|
||||||
for (Account account: accounts) {
|
|
||||||
String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId(), null);
|
|
||||||
new RetrieveNotificationsAsyncTask(getContext(), account.getInstance(), account.getToken(), max_id, account.getAcct(), account.getId(), NotificationsSyncJob.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRetrieveNotifications(APIResponse apiResponse, String acct, String userId, boolean refreshData) {
|
|
||||||
List<Notification> notifications = apiResponse.getNotifications();
|
|
||||||
if( apiResponse.getError() != null || notifications == null || notifications.size() == 0)
|
|
||||||
return;
|
|
||||||
Bitmap icon_notification = null;
|
|
||||||
final SharedPreferences sharedpreferences = getContext().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);
|
|
||||||
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;
|
|
||||||
int newAdds = 0;
|
|
||||||
int newAsks = 0;
|
|
||||||
int newMentions = 0;
|
|
||||||
int newShare = 0;
|
|
||||||
String notificationUrl = null;
|
|
||||||
String title = null;
|
|
||||||
final String message;
|
|
||||||
for(Notification notification: notifications){
|
|
||||||
//The notification associated to max_id is discarded as it is supposed to have already been sent
|
|
||||||
if( max_id != null && notification.getId().equals(max_id))
|
|
||||||
continue;
|
|
||||||
switch (notification.getType()){
|
|
||||||
case "mention":
|
|
||||||
if(notif_mention){
|
|
||||||
newMentions++;
|
|
||||||
if( notificationUrl == null){
|
|
||||||
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),getContext().getString(R.string.notif_mention));
|
|
||||||
else
|
|
||||||
title = String.format("@%s %s", notification.getAccount().getUsername(),getContext().getString(R.string.notif_mention));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "reblog":
|
|
||||||
if(notif_share){
|
|
||||||
newShare++;
|
|
||||||
if( notificationUrl == null){
|
|
||||||
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),getContext().getString(R.string.notif_reblog));
|
|
||||||
else
|
|
||||||
title = String.format("@%s %s", notification.getAccount().getUsername(),getContext().getString(R.string.notif_reblog));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "favourite":
|
|
||||||
if(notif_add){
|
|
||||||
newAdds++;
|
|
||||||
if( notificationUrl == null){
|
|
||||||
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),getContext().getString(R.string.notif_favourite));
|
|
||||||
else
|
|
||||||
title = String.format("@%s %s", notification.getAccount().getUsername(),getContext().getString(R.string.notif_favourite));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "follow":
|
|
||||||
if(notif_follow){
|
|
||||||
newFollows++;
|
|
||||||
if( notificationUrl == null){
|
|
||||||
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),getContext().getString(R.string.notif_follow));
|
|
||||||
else
|
|
||||||
title = String.format("@%s %s", notification.getAccount().getUsername(),getContext().getString(R.string.notif_follow));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
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
|
|
||||||
int other = allNotifCount -1;
|
|
||||||
if(other > 0 )
|
|
||||||
message = getContext().getResources().getQuantityString(R.plurals.other_notifications, other, other);
|
|
||||||
else
|
|
||||||
message = "";
|
|
||||||
final Intent intent = new Intent(getContext(), MainActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
|
|
||||||
intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT);
|
|
||||||
intent.putExtra(PREF_KEY_ID, userId);
|
|
||||||
long notif_id = Long.parseLong(userId);
|
|
||||||
final int notificationId = ((notif_id + 1) > 2147483647) ? (int) (2147483647 - notif_id - 1) : (int) (notif_id + 1);
|
|
||||||
|
|
||||||
if( notificationUrl != null && icon_notification == null){
|
|
||||||
ImageLoader imageLoaderNoty = ImageLoader.getInstance();
|
|
||||||
File cacheDir = new File(getContext().getCacheDir(), getContext().getString(R.string.app_name));
|
|
||||||
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getContext())
|
|
||||||
.imageDownloader(new PatchBaseImageDownloader(getContext()))
|
|
||||||
.threadPoolSize(5)
|
|
||||||
.threadPriority(Thread.MIN_PRIORITY + 3)
|
|
||||||
.denyCacheImageMultipleSizesInMemory()
|
|
||||||
.diskCache(new UnlimitedDiskCache(cacheDir))
|
|
||||||
.build();
|
|
||||||
imageLoaderNoty.init(config);
|
|
||||||
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new SimpleBitmapDisplayer()).cacheInMemory(false)
|
|
||||||
.cacheOnDisk(true).resetViewBeforeLoading(true).build();
|
|
||||||
|
|
||||||
final String finalTitle = title;
|
|
||||||
imageLoaderNoty.loadImage(notificationUrl, options, new SimpleImageLoadingListener(){
|
|
||||||
@Override
|
|
||||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
|
||||||
super.onLoadingComplete(imageUri, view, loadedImage);
|
|
||||||
if( max_id != null)
|
|
||||||
notify_user(getContext(), intent, notificationId, loadedImage, finalTitle, message);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onLoadingFailed(java.lang.String imageUri, android.view.View view, FailReason failReason){
|
|
||||||
if( max_id != null)
|
|
||||||
notify_user(getContext(), intent, notificationId, BitmapFactory.decodeResource(getContext().getResources(),
|
|
||||||
R.drawable.mastodonlogo), finalTitle, message);
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ package fr.gouv.etalab.mastodon.jobs;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.evernote.android.job.Job;
|
import com.evernote.android.job.Job;
|
||||||
import com.evernote.android.job.JobRequest;
|
import com.evernote.android.job.JobRequest;
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package fr.gouv.etalab.mastodon.jobs;
|
||||||
|
/* 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 <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import com.evernote.android.job.Job;
|
||||||
|
import com.evernote.android.job.JobManager;
|
||||||
|
import com.evernote.android.job.JobRequest;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.services.StreamingService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 29/04/2017.
|
||||||
|
* Notifications refresh job
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class StreamingSyncJob extends Job {
|
||||||
|
|
||||||
|
static final String STREAMING = "job_streaming";
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected Result onRunJob(Params params) {
|
||||||
|
//Code refresh here
|
||||||
|
getContext().startService(new Intent(getContext(), StreamingService.class));
|
||||||
|
return Result.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int schedule(boolean updateCurrent){
|
||||||
|
|
||||||
|
Set<JobRequest> jobRequests = JobManager.instance().getAllJobRequestsForTag(STREAMING);
|
||||||
|
if (!jobRequests.isEmpty() && !updateCurrent) {
|
||||||
|
return jobRequests.iterator().next().getJobId();
|
||||||
|
}
|
||||||
|
return new JobRequest.Builder(StreamingSyncJob.STREAMING)
|
||||||
|
.setPeriodic(TimeUnit.MINUTES.toMillis(Helper.MINUTES_BETWEEN_STREAMING_CHECK_ALIVE), TimeUnit.MINUTES.toMillis(5))
|
||||||
|
.setPersisted(true)
|
||||||
|
.setUpdateCurrent(updateCurrent)
|
||||||
|
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
|
||||||
|
.setRequirementsEnforced(false)
|
||||||
|
.build()
|
||||||
|
.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
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 <http://www.gnu.org/licenses>. */
|
||||||
|
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.AsyncTask;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.text.Html;
|
||||||
|
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.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.activities.MainActivity;
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.StreamingUserAsyncTask;
|
||||||
|
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.helper.Helper;
|
||||||
|
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveStreamingInterface;
|
||||||
|
import fr.gouv.etalab.mastodon.jobs.StreamingSyncJob;
|
||||||
|
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.notify_user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Thomas on 28/08/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class StreamingService extends Service implements OnRetrieveStreamingInterface {
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
private int notificationId;
|
||||||
|
private Intent intent;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
callAsynchronousTask();
|
||||||
|
return START_NOT_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task in background starts here.
|
||||||
|
*/
|
||||||
|
private void callAsynchronousTask() {
|
||||||
|
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
|
||||||
|
//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(!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(getApplicationContext())) {
|
||||||
|
List<Account> accounts = new AccountDAO(getApplicationContext(),db).getAllAccount();
|
||||||
|
//It means there is no user in DB.
|
||||||
|
if( accounts == null )
|
||||||
|
return;
|
||||||
|
//Retrieve users in db that owner has.
|
||||||
|
for (Account account: accounts) {
|
||||||
|
new StreamingUserAsyncTask(account.getInstance(), account.getToken(), account.getAcct(), account.getId(), StreamingService.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRetrieveStreaming(StreamingUserAsyncTask.EventStreaming event, JSONObject response, String acct, String userId) {
|
||||||
|
if( response == null )
|
||||||
|
return;
|
||||||
|
String max_id = null;
|
||||||
|
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 == StreamingUserAsyncTask.EventStreaming.NOTIFICATION){
|
||||||
|
notification = API.parseNotificationResponse(getApplicationContext(), response);
|
||||||
|
max_id = notification.getId();
|
||||||
|
switch (notification.getType()){
|
||||||
|
case "mention":
|
||||||
|
if(notif_mention){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, notification.getId());
|
||||||
|
editor.apply();
|
||||||
|
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 == StreamingUserAsyncTask.EventStreaming.UPDATE){
|
||||||
|
status = API.parseStatuses(getApplicationContext(), response);
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, status.getId());
|
||||||
|
editor.apply();
|
||||||
|
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 == StreamingUserAsyncTask.EventStreaming.DELETE){
|
||||||
|
try {
|
||||||
|
dataId = response.getString("id");
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if( max_id != null){
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + userId, max_id);
|
||||||
|
editor.apply();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check which user is connected and if activity is to front
|
||||||
|
boolean activityVisible = false;
|
||||||
|
try{
|
||||||
|
activityVisible = MainActivity.isActivityVisible();
|
||||||
|
}catch (Exception ignored){}
|
||||||
|
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);
|
||||||
|
//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 && account != null && !account.getAcct().trim().equals(acct.trim()) && !account.getId().trim().equals(userId.trim())){
|
||||||
|
notify = false;
|
||||||
|
Intent intentBC = new Intent(Helper.RECEIVE_DATA);
|
||||||
|
intentBC.putExtra("eventStreaming", event);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
if( event == StreamingUserAsyncTask.EventStreaming.UPDATE)
|
||||||
|
b.putParcelable("data", status);
|
||||||
|
else if(event == StreamingUserAsyncTask.EventStreaming.NOTIFICATION)
|
||||||
|
b.putParcelable("data", notification);
|
||||||
|
else if(event == StreamingUserAsyncTask.EventStreaming.DELETE)
|
||||||
|
b.putString("id", dataId);
|
||||||
|
intentBC.putExtras(b);
|
||||||
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intentBC);
|
||||||
|
}else if(event == StreamingUserAsyncTask.EventStreaming.NOTIFICATION ){
|
||||||
|
notify = true;
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
}else if(event == StreamingUserAsyncTask.EventStreaming.UPDATE ){
|
||||||
|
if(account.getAcct().trim().equals(acct.trim()) && account.getId().trim().equals(userId.trim())){
|
||||||
|
notify = false;
|
||||||
|
}else {
|
||||||
|
notify = true;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,11 +58,6 @@
|
||||||
android:text="@string/set_auto_store_toot"
|
android:text="@string/set_auto_store_toot"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/set_bubble_counter"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:text="@string/set_bubble_counter"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/set_preview_reply"
|
android:id="@+id/set_preview_reply"
|
||||||
|
|
|
@ -58,11 +58,6 @@
|
||||||
android:text="@string/set_auto_store_toot"
|
android:text="@string/set_auto_store_toot"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/set_bubble_counter"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:text="@string/set_bubble_counter"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/set_preview_reply"
|
android:id="@+id/set_preview_reply"
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
package fr.gouv.etalab.mastodon.activities;
|
package fr.gouv.etalab.mastodon.activities;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -31,6 +33,7 @@ import android.support.design.widget.TabLayout;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
|
@ -71,8 +74,11 @@ import java.util.Locale;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import fr.gouv.etalab.mastodon.asynctasks.StreamingUserAsyncTask;
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask;
|
import fr.gouv.etalab.mastodon.asynctasks.UpdateAccountInfoByIDAsyncTask;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Account;
|
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.PatchBaseImageDownloader;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayFollowRequestSentFragment;
|
||||||
|
@ -80,6 +86,7 @@ import fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
|
||||||
import fr.gouv.etalab.mastodon.helper.Helper;
|
import fr.gouv.etalab.mastodon.helper.Helper;
|
||||||
import fr.gouv.etalab.mastodon.interfaces.OnUpdateAccountInfoInterface;
|
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.sqlite.Sqlite;
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask;
|
||||||
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
|
||||||
|
@ -124,6 +131,8 @@ public class MainActivity extends AppCompatActivity
|
||||||
private DisplayStatusFragment homeFragment;
|
private DisplayStatusFragment homeFragment;
|
||||||
private DisplayNotificationsFragment notificationsFragment;
|
private DisplayNotificationsFragment notificationsFragment;
|
||||||
private static final int ERROR_DIALOG_REQUEST_CODE = 97;
|
private static final int ERROR_DIALOG_REQUEST_CODE = 97;
|
||||||
|
private BroadcastReceiver receive_data;
|
||||||
|
private int newNotif, newHome;
|
||||||
|
|
||||||
public MainActivity() {
|
public MainActivity() {
|
||||||
}
|
}
|
||||||
|
@ -131,6 +140,46 @@ public class MainActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
newNotif = 0;
|
||||||
|
newHome = 0;
|
||||||
|
|
||||||
|
receive_data = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
Bundle b = intent.getExtras();
|
||||||
|
StreamingUserAsyncTask.EventStreaming eventStreaming = (StreamingUserAsyncTask.EventStreaming) intent.getSerializableExtra("eventStreaming");
|
||||||
|
|
||||||
|
if( eventStreaming == StreamingUserAsyncTask.EventStreaming.NOTIFICATION){
|
||||||
|
Notification notification = b.getParcelable("data");
|
||||||
|
if(notificationsFragment != null && notificationsFragment.getUserVisibleHint()){
|
||||||
|
notificationsFragment.updateData(notification);
|
||||||
|
}else{
|
||||||
|
newNotif++;
|
||||||
|
updateNotifCounter();
|
||||||
|
notificationsFragment.updateData(notification);
|
||||||
|
}
|
||||||
|
}else if(eventStreaming == StreamingUserAsyncTask.EventStreaming.UPDATE){
|
||||||
|
Status status = b.getParcelable("data");
|
||||||
|
if(homeFragment != null && homeFragment.getUserVisibleHint()){
|
||||||
|
homeFragment.updateData(status);
|
||||||
|
}else{
|
||||||
|
newHome++;
|
||||||
|
updateHomeCounter();
|
||||||
|
homeFragment.updateData(status);
|
||||||
|
}
|
||||||
|
}else if(eventStreaming == StreamingUserAsyncTask.EventStreaming.DELETE){
|
||||||
|
String id = b.getString("id");
|
||||||
|
if(notificationsFragment != null && notificationsFragment.getUserVisibleHint()){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA));
|
||||||
|
|
||||||
|
|
||||||
ProviderInstaller.installIfNeededAsync(this, this);
|
ProviderInstaller.installIfNeededAsync(this, this);
|
||||||
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||||
|
|
||||||
|
@ -150,7 +199,7 @@ public class MainActivity extends AppCompatActivity
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
startService(new Intent(getApplicationContext(), StreamingService.class));
|
||||||
Helper.fillMapEmoji(getApplicationContext());
|
Helper.fillMapEmoji(getApplicationContext());
|
||||||
//Here, the user is authenticated
|
//Here, the user is authenticated
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
|
@ -208,7 +257,6 @@ public class MainActivity extends AppCompatActivity
|
||||||
(getSupportFragmentManager(), tabLayout.getTabCount());
|
(getSupportFragmentManager(), tabLayout.getTabCount());
|
||||||
viewPager.setAdapter(adapter);
|
viewPager.setAdapter(adapter);
|
||||||
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
||||||
final boolean bubbles = sharedpreferences.getBoolean(Helper.SET_BUBBLE_COUNTER, true);
|
|
||||||
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTabSelected(TabLayout.Tab tab) {
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
|
@ -231,16 +279,18 @@ public class MainActivity extends AppCompatActivity
|
||||||
case 0:
|
case 0:
|
||||||
item = navigationView.getMenu().findItem(R.id.nav_home);
|
item = navigationView.getMenu().findItem(R.id.nav_home);
|
||||||
fragmentTag = "HOME_TIMELINE";
|
fragmentTag = "HOME_TIMELINE";
|
||||||
if( bubbles && homeFragment != null)
|
newHome = 0;
|
||||||
homeFragment.refreshData();
|
if( homeFragment != null)
|
||||||
updateHomeCounter(0);
|
homeFragment.refresh();
|
||||||
|
updateHomeCounter();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fragmentTag = "NOTIFICATIONS";
|
fragmentTag = "NOTIFICATIONS";
|
||||||
item = navigationView.getMenu().findItem(R.id.nav_notification);
|
item = navigationView.getMenu().findItem(R.id.nav_notification);
|
||||||
updateNotifCounter(0);
|
newNotif = 0;
|
||||||
if( bubbles && notificationsFragment != null)
|
if( notificationsFragment != null)
|
||||||
notificationsFragment.refreshData();
|
notificationsFragment.refresh();
|
||||||
|
updateNotifCounter();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
fragmentTag = "LOCAL_TIMELINE";
|
fragmentTag = "LOCAL_TIMELINE";
|
||||||
|
@ -448,6 +498,8 @@ public class MainActivity extends AppCompatActivity
|
||||||
navigationView.getMenu().findItem(R.id.nav_follow_request).setVisible(false);
|
navigationView.getMenu().findItem(R.id.nav_follow_request).setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LinearLayout owner_container = (LinearLayout) headerLayout.findViewById(R.id.owner_container);
|
LinearLayout owner_container = (LinearLayout) headerLayout.findViewById(R.id.owner_container);
|
||||||
owner_container.setOnClickListener(new View.OnClickListener() {
|
owner_container.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -810,23 +862,23 @@ public class MainActivity extends AppCompatActivity
|
||||||
@Override
|
@Override
|
||||||
public void onResume(){
|
public void onResume(){
|
||||||
super.onResume();
|
super.onResume();
|
||||||
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
MainActivity.activityResumed();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Proceeds to update of the authenticated account
|
//Proceeds to update of the authenticated account
|
||||||
if(Helper.isLoggedIn(getApplicationContext()))
|
if(Helper.isLoggedIn(getApplicationContext()))
|
||||||
new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
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")
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
@Override
|
@Override
|
||||||
|
@ -1060,40 +1112,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);
|
public void updateHomeCounter(){
|
||||||
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){
|
|
||||||
if( tabLayout.getTabAt(0) == null )
|
if( tabLayout.getTabAt(0) == null )
|
||||||
return;
|
return;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
@ -1101,8 +1121,8 @@ public class MainActivity extends AppCompatActivity
|
||||||
if( tabHome == null)
|
if( tabHome == null)
|
||||||
return;
|
return;
|
||||||
TextView tabCounterHome = (TextView) tabHome.findViewById(R.id.tab_counter);
|
TextView tabCounterHome = (TextView) tabHome.findViewById(R.id.tab_counter);
|
||||||
tabCounterHome.setText(String.valueOf(newHomeCount));
|
tabCounterHome.setText(String.valueOf(newHome));
|
||||||
if( newHomeCount > 0){
|
if( newHome > 0){
|
||||||
//New data are available
|
//New data are available
|
||||||
//The fragment is not displayed, so the counter is displayed
|
//The fragment is not displayed, so the counter is displayed
|
||||||
if( tabLayout.getSelectedTabPosition() != 0)
|
if( tabLayout.getSelectedTabPosition() != 0)
|
||||||
|
@ -1114,7 +1134,7 @@ public class MainActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateNotifCounter(int newNotifCount){
|
public void updateNotifCounter(){
|
||||||
if(tabLayout.getTabAt(1) == null)
|
if(tabLayout.getTabAt(1) == null)
|
||||||
return;
|
return;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
|
@ -1122,8 +1142,8 @@ public class MainActivity extends AppCompatActivity
|
||||||
if( tabNotif == null)
|
if( tabNotif == null)
|
||||||
return;
|
return;
|
||||||
TextView tabCounterNotif = (TextView) tabNotif.findViewById(R.id.tab_counter);
|
TextView tabCounterNotif = (TextView) tabNotif.findViewById(R.id.tab_counter);
|
||||||
tabCounterNotif.setText(String.valueOf(newNotifCount));
|
tabCounterNotif.setText(String.valueOf(newNotif));
|
||||||
if( newNotifCount > 0){
|
if( newNotif > 0){
|
||||||
if( tabLayout.getSelectedTabPosition() != 1)
|
if( tabLayout.getSelectedTabPosition() != 1)
|
||||||
tabCounterNotif.setVisibility(View.VISIBLE);
|
tabCounterNotif.setVisibility(View.VISIBLE);
|
||||||
else
|
else
|
||||||
|
@ -1133,4 +1153,21 @@ public class MainActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isActivityVisible() {
|
||||||
|
return activityVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void activityResumed() {
|
||||||
|
activityVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void activityPaused() {
|
||||||
|
activityVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean activityVisible;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue