Quellcode durchsuchen

Add an option to change cache size and clear the cache

inorichi vor 10 Jahren
Ursprung
Commit
8f7443a686
22 geänderte Dateien mit 331 neuen und 158 gelöschten Zeilen
  1. 6 0
      app/build.gradle
  2. 40 56
      app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java
  3. 4 0
      app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java
  4. 5 5
      app/src/main/java/eu/kanade/mangafeed/injection/component/AppComponent.java
  5. 2 2
      app/src/main/java/eu/kanade/mangafeed/injection/module/DataModule.java
  6. 7 19
      app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsAccountsFragment.java
  7. 52 0
      app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsActivity.java
  8. 92 0
      app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsCacheFragment.java
  9. 5 21
      app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsDownloadsFragment.java
  10. 0 44
      app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsMainFragment.java
  11. 17 6
      app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsNestedFragment.java
  12. 1 1
      app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/ChapterSyncLoginDialog.java
  13. 35 0
      app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/IntListPreference.java
  14. 1 1
      app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/LoginDialogPreference.java
  15. 1 1
      app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/SourceLoginDialog.java
  16. 13 0
      app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java
  17. 12 0
      app/src/main/res/values/arrays.xml
  18. 4 0
      app/src/main/res/values/keys.xml
  19. 12 2
      app/src/main/res/values/strings.xml
  20. 16 0
      app/src/main/res/xml/pref_cache.xml
  21. 5 0
      app/src/main/res/xml/pref_main.xml
  22. 1 0
      build.gradle

+ 6 - 0
app/build.gradle

@@ -95,6 +95,12 @@ dependencies {
     compile('com.mikepenz:materialdrawer:4.4.8@aar') {
         transitive = true
     }
+    compile('com.github.afollestad.material-dialogs:core:0.8.5.2@aar') {
+        transitive = true
+    }
+    compile('com.github.afollestad.material-dialogs:commons:0.8.5.2@aar') {
+        transitive = true
+    }
 
     testCompile 'junit:junit:4.12'
     testCompile "org.hamcrest:hamcrest-core:$HAMCREST_VERSION"

+ 40 - 56
app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java

@@ -1,8 +1,8 @@
 package eu.kanade.mangafeed.data.cache;
 
 import android.content.Context;
+import android.text.format.Formatter;
 
-import com.bumptech.glide.Glide;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import com.jakewharton.disklrucache.DiskLruCache;
@@ -15,6 +15,7 @@ import java.io.OutputStream;
 import java.lang.reflect.Type;
 import java.util.List;
 
+import eu.kanade.mangafeed.data.preference.PreferencesHelper;
 import eu.kanade.mangafeed.data.source.model.Page;
 import eu.kanade.mangafeed.util.DiskUtils;
 import okio.BufferedSink;
@@ -26,67 +27,54 @@ public class CacheManager {
     private static final String PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache";
     private static final int PARAMETER_APP_VERSION = 1;
     private static final int PARAMETER_VALUE_COUNT = 1;
-    private static final long PARAMETER_CACHE_SIZE = 100 * 1024 * 1024;
-    private static final int READ_TIMEOUT = 60;
 
-    private Context mContext;
-    private Gson mGson;
+    private Context context;
+    private Gson gson;
 
-    private DiskLruCache mDiskCache;
+    private DiskLruCache diskCache;
 
-    public CacheManager(Context context) {
-        mContext = context;
-        mGson = new Gson();
+    public CacheManager(Context context, PreferencesHelper preferences) {
+        this.context = context;
+        gson = new Gson();
 
         try {
-            mDiskCache = DiskLruCache.open(
+            diskCache = DiskLruCache.open(
                     new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY),
                     PARAMETER_APP_VERSION,
                     PARAMETER_VALUE_COUNT,
-                    PARAMETER_CACHE_SIZE
+                    preferences.cacheSize() * 1024 * 1024
             );
         } catch (IOException e) {
             // Do Nothing.
         }
     }
 
-    public Observable<Boolean> clearImageCache() {
-        return Observable.create(subscriber -> {
-            try {
-                subscriber.onNext(clearImageCacheImpl());
-                subscriber.onCompleted();
-            } catch (Throwable e) {
-                subscriber.onError(e);
-            }
-        });
+    public boolean remove(String file) {
+        if (file.equals("journal") || file.startsWith("journal."))
+            return false;
+
+        try {
+            String key = file.substring(0, file.lastIndexOf("."));
+            return diskCache.remove(key);
+        } catch (IOException e) {
+            return false;
+        }
     }
 
-    private boolean clearImageCacheImpl() {
-        boolean isSuccessful = true;
+    public File getCacheDir() {
+        return diskCache.getDirectory();
+    }
 
-        File imageCacheDirectory = Glide.getPhotoCacheDir(mContext);
-        if (imageCacheDirectory.isDirectory()) {
-            for (File cachedFile : imageCacheDirectory.listFiles()) {
-                if (!cachedFile.delete()) {
-                    isSuccessful = false;
-                }
-            }
-        } else {
-            isSuccessful = false;
-        }
+    public long getRealSize() {
+        return DiskUtils.getDirectorySize(getCacheDir());
+    }
 
-        File urlCacheDirectory = getCacheDir();
-        if (urlCacheDirectory.isDirectory()) {
-            for (File cachedFile : urlCacheDirectory.listFiles()) {
-                if (!cachedFile.delete()) {
-                    isSuccessful = false;
-                }
-            }
-        } else {
-            isSuccessful = false;
-        }
+    public String getReadableSize() {
+        return Formatter.formatFileSize(context, getRealSize());
+    }
 
-        return isSuccessful;
+    public void setSize(int value) {
+        diskCache.setMaxSize(value * 1024 * 1024);
     }
 
     public Observable<List<Page>> getPageUrlsFromDiskCache(final String chapterUrl) {
@@ -107,10 +95,10 @@ public class CacheManager {
 
         try {
             String key = DiskUtils.hashKeyForDisk(chapterUrl);
-            snapshot = mDiskCache.get(key);
+            snapshot = diskCache.get(key);
 
             Type collectionType = new TypeToken<List<Page>>() {}.getType();
-            pages = mGson.fromJson(snapshot.getString(0), collectionType);
+            pages = gson.fromJson(snapshot.getString(0), collectionType);
         } catch (IOException e) {
             // Do Nothing.
         } finally {
@@ -122,13 +110,13 @@ public class CacheManager {
     }
 
     public void putPageUrlsToDiskCache(final String chapterUrl, final List<Page> pages) {
-        String cachedValue = mGson.toJson(pages);
+        String cachedValue = gson.toJson(pages);
 
         DiskLruCache.Editor editor = null;
         OutputStream outputStream = null;
         try {
             String key = DiskUtils.hashKeyForDisk(chapterUrl);
-            editor = mDiskCache.edit(key);
+            editor = diskCache.edit(key);
             if (editor == null) {
                 return;
             }
@@ -137,7 +125,7 @@ public class CacheManager {
             outputStream.write(cachedValue.getBytes());
             outputStream.flush();
 
-            mDiskCache.flush();
+            diskCache.flush();
             editor.commit();
         } catch (Exception e) {
             // Do Nothing.
@@ -155,13 +143,9 @@ public class CacheManager {
         }
     }
 
-    public File getCacheDir() {
-        return mDiskCache.getDirectory();
-    }
-
     public boolean isImageInCache(final String imageUrl) {
         try {
-            return mDiskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null;
+            return diskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null;
         } catch (IOException e) {
             e.printStackTrace();
         }
@@ -171,7 +155,7 @@ public class CacheManager {
     public String getImagePath(final String imageUrl) {
         try {
             String imageName = DiskUtils.hashKeyForDisk(imageUrl) + ".0";
-            File file = new File(mDiskCache.getDirectory(), imageName);
+            File file = new File(diskCache.getDirectory(), imageName);
             return file.getCanonicalPath();
         } catch (IOException e) {
             e.printStackTrace();
@@ -185,7 +169,7 @@ public class CacheManager {
 
         try {
             String key = DiskUtils.hashKeyForDisk(imageUrl);
-            editor = mDiskCache.edit(key);
+            editor = diskCache.edit(key);
             if (editor == null) {
                 throw new IOException("Unable to edit key");
             }
@@ -194,7 +178,7 @@ public class CacheManager {
             sink = Okio.buffer(Okio.sink(outputStream));
             sink.writeAll(response.body().source());
 
-            mDiskCache.flush();
+            diskCache.flush();
             editor.commit();
         } catch (Exception e) {
             throw new IOException("Unable to save image");

+ 4 - 0
app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java

@@ -40,6 +40,10 @@ public class PreferencesHelper {
         prefs.edit().clear().apply();
     }
 
+    public int cacheSize() {
+        return prefs.getInt(getKey(R.string.pref_chapter_cache_size_key), 75);
+    }
+
     public Preference<Boolean> lockOrientation() {
         return rxPrefs.getBoolean(getKey(R.string.pref_lock_orientation_key), true);
     }

+ 5 - 5
app/src/main/java/eu/kanade/mangafeed/injection/component/AppComponent.java

@@ -8,10 +8,12 @@ import dagger.Component;
 import eu.kanade.mangafeed.data.chaptersync.MyAnimeList;
 import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService;
 import eu.kanade.mangafeed.data.download.DownloadService;
+import eu.kanade.mangafeed.data.source.base.Source;
 import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
 import eu.kanade.mangafeed.injection.module.AppModule;
 import eu.kanade.mangafeed.injection.module.DataModule;
 import eu.kanade.mangafeed.ui.catalogue.CataloguePresenter;
+import eu.kanade.mangafeed.ui.catalogue.SourcePresenter;
 import eu.kanade.mangafeed.ui.download.DownloadPresenter;
 import eu.kanade.mangafeed.ui.library.LibraryPresenter;
 import eu.kanade.mangafeed.ui.manga.MangaActivity;
@@ -19,12 +21,10 @@ import eu.kanade.mangafeed.ui.manga.MangaPresenter;
 import eu.kanade.mangafeed.ui.manga.chapter.ChaptersPresenter;
 import eu.kanade.mangafeed.ui.manga.info.MangaInfoPresenter;
 import eu.kanade.mangafeed.ui.manga.myanimelist.MyAnimeListPresenter;
-import eu.kanade.mangafeed.ui.reader.ReaderPresenter;
-import eu.kanade.mangafeed.ui.catalogue.SourcePresenter;
-import eu.kanade.mangafeed.data.source.base.Source;
 import eu.kanade.mangafeed.ui.reader.ReaderActivity;
+import eu.kanade.mangafeed.ui.reader.ReaderPresenter;
 import eu.kanade.mangafeed.ui.setting.SettingsAccountsFragment;
-import eu.kanade.mangafeed.ui.setting.SettingsDownloadsFragment;
+import eu.kanade.mangafeed.ui.setting.SettingsActivity;
 
 @Singleton
 @Component(
@@ -48,7 +48,7 @@ public interface AppComponent {
     void inject(ReaderActivity readerActivity);
     void inject(MangaActivity mangaActivity);
     void inject(SettingsAccountsFragment settingsAccountsFragment);
-    void inject(SettingsDownloadsFragment settingsDownloadsFragment);
+    void inject(SettingsActivity settingsActivity);
 
     void inject(Source source);
 

+ 2 - 2
app/src/main/java/eu/kanade/mangafeed/injection/module/DataModule.java

@@ -35,8 +35,8 @@ public class DataModule {
 
     @Provides
     @Singleton
-    CacheManager provideCacheManager(Application app) {
-        return new CacheManager(app);
+    CacheManager provideCacheManager(Application app, PreferencesHelper preferences) {
+        return new CacheManager(app, preferences);
     }
 
     @Provides

+ 7 - 19
app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsAccountsFragment.java

@@ -2,7 +2,6 @@ package eu.kanade.mangafeed.ui.setting;
 
 import android.os.Bundle;
 import android.preference.PreferenceCategory;
-import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 
 import java.util.List;
@@ -10,33 +9,29 @@ import java.util.List;
 import javax.inject.Inject;
 
 import eu.kanade.mangafeed.App;
-import eu.kanade.mangafeed.R;
 import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
 import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
-import eu.kanade.mangafeed.data.preference.PreferencesHelper;
 import eu.kanade.mangafeed.data.source.SourceManager;
 import eu.kanade.mangafeed.data.source.base.Source;
-import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
-import eu.kanade.mangafeed.ui.setting.dialog.ChapterSyncLoginDialog;
-import eu.kanade.mangafeed.ui.setting.dialog.SourceLoginDialog;
+import eu.kanade.mangafeed.ui.setting.preference.ChapterSyncLoginDialog;
+import eu.kanade.mangafeed.ui.setting.preference.SourceLoginDialog;
 import rx.Observable;
 
-public class SettingsAccountsFragment extends PreferenceFragment {
+public class SettingsAccountsFragment extends SettingsNestedFragment {
 
-    @Inject PreferencesHelper preferences;
     @Inject SourceManager sourceManager;
     @Inject ChapterSyncManager syncManager;
 
-    public static SettingsAccountsFragment newInstance() {
-        return new SettingsAccountsFragment();
+    public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
+        SettingsNestedFragment fragment = new SettingsAccountsFragment();
+        fragment.setBundle(resourcePreference, resourceTitle);
+        return fragment;
     }
 
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         App.get(getActivity()).getComponent().inject(this);
 
-        addPreferencesFromResource(R.xml.pref_accounts);
-
         PreferenceScreen screen = getPreferenceScreen();
 
         List<Source> sourceAccounts = getSourcesWithLogin();
@@ -67,13 +62,6 @@ public class SettingsAccountsFragment extends PreferenceFragment {
 
     }
 
-    @Override
-    public void onResume() {
-        super.onResume();
-        ((BaseActivity)getActivity())
-                .setToolbarTitle(getString(R.string.pref_category_accounts));
-    }
-
     private List<Source> getSourcesWithLogin() {
         return Observable.from(sourceManager.getSources())
                 .filter(Source::isLoginRequired)

+ 52 - 0
app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsActivity.java

@@ -1,20 +1,30 @@
 package eu.kanade.mangafeed.ui.setting;
 
 import android.os.Bundle;
+import android.preference.PreferenceFragment;
 import android.support.v7.widget.Toolbar;
 
+import javax.inject.Inject;
+
 import butterknife.Bind;
 import butterknife.ButterKnife;
+import eu.kanade.mangafeed.App;
 import eu.kanade.mangafeed.R;
+import eu.kanade.mangafeed.data.cache.CacheManager;
+import eu.kanade.mangafeed.data.preference.PreferencesHelper;
 import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
 
 public class SettingsActivity extends BaseActivity {
 
+    @Inject PreferencesHelper preferences;
+    @Inject CacheManager cacheManager;
+
     @Bind(R.id.toolbar) Toolbar toolbar;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        App.get(getActivity()).getComponent().inject(this);
         setContentView(R.layout.activity_preferences);
         ButterKnife.bind(this);
 
@@ -31,4 +41,46 @@ public class SettingsActivity extends BaseActivity {
         if( !getFragmentManager().popBackStackImmediate() ) super.onBackPressed();
     }
 
+    public static class SettingsMainFragment extends PreferenceFragment {
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            addPreferencesFromResource(R.xml.pref_main);
+
+            registerSubpreference(R.string.pref_category_reader_key,
+                    SettingsNestedFragment.newInstance(
+                        R.xml.pref_reader, R.string.pref_category_reader));
+
+            registerSubpreference(R.string.pref_category_downloads_key,
+                    SettingsDownloadsFragment.newInstance(
+                        R.xml.pref_downloads, R.string.pref_category_downloads));
+
+            registerSubpreference(R.string.pref_category_accounts_key,
+                    SettingsAccountsFragment.newInstance(
+                        R.xml.pref_accounts, R.string.pref_category_accounts));
+
+            registerSubpreference(R.string.pref_category_cache_key,
+                    SettingsCacheFragment.newInstance(
+                            R.xml.pref_cache, R.string.pref_category_cache));
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+            ((BaseActivity) getActivity()).setToolbarTitle(getString(R.string.label_settings));
+        }
+
+        private void registerSubpreference(int preferenceResource, PreferenceFragment fragment) {
+            findPreference(getString(preferenceResource))
+                    .setOnPreferenceClickListener(preference -> {
+                        getFragmentManager().beginTransaction()
+                                .replace(R.id.settings_content, fragment)
+                                .addToBackStack(fragment.getClass().getSimpleName()).commit();
+                        return true;
+                    });
+        }
+
+    }
+
 }

+ 92 - 0
app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsCacheFragment.java

@@ -0,0 +1,92 @@
+package eu.kanade.mangafeed.ui.setting;
+
+import android.os.Bundle;
+import android.preference.Preference;
+
+import com.afollestad.materialdialogs.MaterialDialog;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import eu.kanade.mangafeed.R;
+import eu.kanade.mangafeed.data.cache.CacheManager;
+import eu.kanade.mangafeed.ui.setting.preference.IntListPreference;
+import eu.kanade.mangafeed.util.ToastUtil;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+public class SettingsCacheFragment extends SettingsNestedFragment implements Preference.OnPreferenceClickListener {
+
+    private CacheManager cacheManager;
+    private Preference clearCache;
+    private Subscription clearChapterCacheSubscription;
+
+    public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
+        SettingsNestedFragment fragment = new SettingsCacheFragment();
+        fragment.setBundle(resourcePreference, resourceTitle);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        cacheManager = getSettingsActivity().cacheManager;
+
+        IntListPreference cacheSize = (IntListPreference)findPreference(getString(R.string.pref_chapter_cache_size_key));
+        cacheSize.setOnPreferenceChangeListener(
+                (preference, newValue) -> {
+                    cacheManager.setSize(Integer.parseInt(newValue.toString()));
+                    return true;
+                });
+
+        clearCache = findPreference(getString(R.string.pref_clear_chapter_cache_key));
+        clearCache.setOnPreferenceClickListener(this);
+        clearCache.setSummary(getString(R.string.used_cache, cacheManager.getReadableSize()));
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        if (preference.equals(clearCache)) {
+            clearChapterCache();
+        }
+        return true;
+    }
+
+    private void clearChapterCache() {
+        final AtomicInteger deletedFiles = new AtomicInteger();
+
+        File[] files = cacheManager.getCacheDir().listFiles();
+
+        MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
+                .title(R.string.deleting_files)
+                .progress(false, files.length, true)
+                .cancelable(false)
+                .dismissListener(d -> {
+                    if (clearChapterCacheSubscription != null && !clearChapterCacheSubscription.isUnsubscribed())
+                        clearChapterCacheSubscription.unsubscribe();
+                })
+                .show();
+
+        clearChapterCacheSubscription = Observable.defer(() -> Observable.from(files))
+                .concatMap(file -> {
+                    if (cacheManager.remove(file.getName())) {
+                        deletedFiles.incrementAndGet();
+                    }
+                    return Observable.just(file);
+                })
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(file -> dialog.incrementProgress(1),
+                        error -> {
+                            dialog.dismiss();
+                            ToastUtil.showShort(getActivity(), getString(R.string.cache_delete_error));
+                        }, () -> {
+                            dialog.dismiss();
+                            ToastUtil.showShort(getActivity(), getString(R.string.cache_deleted, deletedFiles.get()));
+                            clearCache.setSummary(getString(R.string.used_cache, cacheManager.getReadableSize()));
+                        });
+    }
+
+}

+ 5 - 21
app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsDownloadsFragment.java

@@ -2,30 +2,21 @@ package eu.kanade.mangafeed.ui.setting;
 
 import android.os.Bundle;
 import android.preference.ListPreference;
-import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 
-import javax.inject.Inject;
-
-import eu.kanade.mangafeed.App;
 import eu.kanade.mangafeed.R;
-import eu.kanade.mangafeed.data.preference.PreferencesHelper;
-import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
 import eu.kanade.mangafeed.util.DiskUtils;
 
-public class SettingsDownloadsFragment extends PreferenceFragment {
-
-    @Inject PreferencesHelper preferences;
+public class SettingsDownloadsFragment extends SettingsNestedFragment {
 
-    public static SettingsDownloadsFragment newInstance() {
-        return new SettingsDownloadsFragment();
+    public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
+        SettingsNestedFragment fragment = new SettingsDownloadsFragment();
+        fragment.setBundle(resourcePreference, resourceTitle);
+        return fragment;
     }
 
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        App.get(getActivity()).getComponent().inject(this);
-
-        addPreferencesFromResource(R.xml.pref_downloads);
 
         PreferenceScreen screen = getPreferenceScreen();
 
@@ -46,11 +37,4 @@ public class SettingsDownloadsFragment extends PreferenceFragment {
         screen.addPreference(directoriesPref);
     }
 
-    @Override
-    public void onResume() {
-        super.onResume();
-        ((BaseActivity)getActivity())
-                .setToolbarTitle(getString(R.string.pref_category_downloads));
-    }
-
 }

+ 0 - 44
app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsMainFragment.java

@@ -1,44 +0,0 @@
-package eu.kanade.mangafeed.ui.setting;
-
-import android.os.Bundle;
-import android.preference.PreferenceFragment;
-
-import eu.kanade.mangafeed.R;
-import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
-
-public class SettingsMainFragment extends PreferenceFragment {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        addPreferencesFromResource(R.xml.pref_main);
-
-        registerSubpreference(R.string.pref_category_reader_key,
-                SettingsNestedFragment.newInstance(
-                        R.xml.pref_reader, R.string.pref_category_reader));
-
-        registerSubpreference(R.string.pref_category_downloads_key,
-                SettingsDownloadsFragment.newInstance());
-
-        registerSubpreference(R.string.pref_category_accounts_key,
-                SettingsAccountsFragment.newInstance());
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        ((BaseActivity)getActivity())
-                .setToolbarTitle(getString(R.string.label_settings));
-    }
-
-    private void registerSubpreference(int preferenceResource, PreferenceFragment fragment) {
-        findPreference(getString(preferenceResource))
-                .setOnPreferenceClickListener(preference -> {
-                    getFragmentManager().beginTransaction()
-                            .replace(R.id.settings_content, fragment)
-                            .addToBackStack(fragment.getClass().getSimpleName()).commit();
-                    return true;
-                });
-    }
-
-}

+ 17 - 6
app/src/main/java/eu/kanade/mangafeed/ui/setting/SettingsNestedFragment.java

@@ -3,34 +3,45 @@ package eu.kanade.mangafeed.ui.setting;
 import android.os.Bundle;
 import android.preference.PreferenceFragment;
 
+import eu.kanade.mangafeed.data.preference.PreferencesHelper;
 import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
 
 public class SettingsNestedFragment extends PreferenceFragment {
 
+    protected PreferencesHelper preferences;
+
     private static final String RESOURCE_FILE = "resource_file";
     private static final String TOOLBAR_TITLE = "toolbar_title";
 
     public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
         SettingsNestedFragment fragment = new SettingsNestedFragment();
-        Bundle args = new Bundle();
-        args.putInt(RESOURCE_FILE, resourcePreference);
-        args.putInt(TOOLBAR_TITLE, resourceTitle);
-        fragment.setArguments(args);
+        fragment.setBundle(resourcePreference, resourceTitle);
         return fragment;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        preferences = getSettingsActivity().preferences;
         addPreferencesFromResource(getArguments().getInt(RESOURCE_FILE));
-
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        ((BaseActivity)getActivity())
+        ((BaseActivity) getActivity())
                 .setToolbarTitle(getString(getArguments().getInt(TOOLBAR_TITLE)));
     }
 
+    public void setBundle(int resourcePreference, int resourceTitle) {
+        Bundle args = new Bundle();
+        args.putInt(RESOURCE_FILE, resourcePreference);
+        args.putInt(TOOLBAR_TITLE, resourceTitle);
+        setArguments(args);
+    }
+
+    public SettingsActivity getSettingsActivity() {
+        return (SettingsActivity) getActivity();
+    }
+
 }

+ 1 - 1
app/src/main/java/eu/kanade/mangafeed/ui/setting/dialog/ChapterSyncLoginDialog.java → app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/ChapterSyncLoginDialog.java

@@ -1,4 +1,4 @@
-package eu.kanade.mangafeed.ui.setting.dialog;
+package eu.kanade.mangafeed.ui.setting.preference;
 
 import android.content.Context;
 import android.content.DialogInterface;

+ 35 - 0
app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/IntListPreference.java

@@ -0,0 +1,35 @@
+package eu.kanade.mangafeed.ui.setting.preference;
+
+import android.content.Context;
+import android.preference.ListPreference;
+import android.util.AttributeSet;
+
+public class IntListPreference extends ListPreference
+{
+    public IntListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public IntListPreference(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected boolean persistString(String value) {
+        if(value == null) {
+            return false;
+        } else {
+            return persistInt(Integer.valueOf(value));
+        }
+    }
+
+    @Override
+    protected String getPersistedString(String defaultReturnValue) {
+        if(getSharedPreferences().contains(getKey())) {
+            int intValue = getPersistedInt(0);
+            return String.valueOf(intValue);
+        } else {
+            return defaultReturnValue;
+        }
+    }
+}

+ 1 - 1
app/src/main/java/eu/kanade/mangafeed/ui/setting/dialog/LoginDialogPreference.java → app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/LoginDialogPreference.java

@@ -1,4 +1,4 @@
-package eu.kanade.mangafeed.ui.setting.dialog;
+package eu.kanade.mangafeed.ui.setting.preference;
 
 import android.app.AlertDialog;
 import android.content.Context;

+ 1 - 1
app/src/main/java/eu/kanade/mangafeed/ui/setting/dialog/SourceLoginDialog.java → app/src/main/java/eu/kanade/mangafeed/ui/setting/preference/SourceLoginDialog.java

@@ -1,4 +1,4 @@
-package eu.kanade.mangafeed.ui.setting.dialog;
+package eu.kanade.mangafeed.ui.setting.preference;
 
 import android.content.Context;
 import android.content.DialogInterface;

+ 13 - 0
app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java

@@ -158,5 +158,18 @@ public final class DiskUtils {
         }
 
     }
+
+    public static long getDirectorySize(File f) {
+        long size = 0;
+        if (f.isDirectory()) {
+            for (File file : f.listFiles()) {
+                size += getDirectorySize(file);
+            }
+        } else {
+            size=f.length();
+        }
+        return size;
+    }
+
 }
 

+ 12 - 0
app/src/main/res/values/arrays.xml

@@ -27,4 +27,16 @@
         <item>2</item>
         <item>3</item>
     </string-array>
+
+    <string-array name="cache_size">
+        <item>50 MB</item>
+        <item>75 MB</item>
+        <item>100 MB</item>
+    </string-array>
+
+    <string-array name="cache_values">
+        <item>50</item>
+        <item>75</item>
+        <item>100</item>
+    </string-array>
 </resources>

+ 4 - 0
app/src/main/res/values/keys.xml

@@ -3,6 +3,7 @@
     <string name="pref_category_reader_key">pref_category_reader_key</string>
     <string name="pref_category_accounts_key">pref_category_accounts_key</string>
     <string name="pref_category_downloads_key">pref_category_downloads_key</string>
+    <string name="pref_category_cache_key">pref_category_cache_key</string>
 
     <string name="pref_default_viewer_key">pref_default_viewer_key</string>
     <string name="pref_hide_status_bar_key">pref_hide_status_bar_key</string>
@@ -15,4 +16,7 @@
 
     <string name="pref_download_directory_key">pref_download_directory_key</string>
     <string name="pref_download_threads_key">pref_download_threads_key</string>
+
+    <string name="pref_chapter_cache_size_key">pref_chapter_cache_size_key</string>
+    <string name="pref_clear_chapter_cache_key">pref_clear_chapter_cache_key</string>
 </resources>

+ 12 - 2
app/src/main/res/values/strings.xml

@@ -29,12 +29,16 @@
     <string name="button_ok">OK</string>
     <string name="button_cancel">Cancel</string>
 
+    <!-- Operations -->
+    <string name="deleting_files">Deleting files…</string>
+    <string name="loading">Loading…</string>
 
     <!-- Preferences -->
       <!-- Subsections -->
     <string name="pref_category_reader">Reader</string>
     <string name="pref_category_accounts">Accounts</string>
     <string name="pref_category_downloads">Downloads</string>
+    <string name="pref_category_cache">Cache</string>
 
       <!-- Reader section -->
     <string name="pref_hide_status_bar">Hide status bar</string>
@@ -53,16 +57,22 @@
     <string name="pref_download_directory">Downloads directory</string>
     <string name="pref_download_threads">Download threads</string>
 
+      <!-- Cache section -->
+    <string name="pref_chapter_cache_size">Chapters cache size</string>
+    <string name="pref_clear_chapter_cache">Clear chapter cache</string>
+    <string name="used_cache">Used: %1$s</string>
+    <string name="cache_deleted">Cache cleared. %1$d files have been deleted</string>
+    <string name="cache_delete_error">An error occurred clearing cache</string>
+
+
     <!-- Login dialog -->
     <string name="accounts_login_title">Login for %1$s</string>
     <string name="username">Username</string>
     <string name="password">Password</string>
     <string name="show_password">Show password</string>
-    <string name="check_credentials">Check credentials</string>
     <string name="login">Login</string>
     <string name="login_success">Login successful</string>
     <string name="invalid_login">Login error</string>
-    <string name="loading">Loading…</string>
     <string name="unknown_error">Unknown error</string>
 
     <!-- Library fragment -->

+ 16 - 0
app/src/main/res/xml/pref_cache.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <eu.kanade.mangafeed.ui.setting.preference.IntListPreference
+        android:title="@string/pref_chapter_cache_size"
+        android:key="@string/pref_chapter_cache_size_key"
+        android:entries="@array/cache_size"
+        android:entryValues="@array/cache_values"
+        android:summary="%s"
+        android:defaultValue="75"/>
+
+    <Preference
+        android:title="@string/pref_clear_chapter_cache"
+        android:key="@string/pref_clear_chapter_cache_key" />
+
+</PreferenceScreen>

+ 5 - 0
app/src/main/res/xml/pref_main.xml

@@ -16,4 +16,9 @@
         android:persistent="false"
         android:title="@string/pref_category_accounts" />
 
+    <Preference
+        android:key="@string/pref_category_cache_key"
+        android:persistent="false"
+        android:title="@string/pref_category_cache" />
+
 </PreferenceScreen>

+ 1 - 0
build.gradle

@@ -20,5 +20,6 @@ allprojects {
         jcenter()
         maven { url "https://clojars.org/repo/" }
         maven { url "http://dl.bintray.com/davideas/maven" }
+        maven { url "https://jitpack.io" }
     }
 }