diff --git a/app/src/main/java/app/fedilab/android/activities/CacheActivity.java b/app/src/main/java/app/fedilab/android/activities/CacheActivity.java index 58566b8c..7a8dce5b 100644 --- a/app/src/main/java/app/fedilab/android/activities/CacheActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/CacheActivity.java @@ -19,27 +19,34 @@ import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.view.Menu; import android.view.MenuItem; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import app.fedilab.android.R; import app.fedilab.android.client.entities.app.Account; import app.fedilab.android.client.entities.app.BaseAccount; +import app.fedilab.android.client.entities.app.CacheAccount; import app.fedilab.android.databinding.ActivityCacheBinding; import app.fedilab.android.helper.CacheHelper; +import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.ui.drawer.CacheAdapter; public class CacheActivity extends BaseActivity { private ActivityCacheBinding binding; - + private List cacheAccounts; + private CacheAdapter cacheAdapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -61,24 +68,52 @@ public class CacheActivity extends BaseActivity { new Thread(() -> { List accounts = new Account(CacheActivity.this).getPushNotificationAccounts(); + cacheAccounts = new ArrayList<>(); + for (BaseAccount baseAccount : accounts) { + CacheAccount cacheAccount = new CacheAccount(); + cacheAccount.account = baseAccount; + cacheAccounts.add(cacheAccount); + } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> { - CacheAdapter cacheAdapter = new CacheAdapter(accounts); + cacheAdapter = new CacheAdapter(cacheAccounts); + binding.cacheRecyclerview.setAdapter(cacheAdapter); LinearLayoutManager mLayoutManager = new LinearLayoutManager(CacheActivity.this); binding.cacheRecyclerview.setLayoutManager(mLayoutManager); - binding.cacheRecyclerview.setAdapter(cacheAdapter); }; mainHandler.post(myRunnable); }).start(); } + @Override + public boolean onCreateOptionsMenu(@NonNull Menu menu) { + getMenuInflater().inflate(R.menu.menu_cache, menu); + return super.onCreateOptionsMenu(menu); + } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; + } else if (item.getItemId() == R.id.action_clear) { + AlertDialog.Builder deleteConfirm = new AlertDialog.Builder(CacheActivity.this, Helper.dialogStyle()); + deleteConfirm.setTitle(getString(R.string.delete_cache)); + deleteConfirm.setMessage(getString(R.string.delete_cache_message)); + deleteConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); + deleteConfirm.setPositiveButton(R.string.delete, (dialog, which) -> { + CacheHelper.clearCache(CacheActivity.this, binding.labelFileCache.isChecked(), cacheAccounts, () -> CacheHelper.getCacheValues(CacheActivity.this, size -> { + if (size > 0) { + size = size / 1000000.0f; + } + binding.fileCacheSize.setText(String.format("%s %s", String.format(Locale.getDefault(), "%.2f", size), getString(R.string.cache_units))); + cacheAdapter.notifyDataSetChanged(); + })); + dialog.dismiss(); + }); + deleteConfirm.create().show(); + return true; } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/CacheAccount.java b/app/src/main/java/app/fedilab/android/client/entities/app/CacheAccount.java new file mode 100644 index 00000000..7f27aea5 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/client/entities/app/CacheAccount.java @@ -0,0 +1,31 @@ +package app.fedilab.android.client.entities.app; +/* Copyright 2022 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 . */ + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +public class CacheAccount implements Serializable { + + @SerializedName("clear_home") + public boolean clear_home = true; + @SerializedName("clear_other") + public boolean clear_other = true; + @SerializedName("clear_drafts") + public boolean clear_drafts = false; + @SerializedName("account") + public BaseAccount account; +} diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/StatusDraft.java b/app/src/main/java/app/fedilab/android/client/entities/app/StatusDraft.java index 711d9c8f..fd915a58 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/StatusDraft.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/StatusDraft.java @@ -191,6 +191,17 @@ public class StatusDraft implements Serializable { return db.delete(Sqlite.TABLE_STATUS_DRAFT, Sqlite.COL_USER_ID + " = '" + BaseMainActivity.currentUserID + "' AND " + Sqlite.COL_INSTANCE + " = '" + BaseMainActivity.currentInstance + "'", null); } + /** + * Remove all drafts for an account from db + * + * @return int + */ + public int removeAllDraftFor(BaseAccount account) throws DBException { + if (db == null) { + throw new DBException("db is null. Wrong initialization."); + } + return db.delete(Sqlite.TABLE_STATUS_DRAFT, Sqlite.COL_USER_ID + " = '" + account.user_id + "' AND " + Sqlite.COL_INSTANCE + " = '" + account.instance + "'", null); + } public int count(BaseAccount account) throws DBException { if (db == null) { diff --git a/app/src/main/java/app/fedilab/android/helper/CacheHelper.java b/app/src/main/java/app/fedilab/android/helper/CacheHelper.java index 4a87274b..6e793e46 100644 --- a/app/src/main/java/app/fedilab/android/helper/CacheHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/CacheHelper.java @@ -14,35 +14,21 @@ package app.fedilab.android.helper; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ -import static app.fedilab.android.helper.Helper.getCurrentAccount; - import android.content.Context; import android.os.Handler; import android.os.Looper; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.SwitchCompat; import java.io.File; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.Objects; -import app.fedilab.android.BaseMainActivity; -import app.fedilab.android.R; import app.fedilab.android.client.entities.app.BaseAccount; +import app.fedilab.android.client.entities.app.CacheAccount; import app.fedilab.android.client.entities.app.QuickLoad; import app.fedilab.android.client.entities.app.StatusCache; import app.fedilab.android.client.entities.app.StatusDraft; import app.fedilab.android.exception.DBException; -import es.dmoral.toasty.Toasty; public class CacheHelper { @@ -133,65 +119,46 @@ public class CacheHelper { void getcount(List countStatuses); } - public static class CacheTask { - private final WeakReference contextReference; - private float cacheSize; - - public CacheTask(Context context) { - contextReference = new WeakReference<>(context); - doInBackground(); - } - - protected void doInBackground() { - new Thread(() -> { - long sizeCache = cacheSize(contextReference.get().getCacheDir().getParentFile()); - cacheSize = 0; - if (sizeCache > 0) { - cacheSize = (float) sizeCache / 1000000.0f; + public static void clearCache(Context context, boolean clearFiles, List cacheAccounts, CallbackClear callbackClear) { + new Thread(() -> { + if (clearFiles) { + String path = context.getCacheDir().getParentFile().getPath(); + File dir = new File(path); + if (dir.isDirectory()) { + deleteDir(dir); } - Handler mainHandler = new Handler(Looper.getMainLooper()); - Runnable myRunnable = () -> { - AlertDialog.Builder builder = new AlertDialog.Builder(contextReference.get(), Helper.dialogStyle()); - LayoutInflater inflater = ((BaseMainActivity) contextReference.get()).getLayoutInflater(); - View dialogView = inflater.inflate(R.layout.popup_cache, new LinearLayout(contextReference.get()), false); - TextView message = dialogView.findViewById(R.id.message); - message.setText(contextReference.get().getString(R.string.cache_message, String.format("%s %s", String.format(Locale.getDefault(), "%.2f", cacheSize), contextReference.get().getString(R.string.cache_units)))); - builder.setView(dialogView); - builder.setTitle(R.string.cache_title); + } + for (CacheAccount cacheAccount : cacheAccounts) { + if (cacheAccount.clear_home) { + try { + new StatusCache(context).deleteForAccount(cacheAccount.account); + } catch (DBException e) { + e.printStackTrace(); + } + } + if (cacheAccount.clear_other) { + try { + new QuickLoad(context).deleteForAccount(cacheAccount.account); + } catch (DBException e) { + e.printStackTrace(); + } + } + if (cacheAccount.clear_drafts) { + try { + new StatusDraft(context).removeAllDraftFor(cacheAccount.account); + } catch (DBException e) { + e.printStackTrace(); + } + } + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = callbackClear::onCleared; + mainHandler.post(myRunnable); + }).start(); + } - final SwitchCompat clean_all = dialogView.findViewById(R.id.clean_all); - final float finalCacheSize = cacheSize; - builder - .setPositiveButton(R.string.clear, (dialog, which) -> new Thread(() -> { - try { - String path = Objects.requireNonNull(contextReference.get().getCacheDir().getParentFile()).getPath(); - File dir = new File(path); - if (dir.isDirectory()) { - deleteDir(dir); - } - if (clean_all.isChecked()) { - new QuickLoad(contextReference.get()).deleteForAllAccount(); - new StatusCache(contextReference.get()).deleteForAllAccount(); - } else { - new QuickLoad(contextReference.get()).deleteForAccount(getCurrentAccount(contextReference.get())); - new StatusCache(contextReference.get()).deleteForAccount(getCurrentAccount(contextReference.get())); - } - Handler mainHandler2 = new Handler(Looper.getMainLooper()); - Runnable myRunnable2 = () -> { - Toasty.success(contextReference.get(), contextReference.get().getString(R.string.toast_cache_clear, String.format("%s %s", String.format(Locale.getDefault(), "%.2f", finalCacheSize), contextReference.get().getString(R.string.cache_units))), Toast.LENGTH_LONG).show(); - dialog.dismiss(); - }; - mainHandler2.post(myRunnable2); - } catch (Exception ignored) { - } - }).start()) - .setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()) - .setIcon(android.R.drawable.ic_dialog_alert) - .show(); - }; - mainHandler.post(myRunnable); - }).start(); - } + public interface CallbackClear { + void onCleared(); } } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/CacheAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/CacheAdapter.java index 953e058c..f914d301 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/CacheAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/CacheAdapter.java @@ -24,8 +24,7 @@ import androidx.recyclerview.widget.RecyclerView; import java.util.List; -import app.fedilab.android.activities.ProfileActivity; -import app.fedilab.android.client.entities.app.BaseAccount; +import app.fedilab.android.client.entities.app.CacheAccount; import app.fedilab.android.databinding.DrawerCacheBinding; import app.fedilab.android.helper.CacheHelper; import app.fedilab.android.helper.MastodonHelper; @@ -33,11 +32,10 @@ import app.fedilab.android.helper.MastodonHelper; public class CacheAdapter extends RecyclerView.Adapter { - private static ProfileActivity.action doAction; - private final List accountList; + private final List accountList; private Context context; - public CacheAdapter(List accountList) { + public CacheAdapter(List accountList) { this.accountList = accountList; } @@ -46,10 +44,11 @@ public class CacheAdapter extends RecyclerView.Adapter return accountList.size(); } - public BaseAccount getItem(int position) { + public CacheAccount getItem(int position) { return accountList.get(position); } + @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { @@ -60,18 +59,24 @@ public class CacheAdapter extends RecyclerView.Adapter @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { - BaseAccount account = accountList.get(position); + CacheAccount cacheAccount = accountList.get(position); AccountCacheViewHolder holder = (AccountCacheViewHolder) viewHolder; - MastodonHelper.loadPPMastodon(holder.binding.pp, account.mastodon_account); - holder.binding.acct.setText(String.format("@%s@%s", account.mastodon_account.username, account.instance)); - holder.binding.displayName.setText(account.mastodon_account.display_name); - CacheHelper.getTimelineValues(context, account, countStatuses -> { + MastodonHelper.loadPPMastodon(holder.binding.pp, cacheAccount.account.mastodon_account); + holder.binding.acct.setText(String.format("@%s@%s", cacheAccount.account.mastodon_account.username, cacheAccount.account.instance)); + holder.binding.displayName.setText(cacheAccount.account.mastodon_account.display_name); + CacheHelper.getTimelineValues(context, cacheAccount.account, countStatuses -> { if (countStatuses != null && countStatuses.size() == 3) { holder.binding.homeCount.setText(String.valueOf(countStatuses.get(0))); holder.binding.otherCount.setText(String.valueOf(countStatuses.get(1))); holder.binding.draftCount.setText(String.valueOf(countStatuses.get(2))); } }); + holder.binding.labelHomeTimelineCacheCount.setChecked(cacheAccount.clear_home); + holder.binding.labelTimelinesCacheCount.setChecked(cacheAccount.clear_other); + holder.binding.labelDraftsCount.setChecked(cacheAccount.clear_drafts); + holder.binding.labelHomeTimelineCacheCount.setOnCheckedChangeListener((compoundButton, checked) -> cacheAccount.clear_home = checked); + holder.binding.labelTimelinesCacheCount.setOnCheckedChangeListener((compoundButton, checked) -> cacheAccount.clear_other = checked); + holder.binding.labelDraftsCount.setOnCheckedChangeListener((compoundButton, checked) -> cacheAccount.clear_drafts = checked); } public long getItemId(int position) { diff --git a/app/src/main/res/menu/menu_cache.xml b/app/src/main/res/menu/menu_cache.xml new file mode 100644 index 00000000..b515daac --- /dev/null +++ b/app/src/main/res/menu/menu_cache.xml @@ -0,0 +1,9 @@ + + + + \ 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 4e4723e1..16a5b8c3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1635,6 +1635,8 @@ Built-in browser cache Fiiles cache File cache size + Clear cache + Are you sure you want to delete cache? If you have drafts with media, the attached media will be lost.