diff --git a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java index 0a7f1b6e..baef9cf5 100644 --- a/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/BaseActivity.java @@ -95,6 +95,14 @@ public abstract class BaseActivity extends AppCompatActivity { tinyDb.putString("crashReportingEnabledInit", "yes"); } + // default cache setter + if(tinyDb.getString("cacheSizeStr").isEmpty()) { + tinyDb.putString("cacheSizeStr", getResources().getString(R.string.cacheSizeDataSelectionSelectedText)); + } + if(tinyDb.getString("cacheSizeImagesStr").isEmpty()) { + tinyDb.putString("cacheSizeImagesStr", getResources().getString(R.string.cacheSizeImagesSelectionSelectedText)); + } + if (tinyDb.getBoolean("crashReportingEnabled")) { CoreConfigurationBuilder ACRABuilder = new CoreConfigurationBuilder(this); diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java index 1dff9548..71ca613a 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java @@ -3,13 +3,22 @@ package org.mian.gitnex.activities; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.appcompat.app.AlertDialog; +import org.apache.commons.io.FileUtils; import org.mian.gitnex.R; +import org.mian.gitnex.helpers.FilesData; +import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.ssl.MemorizingTrustManager; +import org.mian.gitnex.util.AppUtil; import org.mian.gitnex.util.TinyDB; +import java.io.File; +import java.io.IOException; +import java.util.HashSet; /** * Author M M Arif @@ -20,6 +29,12 @@ public class SettingsSecurityActivity extends BaseActivity { private Context appCtx; private View.OnClickListener onClickListener; + private static String[] cacheSizeDataList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"}; + private static int cacheSizeDataSelectedChoice = 0; + + private static String[] cacheSizeImagesList = {"50 MB", "100 MB", "250 MB", "500 MB", "1 GB"}; + private static int cacheSizeImagesSelectedChoice = 0; + @Override protected int getLayoutResourceId() { @@ -39,7 +54,127 @@ public class SettingsSecurityActivity extends BaseActivity { initCloseListener(); closeActivity.setOnClickListener(onClickListener); + TextView cacheSizeDataSelected = findViewById(R.id.cacheSizeDataSelected); // setter for data cache size + TextView cacheSizeImagesSelected = findViewById(R.id.cacheSizeImagesSelected); // setter for images cache size + TextView clearCacheSelected = findViewById(R.id.clearCacheSelected); // setter for clear cache + LinearLayout certsFrame = findViewById(R.id.certsFrame); + LinearLayout cacheSizeDataFrame = findViewById(R.id.cacheSizeDataSelectionFrame); + LinearLayout cacheSizeImagesFrame = findViewById(R.id.cacheSizeImagesSelectionFrame); + LinearLayout clearCacheFrame = findViewById(R.id.clearCacheSelectionFrame); + + if(!tinyDb.getString("cacheSizeStr").isEmpty()) { + cacheSizeDataSelected.setText(tinyDb.getString("cacheSizeStr")); + } + + if(!tinyDb.getString("cacheSizeImagesStr").isEmpty()) { + cacheSizeImagesSelected.setText(tinyDb.getString("cacheSizeImagesStr")); + } + + if(cacheSizeDataSelectedChoice == 0) { + cacheSizeDataSelectedChoice = tinyDb.getInt("cacheSizeId"); + } + + if(cacheSizeImagesSelectedChoice == 0) { + cacheSizeImagesSelectedChoice = tinyDb.getInt("cacheSizeImagesId"); + } + + // clear cache setter + File cacheDir = appCtx.getCacheDir(); + long size__ = FilesData.getFileSizeRecursively(new HashSet<>(), cacheDir); + if(size__ > 0) { + clearCacheSelected.setText(String.valueOf(AppUtil.formatFileSizeInDetail(size__))); + } + + // clear cache + clearCacheFrame.setOnClickListener(v1 -> { + + AlertDialog.Builder builder = new AlertDialog.Builder(SettingsSecurityActivity.this); + + builder.setTitle(getResources().getString(R.string.clearCacheDialogHeader)); + builder.setMessage(getResources().getString(R.string.clearCacheDialogMessage)); + builder.setPositiveButton(R.string.menuDeleteText, (dialog, which) -> { + + try { + + FileUtils.deleteDirectory(cacheDir); + FileUtils.mkdir(cacheDir.getAbsolutePath()); + this.recreate(); + this.overridePendingTransition(0, 0); + + } + catch (IOException e) { + + Log.e("SettingsSecurity", e.toString()); + + } + + }); + + builder.setNeutralButton(R.string.cancelButton, (dialog, which) -> dialog.dismiss()); + builder.create().show(); + + }); + + // cache size images selection dialog + cacheSizeImagesFrame.setOnClickListener(view -> { + + AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this); + + tsBuilder.setTitle(getResources().getString(R.string.cacheSizeImagesDialogHeader)); + if(cacheSizeImagesSelectedChoice != -1) { + tsBuilder.setCancelable(true); + } + else { + tsBuilder.setCancelable(false); + } + + tsBuilder.setSingleChoiceItems(cacheSizeImagesList, cacheSizeImagesSelectedChoice, (dialogInterfaceTheme, i) -> { + + cacheSizeImagesSelectedChoice = i; + cacheSizeImagesSelected.setText(cacheSizeImagesList[i]); + tinyDb.putString("cacheSizeImagesStr", cacheSizeImagesList[i]); + tinyDb.putInt("cacheSizeImagesId", i); + + dialogInterfaceTheme.dismiss(); + Toasty.info(appCtx, getResources().getString(R.string.settingsSave)); + + }); + + AlertDialog cfDialog = tsBuilder.create(); + cfDialog.show(); + + }); + + // cache size data selection dialog + cacheSizeDataFrame.setOnClickListener(view -> { + + AlertDialog.Builder tsBuilder = new AlertDialog.Builder(SettingsSecurityActivity.this); + + tsBuilder.setTitle(getResources().getString(R.string.cacheSizeDataDialogHeader)); + if(cacheSizeDataSelectedChoice != -1) { + tsBuilder.setCancelable(true); + } + else { + tsBuilder.setCancelable(false); + } + + tsBuilder.setSingleChoiceItems(cacheSizeDataList, cacheSizeDataSelectedChoice, (dialogInterfaceTheme, i) -> { + + cacheSizeDataSelectedChoice = i; + cacheSizeDataSelected.setText(cacheSizeDataList[i]); + tinyDb.putString("cacheSizeStr", cacheSizeDataList[i]); + tinyDb.putInt("cacheSizeId", i); + + dialogInterfaceTheme.dismiss(); + Toasty.info(appCtx, getResources().getString(R.string.settingsSave)); + + }); + + AlertDialog cfDialog = tsBuilder.create(); + cfDialog.show(); + + }); // certs deletion certsFrame.setOnClickListener(v1 -> { diff --git a/app/src/main/java/org/mian/gitnex/clients/AppApiService.java b/app/src/main/java/org/mian/gitnex/clients/AppApiService.java index b36b181d..35b467b9 100644 --- a/app/src/main/java/org/mian/gitnex/clients/AppApiService.java +++ b/app/src/main/java/org/mian/gitnex/clients/AppApiService.java @@ -2,8 +2,10 @@ package org.mian.gitnex.clients; import android.content.Context; import android.util.Log; +import org.mian.gitnex.helpers.FilesData; import org.mian.gitnex.helpers.ssl.MemorizingTrustManager; import org.mian.gitnex.util.AppUtil; +import org.mian.gitnex.util.TinyDB; import java.io.File; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; @@ -24,9 +26,10 @@ public class AppApiService { public static S createService(Class serviceClass, String instanceURL, Context ctx) { + TinyDB tinyDb = new TinyDB(ctx); final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); - int cacheSize = 50 * 1024 * 1024; // 50MB + int cacheSize = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeStr")) * 1024 * 1024; Cache cache = new Cache(httpCacheDirectory, cacheSize); HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); diff --git a/app/src/main/java/org/mian/gitnex/clients/PicassoService.java b/app/src/main/java/org/mian/gitnex/clients/PicassoService.java index 9ad334e6..c79d9f03 100644 --- a/app/src/main/java/org/mian/gitnex/clients/PicassoService.java +++ b/app/src/main/java/org/mian/gitnex/clients/PicassoService.java @@ -49,7 +49,7 @@ public class PicassoService { //noinspection ResultOfMethodCallIgnored cachePath.mkdirs(); - picasso = builder.memoryCache(new PicassoCache(cachePath)).build(); + picasso = builder.memoryCache(new PicassoCache(cachePath, context)).build(); } catch(Exception e) { diff --git a/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java b/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java index ec0e235b..83ed2ef8 100644 --- a/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java +++ b/app/src/main/java/org/mian/gitnex/clients/RetrofitClient.java @@ -2,10 +2,12 @@ package org.mian.gitnex.clients; import android.content.Context; import android.util.Log; +import org.mian.gitnex.helpers.FilesData; import org.mian.gitnex.helpers.ssl.MemorizingTrustManager; import org.mian.gitnex.interfaces.ApiInterface; import org.mian.gitnex.interfaces.WebInterface; import org.mian.gitnex.util.AppUtil; +import org.mian.gitnex.util.TinyDB; import java.io.File; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; @@ -29,8 +31,9 @@ public class RetrofitClient { private RetrofitClient(String instanceUrl, Context ctx) { + TinyDB tinyDb = new TinyDB(ctx); final boolean connToInternet = AppUtil.haveNetworkConnection(ctx); - int cacheSize = 50 * 1024 * 1024; // 50MB + int cacheSize = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeStr")) * 1024 * 1024; File httpCacheDirectory = new File(ctx.getCacheDir(), "responses"); Cache cache = new Cache(httpCacheDirectory, cacheSize); diff --git a/app/src/main/java/org/mian/gitnex/helpers/FilesData.java b/app/src/main/java/org/mian/gitnex/helpers/FilesData.java new file mode 100644 index 00000000..1278bb94 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/helpers/FilesData.java @@ -0,0 +1,84 @@ +package org.mian.gitnex.helpers; + +import java.io.File; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * Author M M Arif + */ + +public class FilesData { + + public static int returnOnlyNumber(String fileSize) { + + return Integer.parseInt(fileSize.substring(0, fileSize.indexOf(" "))); + + } + + public static long getFileSizeRecursively(Set alreadySeen, File dirDirectory) { + + long fileSize = 0; + + for (File filItem : Objects.requireNonNull(dirDirectory.listFiles())) { + + if (filItem.isDirectory()) { + + fileSize += getFileSize(filItem); + + } + else { + + alreadySeen.add(new File(filItem.getName())); + fileSize += filItem.length(); + + } + + } + + return fileSize; + + } + + private static long getFileSize(File subDirectory) { + + long fileSize = 0; + + Deque unprocessedDirs = new ArrayDeque<>(); + unprocessedDirs.add(subDirectory); + Set alreadySeen = new HashSet<>(); + + while (!unprocessedDirs.isEmpty()) { + + File dir = unprocessedDirs.removeFirst(); + + for (File filItem : Objects.requireNonNull(dir.listFiles())) { + + if (filItem.isDirectory()) { + + unprocessedDirs.addFirst(filItem); + + } + else { + + if (! alreadySeen.contains(filItem.getName())) { + + alreadySeen.add(new File(filItem.getName())); + fileSize += filItem.length(); + + } + + } + + } + + } + + return fileSize; + + } + +} diff --git a/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java b/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java index 0fd5ef26..bce0e3cb 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java +++ b/app/src/main/java/org/mian/gitnex/helpers/PicassoCache.java @@ -1,9 +1,11 @@ package org.mian.gitnex.helpers; +import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import com.squareup.picasso.Cache; +import org.mian.gitnex.util.TinyDB; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -20,21 +22,26 @@ import java.util.UUID; public class PicassoCache implements Cache { + private Context ctx; private String TAG = "PicassoCache"; private static final Bitmap.CompressFormat COMPRESS_FORMAT = Bitmap.CompressFormat.PNG; - private static final int COMPRESSION_QUALITY = 0; // 0 = high compression (low file size) | 100 = no compression + private static final int COMPRESSION_QUALITY = 50; // 0 = high compression (low file size) | 100 = no compression + private final int CACHE_SIZE; private static final String CACHE_MAP_FILE = "cacheMap"; - private static final int CACHE_SIZE = 25 * 1024 * 1024; // Cache can hold twenty-five megabytes private File cachePath; private HashMap cacheMap; - public PicassoCache(File cachePath) throws IOException, ClassNotFoundException { + public PicassoCache(File cachePath, Context ctx) throws IOException, ClassNotFoundException { + TinyDB tinyDb = new TinyDB(ctx); + + CACHE_SIZE = FilesData.returnOnlyNumber(tinyDb.getString("cacheSizeImagesStr")) * 1024 * 1024; this.cachePath = cachePath; cacheMap = new HashMap<>(); + this.ctx = ctx; if(cacheMapExists(cachePath)) { diff --git a/app/src/main/res/layout/activity_settings_security.xml b/app/src/main/res/layout/activity_settings_security.xml index 9a71bc35..aa4a938f 100644 --- a/app/src/main/res/layout/activity_settings_security.xml +++ b/app/src/main/res/layout/activity_settings_security.xml @@ -66,4 +66,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_files.xml b/app/src/main/res/layout/fragment_files.xml index 6bbd1e04..dce8d9cd 100644 --- a/app/src/main/res/layout/fragment_files.xml +++ b/app/src/main/res/layout/fragment_files.xml @@ -54,8 +54,8 @@ android:id="@+id/progress_bar" style="@style/Base.Widget.AppCompat.ProgressBar" android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center" + android:layout_height="wrap_content" + android:layout_centerInParent="true" android:indeterminate="true" android:visibility="gone" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 587bb6e9..9205a06d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -288,6 +288,16 @@ Source Code Theme Sublime Select Source Code Theme + Data Cache Size + Data Cache Size + 50 MB + Images Cache Size + Images Cache Size + 50 MB + Clear Cache + 0 B + Clear Cache? + This will delete all the cache data including files and images.\n\nProceed with deletion? No more data available @@ -635,7 +645,7 @@ Themes, fonts, badges, code block theme PDF mode, source code theme - SSL certificates + SSL certificates, cache Languages Crash reports