diff options
author | Thomas <tschneider.ac@gmail.com> | 2023-03-04 18:28:59 +0100 |
---|---|---|
committer | Thomas <tschneider.ac@gmail.com> | 2023-03-04 18:28:59 +0100 |
commit | 74b107f1d38ca412e38efa44c8233e75a2faacf2 (patch) | |
tree | 457d70dd710cfdffc42f3af739f82bbea2ae97d0 | |
parent | c04a51f3b7f80447174a124ac519a302b1f62c53 (diff) |
Charts
4 files changed, 158 insertions, 114 deletions
diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/CheckHomeCacheActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/CheckHomeCacheActivity.java index 1fdc505b9..ada8ea430 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/CheckHomeCacheActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/CheckHomeCacheActivity.java @@ -15,34 +15,31 @@ package app.fedilab.android.mastodon.activities; * see <http://www.gnu.org/licenses>. */ -import android.graphics.Canvas; +import android.content.Context; import android.os.Bundle; -import android.util.Log; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.widget.TextView; import androidx.appcompat.widget.LinearLayoutCompat; import com.github.mikephil.charting.components.Description; +import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.IndexAxisValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.Transformer; -import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; -import java.util.Date; import java.util.List; import java.util.Locale; @@ -52,7 +49,6 @@ import app.fedilab.android.databinding.ActivityCheckHomeCachetBinding; import app.fedilab.android.mastodon.client.entities.api.Status; import app.fedilab.android.mastodon.client.entities.app.StatusCache; import app.fedilab.android.mastodon.exception.DBException; -import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.ThemeHelper; import es.dmoral.toasty.Toasty; @@ -62,6 +58,7 @@ public class CheckHomeCacheActivity extends BaseBarActivity { private ActivityCheckHomeCachetBinding binding; private List<Status> statuses; + private ArrayList<String> xVals; @Override protected void onCreate(Bundle savedInstanceState) { @@ -77,16 +74,6 @@ public class CheckHomeCacheActivity extends BaseBarActivity { finish(); return; } - binding.chart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - binding.chart.getViewTreeObserver().removeOnGlobalLayoutListener(this); - int height = (binding.chart.getWidth()); - LinearLayoutCompat.LayoutParams params = new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height); - binding.chart.setLayoutParams(params); - binding.chart.setVisibility(View.VISIBLE); - } - }); new Thread(() -> { try { @@ -95,83 +82,101 @@ public class CheckHomeCacheActivity extends BaseBarActivity { runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE)); return; } - - final ArrayList<String> xVals = new ArrayList<>(); - String xDate; - int inc = 0; - //We loop through cache - List<Entry> statusEntry = new ArrayList<>(); - int index = 0; - for (Status status : statuses) { - //We aggregate message in same hour range - boolean sameHourRange = true; - int count = 0; - while (inc < statuses.size() && sameHourRange) { - Calendar currentStatusDate = Calendar.getInstance(); - currentStatusDate.setTime(statuses.get(inc).created_at); - String xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(statuses.get(inc).created_at); - SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); - String xDateD = df.format(statuses.get(inc).created_at); - xDate = xDateD + " " + String.format(Locale.getDefault(), "%sh", xDateH); - if (inc + 1 < statuses.size()) { - Calendar nextStatusDate = Calendar.getInstance(); - nextStatusDate.setTime(statuses.get(inc + 1).created_at); - if (currentStatusDate.get(Calendar.HOUR) != nextStatusDate.get(Calendar.HOUR)) { - sameHourRange = false; + runOnUiThread(() -> { + + binding.progress.setVisibility(View.GONE); + binding.chart.setVisibility(View.VISIBLE); + binding.chart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + binding.chart.getViewTreeObserver().removeOnGlobalLayoutListener(this); + int height = (binding.chart.getWidth()); + LinearLayoutCompat.LayoutParams params = new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height); + binding.chart.setLayoutParams(params); + binding.chart.setVisibility(View.VISIBLE); + } + }); + xVals = new ArrayList<>(); + String xDate; + int inc = 0; + //We loop through cache + List<Entry> statusEntry = new ArrayList<>(); + int index = 0; + for (Status status : statuses) { + //We aggregate message in same hour range + boolean sameHourRange = true; + int count = 0; + while (inc < statuses.size() && sameHourRange) { + Calendar currentStatusDate = Calendar.getInstance(); + currentStatusDate.setTime(statuses.get(inc).created_at); + String xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(statuses.get(inc).created_at); + SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); + String xDateD = df.format(statuses.get(inc).created_at); + xDate = xDateD + " " + String.format(Locale.getDefault(), "%sh", xDateH); + if (inc + 1 < statuses.size()) { + Calendar nextStatusDate = Calendar.getInstance(); + nextStatusDate.setTime(statuses.get(inc + 1).created_at); + if (currentStatusDate.get(Calendar.HOUR) != nextStatusDate.get(Calendar.HOUR)) { + sameHourRange = false; + statusEntry.add(new Entry(index, count)); + index++; + xVals.add(xDate); + } else { + count++; + } + } else { //Last item + count++; statusEntry.add(new Entry(index, count)); - index++; xVals.add(xDate); - } else { - count++; } - } else { //Last item - count++; - statusEntry.add(new Entry(index, count)); - xVals.add(xDate); + inc++; } - inc++; } - } - List<ILineDataSet> dataSets = new ArrayList<>(); - - LineDataSet dataStatus = new LineDataSet(statusEntry, getString(R.string.cached_messages)); - dataStatus.setDrawValues(false); - dataStatus.setDrawFilled(true); - dataStatus.setDrawCircles(false); - dataStatus.setDrawCircleHole(false); - dataStatus.setMode(LineDataSet.Mode.CUBIC_BEZIER); - dataSets.add(dataStatus); - - LineData data = new LineData(dataSets); - binding.chart.setData(data); - IndexAxisValueFormatter formatter = new IndexAxisValueFormatter() { - @Override - public String getFormattedValue(float value) { - if (value < xVals.size()) { - return xVals.get((int) value); - } else - return ""; - } - }; - binding.chart.setExtraBottomOffset(80); - // binding.chart.getXAxis().setGranularity(1f); - binding.chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); - binding.chart.getXAxis().setLabelRotationAngle(-45f); - binding.chart.getXAxis().setValueFormatter(formatter); - binding.chart.getXAxis().setEnabled(true); - binding.chart.getXAxis().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); - binding.chart.getAxisLeft().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); - binding.chart.getAxisRight().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); - binding.chart.getLegend().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); - binding.chart.getAxisLeft().setAxisMinimum(0f); - binding.chart.getAxisRight().setAxisMinimum(0f); - binding.chart.getXAxis().setLabelCount(10, true); - binding.chart.getLegend().setEnabled(false); - - Description description = binding.chart.getDescription(); - description.setEnabled(false); - - binding.chart.invalidate(); + List<ILineDataSet> dataSets = new ArrayList<>(); + + LineDataSet dataStatus = new LineDataSet(statusEntry, getString(R.string.cached_messages)); + dataStatus.setDrawValues(false); + dataStatus.setDrawFilled(true); + dataStatus.setDrawCircles(false); + dataStatus.setDrawCircleHole(false); + dataStatus.setMode(LineDataSet.Mode.CUBIC_BEZIER); + dataSets.add(dataStatus); + + LineData data = new LineData(dataSets); + binding.chart.setData(data); + IndexAxisValueFormatter formatter = new IndexAxisValueFormatter() { + @Override + public String getFormattedValue(float value) { + if (value < xVals.size()) { + return xVals.get((int) value); + } else + return ""; + } + }; + + binding.chart.setExtraBottomOffset(80); + // binding.chart.getXAxis().setGranularity(1f); + binding.chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); + binding.chart.getXAxis().setLabelRotationAngle(-45f); + binding.chart.getXAxis().setValueFormatter(formatter); + binding.chart.getXAxis().setEnabled(true); + binding.chart.getXAxis().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); + binding.chart.getAxisLeft().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); + binding.chart.getAxisRight().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); + binding.chart.getLegend().setTextColor(ThemeHelper.getAttColor(CheckHomeCacheActivity.this, R.attr.colorOnBackground)); + binding.chart.getAxisLeft().setAxisMinimum(0f); + binding.chart.getAxisRight().setAxisMinimum(0f); + binding.chart.getXAxis().setLabelCount(10, true); + binding.chart.getLegend().setEnabled(false); + binding.chart.setTouchEnabled(true); + Description description = binding.chart.getDescription(); + description.setEnabled(false); + CustomMarkerView mv = new CustomMarkerView(CheckHomeCacheActivity.this, R.layout.custom_marker_view_layout); + binding.chart.setMarkerView(mv); + + binding.chart.invalidate(); + }); + } catch (DBException | NegativeArraySizeException e) { binding.noAction.setVisibility(View.VISIBLE); @@ -182,38 +187,47 @@ public class CheckHomeCacheActivity extends BaseBarActivity { } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - public static class LineChartXAxisValueFormatter extends IndexAxisValueFormatter { + public class CustomMarkerView extends MarkerView { - @Override - public String getFormattedValue(float value) { + private final TextView tvContent; + private MPPointF mOffset; + + public CustomMarkerView(Context context, int layoutResource) { + super(context, layoutResource); - long emissionsMilliSince1970Time = ((long) value); - Log.v(Helper.TAG, "value: " + value); - Date timeMilliseconds = new Date(emissionsMilliSince1970Time); - DateFormat dateTimeFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); - return dateTimeFormat.format(timeMilliseconds); + // find your layout components + tvContent = findViewById(R.id.tvContent); } - } - public class CustomXAxisRenderer extends XAxisRenderer { - public CustomXAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) { - super(viewPortHandler, xAxis, trans); + // callbacks everytime the MarkerView is redrawn, can be used to update the + // content (user-interface) + @Override + public void refreshContent(Entry e, Highlight highlight) { + tvContent.setText(getString(R.string.messages, (int) e.getY()) + "\r\n" + xVals.get((int) e.getX())); + + // this will perform necessary layouting + super.refreshContent(e, highlight); } @Override - protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) { - String[] line = formattedLabel.split("\n"); - Utils.drawXAxisValue(c, line[0], x, y, mAxisLabelPaint, anchor, angleDegrees); - Utils.drawXAxisValue(c, line[1], x + mAxisLabelPaint.getTextSize(), y + mAxisLabelPaint.getTextSize(), mAxisLabelPaint, anchor, angleDegrees); + public MPPointF getOffset() { + if (mOffset == null) { + // center the marker horizontally and vertically + mOffset = new MPPointF(-(getWidth() / 2), -getHeight()); + } + + return mOffset; } + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); } } diff --git a/app/src/main/res/layouts/mastodon/layout/activity_check_home_cachet.xml b/app/src/main/res/layouts/mastodon/layout/activity_check_home_cachet.xml index a0a27860a..e0814ce63 100644 --- a/app/src/main/res/layouts/mastodon/layout/activity_check_home_cachet.xml +++ b/app/src/main/res/layouts/mastodon/layout/activity_check_home_cachet.xml @@ -25,8 +25,16 @@ android:layout_height="wrap_content" android:orientation="vertical"> + <ProgressBar + android:id="@+id/progress" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_centerInParent="true" + android:indeterminate="true" /> + <com.github.mikephil.charting.charts.LineChart android:id="@+id/chart" + android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content" /> diff --git a/app/src/main/res/layouts/mastodon/layout/custom_marker_view_layout.xml b/app/src/main/res/layouts/mastodon/layout/custom_marker_view_layout.xml new file mode 100644 index 000000000..3b85e1ffc --- /dev/null +++ b/app/src/main/res/layouts/mastodon/layout/custom_marker_view_layout.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="60dp" + android:background="@color/black"> + + <TextView + android:id="@+id/tvContent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_marginLeft="5dp" + android:layout_marginTop="7dp" + android:layout_marginRight="5dp" + android:gravity="center" + android:text="" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="@android:color/white" + android:textSize="12sp" /> + +</RelativeLayout>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8267c0c25..04dc1a0cd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1931,4 +1931,5 @@ <string name="set_autoplay_gif">Autoplay animated media</string> <string name="no_cached_messages">No Home cached messages!</string> <string name="check_home_cache">Check Home cache</string> + <string name="messages">%1$d cached messages</string> </resources>
\ No newline at end of file |