This commit is contained in:
Thomas 2023-03-04 18:28:59 +01:00
parent c04a51f3b7
commit 74b107f1d3
4 changed files with 158 additions and 114 deletions

View file

@ -15,34 +15,31 @@ package app.fedilab.android.mastodon.activities;
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.graphics.Canvas; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.TextView;
import androidx.appcompat.widget.LinearLayoutCompat; import androidx.appcompat.widget.LinearLayoutCompat;
import com.github.mikephil.charting.components.Description; 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.components.XAxis;
import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter; 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.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.renderer.XAxisRenderer;
import com.github.mikephil.charting.utils.MPPointF; 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.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; 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.api.Status;
import app.fedilab.android.mastodon.client.entities.app.StatusCache; import app.fedilab.android.mastodon.client.entities.app.StatusCache;
import app.fedilab.android.mastodon.exception.DBException; import app.fedilab.android.mastodon.exception.DBException;
import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.helper.ThemeHelper; import app.fedilab.android.mastodon.helper.ThemeHelper;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@ -62,6 +58,7 @@ public class CheckHomeCacheActivity extends BaseBarActivity {
private ActivityCheckHomeCachetBinding binding; private ActivityCheckHomeCachetBinding binding;
private List<Status> statuses; private List<Status> statuses;
private ArrayList<String> xVals;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -77,16 +74,6 @@ public class CheckHomeCacheActivity extends BaseBarActivity {
finish(); finish();
return; 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(() -> { new Thread(() -> {
try { try {
@ -95,83 +82,101 @@ public class CheckHomeCacheActivity extends BaseBarActivity {
runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE)); runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE));
return; return;
} }
runOnUiThread(() -> {
final ArrayList<String> xVals = new ArrayList<>(); binding.progress.setVisibility(View.GONE);
String xDate; binding.chart.setVisibility(View.VISIBLE);
int inc = 0; binding.chart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
//We loop through cache @Override
List<Entry> statusEntry = new ArrayList<>(); public void onGlobalLayout() {
int index = 0; binding.chart.getViewTreeObserver().removeOnGlobalLayoutListener(this);
for (Status status : statuses) { int height = (binding.chart.getWidth());
//We aggregate message in same hour range LinearLayoutCompat.LayoutParams params = new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
boolean sameHourRange = true; binding.chart.setLayoutParams(params);
int count = 0; binding.chart.setVisibility(View.VISIBLE);
while (inc < statuses.size() && sameHourRange) { }
Calendar currentStatusDate = Calendar.getInstance(); });
currentStatusDate.setTime(statuses.get(inc).created_at); xVals = new ArrayList<>();
String xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(statuses.get(inc).created_at); String xDate;
SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); int inc = 0;
String xDateD = df.format(statuses.get(inc).created_at); //We loop through cache
xDate = xDateD + " " + String.format(Locale.getDefault(), "%sh", xDateH); List<Entry> statusEntry = new ArrayList<>();
if (inc + 1 < statuses.size()) { int index = 0;
Calendar nextStatusDate = Calendar.getInstance(); for (Status status : statuses) {
nextStatusDate.setTime(statuses.get(inc + 1).created_at); //We aggregate message in same hour range
if (currentStatusDate.get(Calendar.HOUR) != nextStatusDate.get(Calendar.HOUR)) { boolean sameHourRange = true;
sameHourRange = false; int count = 0;
statusEntry.add(new Entry(index, count)); while (inc < statuses.size() && sameHourRange) {
index++; Calendar currentStatusDate = Calendar.getInstance();
xVals.add(xDate); currentStatusDate.setTime(statuses.get(inc).created_at);
} else { String xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(statuses.get(inc).created_at);
count++; SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
} String xDateD = df.format(statuses.get(inc).created_at);
} else { //Last item xDate = xDateD + " " + String.format(Locale.getDefault(), "%sh", xDateH);
count++; if (inc + 1 < statuses.size()) {
statusEntry.add(new Entry(index, count)); Calendar nextStatusDate = Calendar.getInstance();
xVals.add(xDate); 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));
xVals.add(xDate);
}
inc++;
} }
inc++;
} }
} List<ILineDataSet> dataSets = new ArrayList<>();
List<ILineDataSet> dataSets = new ArrayList<>();
LineDataSet dataStatus = new LineDataSet(statusEntry, getString(R.string.cached_messages)); LineDataSet dataStatus = new LineDataSet(statusEntry, getString(R.string.cached_messages));
dataStatus.setDrawValues(false); dataStatus.setDrawValues(false);
dataStatus.setDrawFilled(true); dataStatus.setDrawFilled(true);
dataStatus.setDrawCircles(false); dataStatus.setDrawCircles(false);
dataStatus.setDrawCircleHole(false); dataStatus.setDrawCircleHole(false);
dataStatus.setMode(LineDataSet.Mode.CUBIC_BEZIER); dataStatus.setMode(LineDataSet.Mode.CUBIC_BEZIER);
dataSets.add(dataStatus); dataSets.add(dataStatus);
LineData data = new LineData(dataSets); LineData data = new LineData(dataSets);
binding.chart.setData(data); binding.chart.setData(data);
IndexAxisValueFormatter formatter = new IndexAxisValueFormatter() { IndexAxisValueFormatter formatter = new IndexAxisValueFormatter() {
@Override @Override
public String getFormattedValue(float value) { public String getFormattedValue(float value) {
if (value < xVals.size()) { if (value < xVals.size()) {
return xVals.get((int) value); return xVals.get((int) value);
} else } else
return ""; 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(); binding.chart.setExtraBottomOffset(80);
description.setEnabled(false); // 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();
});
binding.chart.invalidate();
} catch (DBException | NegativeArraySizeException e) { } catch (DBException | NegativeArraySizeException e) {
binding.noAction.setVisibility(View.VISIBLE); binding.noAction.setVisibility(View.VISIBLE);
@ -182,6 +187,41 @@ public class CheckHomeCacheActivity extends BaseBarActivity {
} }
public class CustomMarkerView extends MarkerView {
private final TextView tvContent;
private MPPointF mOffset;
public CustomMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
// find your layout components
tvContent = findViewById(R.id.tvContent);
}
// 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
public MPPointF getOffset() {
if (mOffset == null) {
// center the marker horizontally and vertically
mOffset = new MPPointF(-(getWidth() / 2), -getHeight());
}
return mOffset;
}
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) { if (item.getItemId() == android.R.id.home) {
@ -190,30 +230,4 @@ public class CheckHomeCacheActivity extends BaseBarActivity {
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
public static class LineChartXAxisValueFormatter extends IndexAxisValueFormatter {
@Override
public String getFormattedValue(float value) {
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);
}
}
public class CustomXAxisRenderer extends XAxisRenderer {
public CustomXAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) {
super(viewPortHandler, xAxis, trans);
}
@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);
}
}
} }

View file

@ -25,8 +25,16 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> 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 <com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart" android:id="@+id/chart"
android:visibility="gone"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />

View file

@ -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>

View file

@ -1931,4 +1931,5 @@
<string name="set_autoplay_gif">Autoplay animated media</string> <string name="set_autoplay_gif">Autoplay animated media</string>
<string name="no_cached_messages">No Home cached messages!</string> <string name="no_cached_messages">No Home cached messages!</string>
<string name="check_home_cache">Check Home cache</string> <string name="check_home_cache">Check Home cache</string>
<string name="messages">%1$d cached messages</string>
</resources> </resources>