This commit is contained in:
Thomas 2023-03-04 17:40:23 +01:00
parent 6019f5129b
commit c04a51f3b7
8 changed files with 332 additions and 1 deletions

View file

@ -265,7 +265,11 @@
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/action_about" android:label="@string/action_about"
android:theme="@style/AppThemeBar" /> android:theme="@style/AppThemeBar" />
<activity
android:name=".mastodon.activities.CheckHomeCacheActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/home_cache"
android:theme="@style/AppThemeBar" />
<activity <activity
android:name=".mastodon.activities.admin.AdminDomainBlockActivity" android:name=".mastodon.activities.admin.AdminDomainBlockActivity"
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"

View file

@ -0,0 +1,219 @@
package app.fedilab.android.mastodon.activities;
/* Copyright 2023 Thomas Schneider
*
* This file is a part of Fedilab
*
* 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.
*
* Fedilab 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 Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import android.graphics.Canvas;
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 androidx.appcompat.widget.LinearLayoutCompat;
import com.github.mikephil.charting.components.Description;
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.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;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
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;
public class CheckHomeCacheActivity extends BaseBarActivity {
private ActivityCheckHomeCachetBinding binding;
private List<Status> statuses;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCheckHomeCachetBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
if (MainActivity.currentAccount == null || MainActivity.currentAccount.mastodon_account == null) {
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 {
statuses = new StatusCache(this).getHome(MainActivity.currentAccount);
if (statuses == null || statuses.size() < 2) {
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;
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++;
}
}
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();
} catch (DBException | NegativeArraySizeException e) {
binding.noAction.setVisibility(View.VISIBLE);
Toasty.error(this, getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
throw new RuntimeException(e);
}
}).start();
}
@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 {
@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

@ -229,6 +229,28 @@ public class StatusCache {
return count; return count;
} }
/**
* get all cache messages for home
*
* @param baseAccount Status {@link BaseAccount}
* @return List<Status>
* @throws DBException Exception
*/
public List<Status> getHome(BaseAccount baseAccount) throws DBException {
if (db == null) {
throw new DBException("db is null. Wrong initialization.");
}
String selection = Sqlite.COL_INSTANCE + "='" + baseAccount.instance + "' AND " + Sqlite.COL_USER_ID + "= '" + baseAccount.user_id + "' AND " + Sqlite.COL_SLUG + "= '" + Timeline.TimeLineEnum.HOME.getValue() + "' ";
try {
Cursor c = db.query(Sqlite.TABLE_STATUS_CACHE, null, selection, null, Sqlite.COL_STATUS_ID, null, Sqlite.COL_STATUS_ID + " ASC", null);
return cursorToListOfStatuses(c);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/** /**
* count messages for other timelines * count messages for other timelines
* *

View file

@ -15,10 +15,12 @@ package app.fedilab.android.mastodon.ui.fragment.settings;
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
@ -29,6 +31,7 @@ import androidx.work.WorkManager;
import app.fedilab.android.BaseMainActivity; import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R; import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity; import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.mastodon.activities.CheckHomeCacheActivity;
import app.fedilab.android.mastodon.helper.Helper; import app.fedilab.android.mastodon.helper.Helper;
import app.fedilab.android.mastodon.jobs.FetchHomeWorker; import app.fedilab.android.mastodon.jobs.FetchHomeWorker;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
@ -65,6 +68,15 @@ public class FragmentHomeCacheSettings extends PreferenceFragmentCompat implemen
String timeRefresh = sharedpreferences.getString(getString(R.string.SET_FETCH_HOME_DELAY_VALUE) + MainActivity.currentUserID + MainActivity.currentInstance, "60"); String timeRefresh = sharedpreferences.getString(getString(R.string.SET_FETCH_HOME_DELAY_VALUE) + MainActivity.currentUserID + MainActivity.currentInstance, "60");
SET_FETCH_HOME_DELAY_VALUE.setValue(timeRefresh); SET_FETCH_HOME_DELAY_VALUE.setValue(timeRefresh);
} }
Preference pref_category_show_data = findPreference(getString(R.string.pref_category_show_data));
if (pref_category_show_data != null) {
pref_category_show_data.setOnPreferenceClickListener(preference -> {
startActivity(new Intent(requireActivity(), CheckHomeCacheActivity.class));
return false;
});
}
} }

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M3.5,18.49l6,-6.01 4,4L22,6.92l-1.41,-1.41 -7.09,7.97 -4,-4L2,16.99z" />
</vector>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright 2023 Thomas Schneider
This file is a part of Fedilab
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.
Fedilab 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 Fedilab; if not,
see <http://www.gnu.org/licenses>.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="@+id/no_action"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<TextView
android:id="@+id/no_action_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:padding="10dp"
android:text="@string/no_cached_messages"
android:textSize="20sp" />
</RelativeLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</ScrollView>

View file

@ -1645,6 +1645,8 @@
<item>u+1f6a9</item> <item>u+1f6a9</item>
</string-array> </string-array>
<string name="pref_category_key_account" translatable="false">pref_category_account</string> <string name="pref_category_key_account" translatable="false">pref_category_account</string>
<string name="pref_category_show_data" translatable="false">pref_category_show_data</string>
<string name="pref_category_key_timeline" translatable="false">pref_category_timeline</string> <string name="pref_category_key_timeline" translatable="false">pref_category_timeline</string>
<string name="pref_category_key_notifications" translatable="false">pref_category_notifications</string> <string name="pref_category_key_notifications" translatable="false">pref_category_notifications</string>
<string name="pref_category_key_interface" translatable="false">pref_category_interface</string> <string name="pref_category_key_interface" translatable="false">pref_category_interface</string>
@ -1927,4 +1929,6 @@
<string name="send_anyway">Send anyway</string> <string name="send_anyway">Send anyway</string>
<string name="set_remove_battery">Ignore battery optimizations</string> <string name="set_remove_battery">Ignore battery optimizations</string>
<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="check_home_cache">Check Home cache</string>
</resources> </resources>

View file

@ -23,4 +23,11 @@
app:title="@string/type_of_home_delay_title" app:title="@string/type_of_home_delay_title"
app:useSimpleSummaryProvider="true" /> app:useSimpleSummaryProvider="true" />
<Preference
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:title="@string/check_home_cache"
app:icon="@drawable/baseline_show_chart_24"
app:iconSpaceReserved="false"
app:key="@string/pref_category_show_data" />
</PreferenceScreen> </PreferenceScreen>