Loading app/src/main/java/app/fedilab/android/mastodon/activities/CheckHomeCacheActivity.java +114 −61 Original line number Diff line number Diff line Loading @@ -15,15 +15,15 @@ package app.fedilab.android.mastodon.activities; * see <http://www.gnu.org/licenses>. */ import static app.fedilab.android.mastodon.viewmodel.mastodon.TimelinesVM.sortAsc; import android.content.Context; import android.os.Bundle; 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 androidx.annotation.Nullable; import com.github.mikephil.charting.components.Description; import com.github.mikephil.charting.components.MarkerView; Loading @@ -40,6 +40,7 @@ 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; Loading @@ -58,6 +59,8 @@ public class CheckHomeCacheActivity extends BaseBarActivity { private ActivityCheckHomeCachetBinding binding; private List<Status> statuses; private List<Status> statusesDay; private ArrayList<String> xVals; @Override Loading @@ -74,67 +77,101 @@ public class CheckHomeCacheActivity extends BaseBarActivity { finish(); return; } drawCacheGraph(range.ALL); binding.chartToggle.setOnCheckedChangeListener((compoundButton, checked) -> drawCacheGraph(checked ? range.DAY : range.ALL)); } private void drawCacheGraph(range myRange) { binding.chartContainer.setVisibility(View.GONE); binding.progress.setVisibility(View.VISIBLE); new Thread(() -> { try { if (myRange == range.ALL) { if (statuses == null) { statuses = new StatusCache(this).getHome(MainActivity.currentAccount); if (statuses == null || statuses.size() < 2) { sortAsc(statuses); } } else if (myRange == range.DAY) { if (statusesDay == null) { statusesDay = new ArrayList<>(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR, -1); for (Status status : statuses) { if (status.created_at.after(calendar.getTime())) { statusesDay.add(status); } } } } if ((statuses == null || statuses.size() < 2) && myRange == range.ALL) { runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE)); return; } if ((statusesDay == null || statusesDay.size() < 2) && myRange == range.DAY) { runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE)); return; } 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); List<Status> statusToAnalyse = new ArrayList<>(); if (myRange == range.ALL) { statusToAnalyse.addAll(statuses); } else { statusToAnalyse.addAll(statusesDay); } }); Date firstMessageDate = statusToAnalyse.get(0).created_at; Date lastMessageDate = statusToAnalyse.get(statusToAnalyse.size() - 1).created_at; long diff = lastMessageDate.getTime() - firstMessageDate.getTime(); int numberOfHour = (int) Math.ceil((double) diff / (1000 * 60 * 60)); List<GraphElement> graphElements = new ArrayList<>(); xVals = new ArrayList<>(); String xDateH; SimpleDateFormat df; String xDateD; 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); for (int i = 0; i < numberOfHour; i++) { Calendar calendar = Calendar.getInstance(); calendar.setTime(firstMessageDate); calendar.add(Calendar.HOUR, i); xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(calendar.getTime()); df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); xDateD = df.format(calendar.getTime()); 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 { GraphElement graphElement = new GraphElement(); graphElement.dateLabel = xDate; int count = 0; for (Status status : statusToAnalyse) { xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(status.created_at); df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); xDateD = df.format(status.created_at.getTime()); xDate = xDateD + " " + String.format(Locale.getDefault(), "%sh", xDateH); if (xDate.equalsIgnoreCase(graphElement.dateLabel)) { count++; } } else { //Last item count++; statusEntry.add(new Entry(index, count)); xVals.add(xDate); } inc++; graphElement.count = count; graphElements.add(graphElement); } runOnUiThread(() -> { binding.progress.setVisibility(View.GONE); binding.chartContainer.setVisibility(View.VISIBLE); //We loop through cache List<Entry> statusEntry = new ArrayList<>(); int inc = 0; for (GraphElement ge : graphElements) { statusEntry.add(new Entry(inc, ge.count)); inc++; } List<ILineDataSet> dataSets = new ArrayList<>(); LineDataSet dataStatus = new LineDataSet(statusEntry, getString(R.string.cached_messages)); dataStatus.setColor(ThemeHelper.getAttColor(this, R.attr.colorPrimary)); dataStatus.setFillColor(ThemeHelper.getAttColor(this, R.attr.colorPrimary)); dataStatus.setDrawValues(false); dataStatus.setDrawFilled(true); dataStatus.setDrawCircles(false); Loading @@ -153,7 +190,6 @@ public class CheckHomeCacheActivity extends BaseBarActivity { return ""; } }; binding.chart.setExtraBottomOffset(80); // binding.chart.getXAxis().setGranularity(1f); binding.chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); Loading Loading @@ -184,9 +220,35 @@ public class CheckHomeCacheActivity extends BaseBarActivity { throw new RuntimeException(e); } }).start(); } public enum range { ALL, DAY } public static class GraphElement { String dateLabel; int count; @Override public boolean equals(@Nullable Object obj) { boolean same = false; if (obj instanceof GraphElement) { same = this.dateLabel.equals(((GraphElement) obj).dateLabel); } return same; } } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } public class CustomMarkerView extends MarkerView { Loading Loading @@ -214,20 +276,11 @@ public class CheckHomeCacheActivity extends BaseBarActivity { public MPPointF getOffset() { if (mOffset == null) { // center the marker horizontally and vertically mOffset = new MPPointF(-(getWidth() / 2), -getHeight()); mOffset = new MPPointF(-(int) (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); } } app/src/main/java/app/fedilab/android/mastodon/viewmodel/mastodon/TimelinesVM.java +5 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,11 @@ public class TimelinesVM extends AndroidViewModel { Collections.sort(statusList, (obj1, obj2) -> obj2.id.compareToIgnoreCase(obj1.id)); } public static void sortAsc(List<Status> statusList) { Collections.sort(statusList, (obj1, obj2) -> obj1.id.compareToIgnoreCase(obj2.id)); } private static void sortDescConv(List<Conversation> conversationList) { Collections.sort(conversationList, (obj1, obj2) -> obj2.id.compareToIgnoreCase(obj1.id)); } Loading app/src/main/res/layouts/mastodon/layout/activity_check_home_cachet.xml +52 −8 Original line number Diff line number Diff line Loading @@ -17,31 +17,73 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical"> <androidx.appcompat.widget.LinearLayoutCompat <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/title_chart1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/chart_home_cache" android:textAppearance="@style/TextAppearance.AppCompat.Medium" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.appcompat.widget.SwitchCompat android:id="@+id/chart_toggle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@string/last_24_h" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/title_chart1" /> <androidx.appcompat.widget.LinearLayoutCompat android:id="@+id/chart_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="20dp" android:visibility="gone" app:layout_constraintDimensionRatio="1:1" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/chart_toggle" tools:visibility="visible"> <com.github.mikephil.charting.charts.LineChart android:id="@+id/chart" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.appcompat.widget.LinearLayoutCompat> <ProgressBar android:id="@+id/progress" app:layout_constraintBottom_toBottomOf="@+id/chart_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/chart_container" 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" /> <RelativeLayout android:id="@+id/no_action" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="@+id/chart_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/chart_container" android:visibility="gone"> <TextView Loading @@ -54,7 +96,9 @@ android:text="@string/no_cached_messages" android:textSize="20sp" /> </RelativeLayout> </androidx.appcompat.widget.LinearLayoutCompat> </androidx.constraintlayout.widget.ConstraintLayout> </ScrollView> app/src/main/res/layouts/mastodon/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2,4 +2,6 @@ <resources> <string name="chart_home_cache">Home cache records per hour</string> <string name="last_24_h">Last 24 hours</string> </resources> No newline at end of file Loading
app/src/main/java/app/fedilab/android/mastodon/activities/CheckHomeCacheActivity.java +114 −61 Original line number Diff line number Diff line Loading @@ -15,15 +15,15 @@ package app.fedilab.android.mastodon.activities; * see <http://www.gnu.org/licenses>. */ import static app.fedilab.android.mastodon.viewmodel.mastodon.TimelinesVM.sortAsc; import android.content.Context; import android.os.Bundle; 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 androidx.annotation.Nullable; import com.github.mikephil.charting.components.Description; import com.github.mikephil.charting.components.MarkerView; Loading @@ -40,6 +40,7 @@ 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; Loading @@ -58,6 +59,8 @@ public class CheckHomeCacheActivity extends BaseBarActivity { private ActivityCheckHomeCachetBinding binding; private List<Status> statuses; private List<Status> statusesDay; private ArrayList<String> xVals; @Override Loading @@ -74,67 +77,101 @@ public class CheckHomeCacheActivity extends BaseBarActivity { finish(); return; } drawCacheGraph(range.ALL); binding.chartToggle.setOnCheckedChangeListener((compoundButton, checked) -> drawCacheGraph(checked ? range.DAY : range.ALL)); } private void drawCacheGraph(range myRange) { binding.chartContainer.setVisibility(View.GONE); binding.progress.setVisibility(View.VISIBLE); new Thread(() -> { try { if (myRange == range.ALL) { if (statuses == null) { statuses = new StatusCache(this).getHome(MainActivity.currentAccount); if (statuses == null || statuses.size() < 2) { sortAsc(statuses); } } else if (myRange == range.DAY) { if (statusesDay == null) { statusesDay = new ArrayList<>(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_YEAR, -1); for (Status status : statuses) { if (status.created_at.after(calendar.getTime())) { statusesDay.add(status); } } } } if ((statuses == null || statuses.size() < 2) && myRange == range.ALL) { runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE)); return; } if ((statusesDay == null || statusesDay.size() < 2) && myRange == range.DAY) { runOnUiThread(() -> binding.noAction.setVisibility(View.VISIBLE)); return; } 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); List<Status> statusToAnalyse = new ArrayList<>(); if (myRange == range.ALL) { statusToAnalyse.addAll(statuses); } else { statusToAnalyse.addAll(statusesDay); } }); Date firstMessageDate = statusToAnalyse.get(0).created_at; Date lastMessageDate = statusToAnalyse.get(statusToAnalyse.size() - 1).created_at; long diff = lastMessageDate.getTime() - firstMessageDate.getTime(); int numberOfHour = (int) Math.ceil((double) diff / (1000 * 60 * 60)); List<GraphElement> graphElements = new ArrayList<>(); xVals = new ArrayList<>(); String xDateH; SimpleDateFormat df; String xDateD; 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); for (int i = 0; i < numberOfHour; i++) { Calendar calendar = Calendar.getInstance(); calendar.setTime(firstMessageDate); calendar.add(Calendar.HOUR, i); xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(calendar.getTime()); df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); xDateD = df.format(calendar.getTime()); 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 { GraphElement graphElement = new GraphElement(); graphElement.dateLabel = xDate; int count = 0; for (Status status : statusToAnalyse) { xDateH = new SimpleDateFormat("hh", Locale.getDefault()).format(status.created_at); df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); xDateD = df.format(status.created_at.getTime()); xDate = xDateD + " " + String.format(Locale.getDefault(), "%sh", xDateH); if (xDate.equalsIgnoreCase(graphElement.dateLabel)) { count++; } } else { //Last item count++; statusEntry.add(new Entry(index, count)); xVals.add(xDate); } inc++; graphElement.count = count; graphElements.add(graphElement); } runOnUiThread(() -> { binding.progress.setVisibility(View.GONE); binding.chartContainer.setVisibility(View.VISIBLE); //We loop through cache List<Entry> statusEntry = new ArrayList<>(); int inc = 0; for (GraphElement ge : graphElements) { statusEntry.add(new Entry(inc, ge.count)); inc++; } List<ILineDataSet> dataSets = new ArrayList<>(); LineDataSet dataStatus = new LineDataSet(statusEntry, getString(R.string.cached_messages)); dataStatus.setColor(ThemeHelper.getAttColor(this, R.attr.colorPrimary)); dataStatus.setFillColor(ThemeHelper.getAttColor(this, R.attr.colorPrimary)); dataStatus.setDrawValues(false); dataStatus.setDrawFilled(true); dataStatus.setDrawCircles(false); Loading @@ -153,7 +190,6 @@ public class CheckHomeCacheActivity extends BaseBarActivity { return ""; } }; binding.chart.setExtraBottomOffset(80); // binding.chart.getXAxis().setGranularity(1f); binding.chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); Loading Loading @@ -184,9 +220,35 @@ public class CheckHomeCacheActivity extends BaseBarActivity { throw new RuntimeException(e); } }).start(); } public enum range { ALL, DAY } public static class GraphElement { String dateLabel; int count; @Override public boolean equals(@Nullable Object obj) { boolean same = false; if (obj instanceof GraphElement) { same = this.dateLabel.equals(((GraphElement) obj).dateLabel); } return same; } } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } public class CustomMarkerView extends MarkerView { Loading Loading @@ -214,20 +276,11 @@ public class CheckHomeCacheActivity extends BaseBarActivity { public MPPointF getOffset() { if (mOffset == null) { // center the marker horizontally and vertically mOffset = new MPPointF(-(getWidth() / 2), -getHeight()); mOffset = new MPPointF(-(int) (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); } }
app/src/main/java/app/fedilab/android/mastodon/viewmodel/mastodon/TimelinesVM.java +5 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,11 @@ public class TimelinesVM extends AndroidViewModel { Collections.sort(statusList, (obj1, obj2) -> obj2.id.compareToIgnoreCase(obj1.id)); } public static void sortAsc(List<Status> statusList) { Collections.sort(statusList, (obj1, obj2) -> obj1.id.compareToIgnoreCase(obj2.id)); } private static void sortDescConv(List<Conversation> conversationList) { Collections.sort(conversationList, (obj1, obj2) -> obj2.id.compareToIgnoreCase(obj1.id)); } Loading
app/src/main/res/layouts/mastodon/layout/activity_check_home_cachet.xml +52 −8 Original line number Diff line number Diff line Loading @@ -17,31 +17,73 @@ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical"> <androidx.appcompat.widget.LinearLayoutCompat <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/title_chart1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/chart_home_cache" android:textAppearance="@style/TextAppearance.AppCompat.Medium" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.appcompat.widget.SwitchCompat android:id="@+id/chart_toggle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@string/last_24_h" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/title_chart1" /> <androidx.appcompat.widget.LinearLayoutCompat android:id="@+id/chart_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="20dp" android:visibility="gone" app:layout_constraintDimensionRatio="1:1" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/chart_toggle" tools:visibility="visible"> <com.github.mikephil.charting.charts.LineChart android:id="@+id/chart" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.appcompat.widget.LinearLayoutCompat> <ProgressBar android:id="@+id/progress" app:layout_constraintBottom_toBottomOf="@+id/chart_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/chart_container" 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" /> <RelativeLayout android:id="@+id/no_action" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="@+id/chart_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/chart_container" android:visibility="gone"> <TextView Loading @@ -54,7 +96,9 @@ android:text="@string/no_cached_messages" android:textSize="20sp" /> </RelativeLayout> </androidx.appcompat.widget.LinearLayoutCompat> </androidx.constraintlayout.widget.ConstraintLayout> </ScrollView>
app/src/main/res/layouts/mastodon/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2,4 +2,6 @@ <resources> <string name="chart_home_cache">Home cache records per hour</string> <string name="last_24_h">Last 24 hours</string> </resources> No newline at end of file