diff --git a/app/src/main/java/app/fedilab/android/activities/OwnerStatusActivity.java b/app/src/main/java/app/fedilab/android/activities/OwnerStatusActivity.java index 487a95b1d..9c15d5628 100644 --- a/app/src/main/java/app/fedilab/android/activities/OwnerStatusActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/OwnerStatusActivity.java @@ -45,10 +45,12 @@ import android.widget.DatePicker; import android.widget.EditText; import android.widget.ImageView; import android.widget.RelativeLayout; +import android.widget.ScrollView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -96,6 +98,8 @@ public class OwnerStatusActivity extends BaseActivity implements OnRetrieveFeeds private FilterToots filterToots; private Date dateIni, dateEnd; private View statsDialogView; + private Statistics statistics; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -287,6 +291,7 @@ public class OwnerStatusActivity extends BaseActivity implements OnRetrieveFeeds case R.id.action_sync: Intent backupIntent = new Intent(OwnerStatusActivity.this, BackupStatusInDataBaseService.class); startService(backupIntent); + statistics = null; return true; case R.id.action_stats: SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); @@ -300,18 +305,22 @@ public class OwnerStatusActivity extends BaseActivity implements OnRetrieveFeeds } AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(OwnerStatusActivity.this, style); LayoutInflater inflater = this.getLayoutInflater(); - statsDialogView = inflater.inflate(R.layout.filter_owner_toots, null); + statsDialogView = inflater.inflate(R.layout.stats_owner_toots, null); dialogBuilder.setView(statsDialogView); dialogBuilder - .setTitle(R.string.action_filter) - .setPositiveButton(R.string.cancel, new DialogInterface.OnClickListener() { + .setTitle(R.string.action_stats) + .setPositiveButton(R.string.validate, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); dialogBuilder.create().show(); - new RetrieveStatsAsyncTask(getApplicationContext(),OwnerStatusActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if( statistics == null) { + new RetrieveStatsAsyncTask(getApplicationContext(), OwnerStatusActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }else{ + displayStats(); + } return true; case R.id.action_filter: sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); @@ -510,6 +519,55 @@ public class OwnerStatusActivity extends BaseActivity implements OnRetrieveFeeds @Override public void onStats(Statistics statistics) { + this.statistics = statistics; + displayStats(); + } + private void displayStats(){ + if( statsDialogView != null){ + ScrollView stats_container = statsDialogView.findViewById(R.id.stats_container); + RelativeLayout loader = statsDialogView.findViewById(R.id.loader); + + TextView total_statuses = statsDialogView.findViewById(R.id.total_statuses); + TextView number_boosts = statsDialogView.findViewById(R.id.number_boosts); + TextView number_replies = statsDialogView.findViewById(R.id.number_replies); + TextView number_statuses = statsDialogView.findViewById(R.id.number_statuses); + TextView number_with_media = statsDialogView.findViewById(R.id.number_with_media); + TextView number_with_cw = statsDialogView.findViewById(R.id.number_with_cw); + TextView number_with_sensitive_media = statsDialogView.findViewById(R.id.number_with_sensitive_media); + TextView v_public = statsDialogView.findViewById(R.id.v_public); + TextView v_unlisted = statsDialogView.findViewById(R.id.v_unlisted); + TextView v_private = statsDialogView.findViewById(R.id.v_private); + TextView v_direct = statsDialogView.findViewById(R.id.v_direct); + + TextView frequency = statsDialogView.findViewById(R.id.frequency); + TextView last_toot_date = statsDialogView.findViewById(R.id.last_toot_date); + TextView first_toot_date = statsDialogView.findViewById(R.id.first_toot_date); + + + total_statuses.setText(String.valueOf(statistics.getTotal_statuses())); + number_boosts.setText(String.valueOf(statistics.getNumber_boosts())); + number_replies.setText(String.valueOf(statistics.getNumber_replies())); + number_statuses.setText(String.valueOf(statistics.getNumber_status())); + number_with_media.setText(String.valueOf(statistics.getNumber_with_media())); + number_with_cw.setText(String.valueOf(statistics.getNumber_with_cw())); + number_with_sensitive_media.setText(String.valueOf(statistics.getNumber_with_sensitive_media())); + v_public.setText(String.valueOf(statistics.getV_public())); + v_unlisted.setText(String.valueOf(statistics.getV_unlisted())); + v_private.setText(String.valueOf(statistics.getV_private())); + v_direct.setText(String.valueOf(statistics.getV_direct())); + + + first_toot_date.setText(Helper.dateToString(statistics.getFirstTootDate())); + last_toot_date.setText(Helper.dateToString(statistics.getLastTootDate())); + DecimalFormat df = new DecimalFormat("#.##"); + frequency.setText(getString(R.string.toot_per_day, df.format(statistics.getFrequency()))); + + stats_container.setVisibility(View.VISIBLE); + loader.setVisibility(View.GONE); + + }else{ + Toasty.error(OwnerStatusActivity.this,getString(R.string.toast_error),Toast.LENGTH_SHORT).show(); + } } } diff --git a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveStatsAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveStatsAsyncTask.java index 3c91b2186..8d9cf4ec3 100644 --- a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveStatsAsyncTask.java +++ b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveStatsAsyncTask.java @@ -21,6 +21,7 @@ import java.lang.ref.WeakReference; import app.fedilab.android.client.Entities.Statistics; import app.fedilab.android.interfaces.OnRetrieveStatsInterface; import app.fedilab.android.sqlite.Sqlite; +import app.fedilab.android.sqlite.StatusCacheDAO; /** @@ -44,9 +45,8 @@ public class RetrieveStatsAsyncTask extends AsyncTask { @Override protected Void doInBackground(Void... params) { - statistics = new Statistics(); SQLiteDatabase db = Sqlite.getInstance(contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); - + statistics = new StatusCacheDAO(contextReference.get(), db).getStat(); return null; } diff --git a/app/src/main/java/app/fedilab/android/client/Entities/Statistics.java b/app/src/main/java/app/fedilab/android/client/Entities/Statistics.java index feef702a4..ff1dd686c 100644 --- a/app/src/main/java/app/fedilab/android/client/Entities/Statistics.java +++ b/app/src/main/java/app/fedilab/android/client/Entities/Statistics.java @@ -14,19 +14,49 @@ package app.fedilab.android.client.Entities; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import java.util.Date; + public class Statistics { - private int total_statuses; - private int number_boosts; - private int number_replies; - private int number_status; - private int number_with_media; - private int number_with_cw; - private int number_with_sensitive_media; - private int v_public; - private int v_unlisted; - private int v_private; + private int total_statuses = 0; + private int number_boosts = 0; + private int number_replies = 0; + private int number_status = 0; + private int number_with_media = 0; + private int number_with_cw = 0; + private int number_with_sensitive_media = 0; + private int v_public = 0; + private int v_unlisted = 0; + private int v_private = 0; + private Date firstTootDate; + private Date lastTootDate; + private float frequency; + + + public Date getFirstTootDate() { + return firstTootDate; + } + + public void setFirstTootDate(Date firstTootDate) { + this.firstTootDate = firstTootDate; + } + + public Date getLastTootDate() { + return lastTootDate; + } + + public void setLastTootDate(Date lastTootDate) { + this.lastTootDate = lastTootDate; + } + + public float getFrequency() { + return frequency; + } + + public void setFrequency(float frequency) { + this.frequency = frequency; + } public int getTotal_statuses() { return total_statuses; diff --git a/app/src/main/java/app/fedilab/android/sqlite/StatusCacheDAO.java b/app/src/main/java/app/fedilab/android/sqlite/StatusCacheDAO.java index 58cb15c10..adfca2301 100644 --- a/app/src/main/java/app/fedilab/android/sqlite/StatusCacheDAO.java +++ b/app/src/main/java/app/fedilab/android/sqlite/StatusCacheDAO.java @@ -23,7 +23,9 @@ import android.database.sqlite.SQLiteDatabase; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.concurrent.TimeUnit; +import app.fedilab.android.client.Entities.Statistics; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.helper.FilterToots; import app.fedilab.android.helper.Helper; @@ -443,7 +445,117 @@ public class StatusCacheDAO { } } + public Statistics getStat(){ + SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + String instance = Helper.getLiveInstance(context); + + Statistics statistics = new Statistics(); + + //Count All + Cursor mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"'" + , null); + mCount.moveToFirst(); + statistics.setTotal_statuses(mCount.getInt(0)); + mCount.close(); + + //Count boosts + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_REBLOG + " IS NOT NULL" + " AND " + Sqlite.COL_REBLOG + " != ''" + , null); + mCount.moveToFirst(); + statistics.setNumber_boosts(mCount.getInt(0)); + mCount.close(); + + //Count replies + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_IN_REPLY_TO_ID + " IS NOT NULL" + " AND " + Sqlite.COL_IN_REPLY_TO_ID + " != 'null'" + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setNumber_replies(mCount.getInt(0)); + mCount.close(); + + statistics.setNumber_status(statistics.getTotal_statuses() - statistics.getNumber_boosts() - statistics.getNumber_replies()); + + //Count media + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_MEDIA_ATTACHMENTS + " IS NOT NULL" + " AND " + Sqlite.COL_MEDIA_ATTACHMENTS + " !='"+Helper.attachmentToStringStorage(new ArrayList<>())+"' " + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setNumber_with_media(mCount.getInt(0)); + mCount.close(); + + + //Count sensitive + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_SENSITIVE + "= 1 AND " + Sqlite.COL_MEDIA_ATTACHMENTS + " IS NOT NULL" + " AND " + Sqlite.COL_MEDIA_ATTACHMENTS + " !='"+Helper.attachmentToStringStorage(new ArrayList<>())+"' " + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setNumber_with_sensitive_media(mCount.getInt(0)); + mCount.close(); + + + //Count sensitive + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_SPOILER_TEXT + " IS NOT NULL" + " AND " + Sqlite.COL_SPOILER_TEXT + " != '' " + " AND " +Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setNumber_with_cw(mCount.getInt(0)); + mCount.close(); + + //Count public + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_VISIBILITY + "='public'" + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setV_public(mCount.getInt(0)); + mCount.close(); + + //Count unlisted + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_VISIBILITY + "='unlisted'" + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setV_unlisted(mCount.getInt(0)); + mCount.close(); + + //Count private + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_VISIBILITY + "='private'" + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setV_private(mCount.getInt(0)); + mCount.close(); + + + //Count private + mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_STATUSES_CACHE + + " where " + Sqlite.COL_CACHED_ACTION + " = '" + ARCHIVE_CACHE + "' AND " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND " + + Sqlite.COL_VISIBILITY + "='direct'" + " AND " + Sqlite.COL_REBLOG + " IS NULL" + , null); + mCount.moveToFirst(); + statistics.setV_direct(mCount.getInt(0)); + mCount.close(); + + statistics.setFirstTootDate(getSmallerDate(ARCHIVE_CACHE)); + statistics.setLastTootDate(getGreaterDate(ARCHIVE_CACHE)); + + long diff = statistics.getLastTootDate().getTime() - statistics.getFirstTootDate().getTime(); + long days = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS); + statistics.setFrequency((float)statistics.getTotal_statuses()/days); + + return statistics; + } /*** diff --git a/app/src/main/res/layout/stats_owner_toots.xml b/app/src/main/res/layout/stats_owner_toots.xml index 3ff059248..6e2108ee0 100644 --- a/app/src/main/res/layout/stats_owner_toots.xml +++ b/app/src/main/res/layout/stats_owner_toots.xml @@ -24,6 +24,7 @@ android:id="@+id/stats_container" android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + + + @@ -86,6 +163,7 @@ android:layout_height="wrap_content" /> @@ -101,6 +179,7 @@ android:layout_height="wrap_content" /> @@ -116,6 +195,7 @@ android:layout_height="wrap_content" /> @@ -131,6 +211,7 @@ android:layout_height="wrap_content" /> @@ -147,6 +228,7 @@ @@ -161,6 +243,7 @@ android:layout_height="wrap_content" /> @@ -170,6 +253,7 @@ @@ -219,6 +304,7 @@ android:layout_height="wrap_content" /> @@ -235,6 +321,7 @@ @@ -250,6 +337,7 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 787688cda..9fc01ce87 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1132,6 +1132,11 @@ Number with media Number with sensitive media Number with CW + First status date + Last status date + Frequency + %s statuses per day + Date range %d vote %d votes