diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 62a2e14..f6dbe7c 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -29,8 +29,8 @@ diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index b914f54..349c0a1 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index 81693f1..d5fda8b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "ca.pkay.rcloneexplorer" minSdkVersion 21 targetSdkVersion 27 - versionCode 10 - versionName "1.2.1" + versionCode 11 + versionName "1.2.2" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/src/main/assets/changelog.md b/app/src/main/assets/changelog.md index 0da0e2e..6ea286b 100644 --- a/app/src/main/assets/changelog.md +++ b/app/src/main/assets/changelog.md @@ -1,3 +1,11 @@ +### 1.2.2 +* **Update:** Rclone to version 1.41 +* **New:** App shortcuts +* **Fix:** Color picker not working on sdk 21 +* **Fix:** Rclone not getting updated + +*** + ### 1.2.1 * **New:** Dark theme! * **Fix:** Crash when starting app for the first time diff --git a/app/src/main/assets/rclone-arm32 b/app/src/main/assets/rclone-arm32 index 5b2abb3..c8ac16c 100644 Binary files a/app/src/main/assets/rclone-arm32 and b/app/src/main/assets/rclone-arm32 differ diff --git a/app/src/main/assets/rclone-arm64 b/app/src/main/assets/rclone-arm64 index cb3c3fc..6e84659 100644 Binary files a/app/src/main/assets/rclone-arm64 and b/app/src/main/assets/rclone-arm64 differ diff --git a/app/src/main/assets/rclone-x86_32 b/app/src/main/assets/rclone-x86_32 index be3bfa5..92b46ee 100644 Binary files a/app/src/main/assets/rclone-x86_32 and b/app/src/main/assets/rclone-x86_32 differ diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ColorPickerDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ColorPickerDialog.java index 9d85dfb..0493733 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ColorPickerDialog.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/ColorPickerDialog.java @@ -3,6 +3,7 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.content.res.ColorStateList; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; @@ -11,6 +12,7 @@ import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; +import android.widget.ImageView; import android.widget.LinearLayout; import ca.pkay.rcloneexplorer.R; @@ -70,8 +72,8 @@ private void createLayout(View view) { int i = 0; for (final int color : colorChoices) { View item = layoutInflater.inflate(R.layout.color_picker_item, null); - View colorOption = item.findViewById(R.id.color_option); - colorOption.getBackground().setTint(color); + ImageView colorOption = item.findViewById(R.id.color_option); + colorOption.setColorFilter(color); if (color == defaultColor) { (item.findViewById(R.id.checkmark)).setVisibility(View.VISIBLE); @@ -104,10 +106,10 @@ public void onClick(View v) { while (i < 5) { // add dummy items so that layout is even View item = layoutInflater.inflate(R.layout.color_picker_item, null); - View colorOption = item.findViewById(R.id.color_option); + ImageView colorOption = item.findViewById(R.id.color_option); TypedValue typedValue = new TypedValue(); context.getTheme().resolveAttribute(R.attr.cardColor, typedValue, true); - colorOption.getBackground().setTint(typedValue.data); + colorOption.setColorFilter(typedValue.data); rowLayout.addView(item); i++; } diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java index 21fbd01..24490ce 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java @@ -128,7 +128,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { setHasOptionsMenu(true); SharedPreferences sharedPreferences = context.getSharedPreferences(MainActivity.SHARED_PREFS_TAG, Context.MODE_PRIVATE); - sortOrder = sharedPreferences.getInt(SHARED_PREFS_SORT_ORDER, -1); + sortOrder = sharedPreferences.getInt(SHARED_PREFS_SORT_ORDER, SortDialog.ALPHA_ASCENDING); //networkStateReceiver = ((MainActivity)context).getNetworkStateReceiver(); rclone = new Rclone(getContext()); @@ -440,7 +440,9 @@ private void showSortMenu() { .setListener(new SortDialog.OnClickListener() { @Override public void onPositiveButtonClick(int sortById, int sortOrderId) { - sortSelected(sortById, sortOrderId); + if (directoryContent != null && !directoryContent.isEmpty()) { + sortSelected(sortById, sortOrderId); + } } }) .setSortOrder(sortOrder) @@ -590,6 +592,7 @@ public void onDirectoryClicked(FileItem fileItem) { } path = fileItem.getPath(); recyclerViewAdapter.clear(); + directoryContent.clear(); fetchDirectoryTask = new FetchDirectoryContent().execute(); } diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java b/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java index 15656ae..85ca4ba 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java @@ -10,8 +10,11 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.drawable.Icon; import android.net.ConnectivityManager; import android.net.Uri; import android.os.AsyncTask; @@ -37,6 +40,9 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import ca.pkay.rcloneexplorer.BroadcastReceivers.NetworkStateReceiver; import ca.pkay.rcloneexplorer.Dialogs.InputDialog; @@ -54,6 +60,8 @@ public class MainActivity extends AppCompatActivity private static final int READ_REQUEST_CODE = 42; // code when opening rclone config file private static final int REQUEST_PERMISSION_CODE = 62; // code when requesting permissions private static final int SETTINGS_CODE = 71; // code when coming back from settings + private final String APP_SHORTCUT_REMOTE_NAME = "arg_remote_name"; + private final String APP_SHORTCUT_REMOTE_TYPE = "arg_remote_type"; private NavigationView navigationView; private Rclone rclone; private Fragment fragment; @@ -94,10 +102,26 @@ public void onClick(View v) { } }); + Intent intent = getIntent(); + Bundle bundle = intent.getExtras(); + + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + int lastVersionCode = sharedPreferences.getInt(getString(R.string.pref_key_version_code), -1); + int currentVersionCode = BuildConfig.VERSION_CODE; + if (!rclone.isRcloneBinaryCreated()) { new CreateRcloneBinary().execute(); + } else if (lastVersionCode < currentVersionCode) { + new CreateRcloneBinary().execute(); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putInt(getString(R.string.pref_key_version_code), currentVersionCode); + editor.apply(); } else if (rclone.isConfigEncrypted()) { askForConfigPassword(); + } else if (bundle != null && bundle.containsKey(APP_SHORTCUT_REMOTE_NAME) && bundle.containsKey(APP_SHORTCUT_REMOTE_TYPE)) { + String remoteName = bundle.getString(APP_SHORTCUT_REMOTE_NAME); + String remoteType = bundle.getString(APP_SHORTCUT_REMOTE_TYPE); + startRemote(remoteName, remoteType); } else { startRemotesFragment(); } @@ -269,14 +293,129 @@ public void requestPermissions() { } } + private void addRemotesToShortcutList() { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N_MR1) { + return; + } + ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); + if (shortcutManager == null) { + return; + } + shortcutManager.removeAllDynamicShortcuts(); + + List remoteItemList = rclone.getRemotes(); + List shortcutInfoList = new ArrayList<>(); + + for (RemoteItem remoteItem : remoteItemList) { + String id = remoteItem.getName().replaceAll(" ", "_"); + + Intent intent = new Intent(Intent.ACTION_MAIN, Uri.EMPTY, this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + intent.putExtra(APP_SHORTCUT_REMOTE_NAME, remoteItem.getName()); + intent.putExtra(APP_SHORTCUT_REMOTE_TYPE, remoteItem.getType()); + + ShortcutInfo shortcut = new ShortcutInfo.Builder(this, id) + .setShortLabel(remoteItem.getName()) + .setIcon(Icon.createWithResource(context, getRemoteIcon(remoteItem.getType()))) + .setIntent(intent) + .build(); + shortcutInfoList.add(shortcut); + if (shortcutInfoList.size() == 4) { + break; + } + } + shortcutManager.setDynamicShortcuts(shortcutInfoList); + } + + private void addRemoteToShortcutList(RemoteItem remoteItem) { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N_MR1) { + return; + } + ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); + if (shortcutManager == null) { + return; + } + + String id = remoteItem.getName().replaceAll(" ", "_"); + + List shortcutInfoList = shortcutManager.getDynamicShortcuts(); + for (ShortcutInfo shortcutInfo : shortcutInfoList) { + if (shortcutInfo.getId().equals(id)) { + shortcutManager.reportShortcutUsed(id); + return; + } + } + + Intent intent = new Intent(Intent.ACTION_MAIN, Uri.EMPTY, this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + intent.putExtra(APP_SHORTCUT_REMOTE_NAME, remoteItem.getName()); + intent.putExtra(APP_SHORTCUT_REMOTE_TYPE, remoteItem.getType()); + + ShortcutInfo shortcut = new ShortcutInfo.Builder(this, id) + .setShortLabel(remoteItem.getName()) + .setIcon(Icon.createWithResource(context, getRemoteIcon(remoteItem.getType()))) + .setIntent(intent) + .build(); + + if (shortcutInfoList.size() >= 4) { + ShortcutInfo removeId = shortcutInfoList.get(0); + shortcutManager.removeDynamicShortcuts(Collections.singletonList(removeId.getId())); + } + shortcutManager.addDynamicShortcuts(Collections.singletonList(shortcut)); + shortcutManager.reportShortcutUsed(id); + } + + private int getRemoteIcon(String remoteType) { + switch (remoteType) { + case "crypt": + return R.drawable.ic_lock_black; + case "amazon cloud drive": + return R.drawable.ic_amazon; + case "b2": + return R.drawable.ic_b2; + case "drive": + return R.drawable.ic_google_drive; + case "dropbox": + return R.drawable.ic_dropbox; + case "google cloud storage": + return R.drawable.ic_google; + case "onedrive": + return R.drawable.ic_onedrive; + case "s3": + return R.drawable.ic_amazon; + case "yandex": + return R.drawable.ic_yandex; + case "box": + return R.drawable.ic_box; + case "sftp": + return R.drawable.ic_terminal; + default: + return R.drawable.ic_cloud; + } + } + @Override public void onRemoteClick(RemoteItem remote) { + startRemote(remote); + } + + private void startRemote(RemoteItem remote) { fragment = FileExplorerFragment.newInstance(remote.getName(), remote.getType()); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.flFragment, fragment); transaction.addToBackStack(null); transaction.commit(); + addRemoteToShortcutList(remote); + navigationView.getMenu().getItem(0).setChecked(false); + } + + private void startRemote(String remoteName, String remoteType) { + fragment = FileExplorerFragment.newInstance(remoteName, remoteType); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.flFragment, fragment); + transaction.commit(); + navigationView.getMenu().getItem(0).setChecked(false); } @@ -356,6 +495,7 @@ protected void onPostExecute(Boolean success) { if (rclone.isConfigEncrypted()) { askForConfigPassword(); } else { + addRemotesToShortcutList(); startRemotesFragment(); } } @@ -390,6 +530,7 @@ protected void onPostExecute(Boolean success) { askForConfigPassword(); } else { findViewById(R.id.locked_config).setVisibility(View.GONE); + addRemotesToShortcutList(); startRemotesFragment(); } } diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/SettingsActivity.java b/app/src/main/java/ca/pkay/rcloneexplorer/SettingsActivity.java index 368886f..e87dbcd 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/SettingsActivity.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/SettingsActivity.java @@ -13,6 +13,7 @@ import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.CompoundButton; +import android.widget.ImageView; import android.widget.Switch; import android.widget.TextView; @@ -21,9 +22,9 @@ public class SettingsActivity extends AppCompatActivity { private View primaryColorElement; - private View primaryColorPreview; + private ImageView primaryColorPreview; private View accentColorElement; - private View accentColorPreview; + private ImageView accentColorPreview; private Switch darkThemeSwitch; private View darkThemeElement; private View notificationsElement; @@ -194,7 +195,7 @@ private void onPrimaryColorSelected(int color) { editor.putInt(getString(R.string.pref_key_color_primary), color); editor.apply(); - primaryColorPreview.getBackground().setTint(color); + primaryColorPreview.setColorFilter(color); showSnackBar(); } @@ -204,7 +205,7 @@ private void onAccentColorSelected(int color) { editor.putInt(getString(R.string.pref_key_color_accent), color); editor.apply(); - accentColorPreview.getBackground().setTint(color); + accentColorPreview.setColorFilter(color); showSnackBar(); } diff --git a/app/src/main/res/drawable/grey_circle.xml b/app/src/main/res/drawable/grey_circle.xml deleted file mode 100644 index 0a4701e..0000000 --- a/app/src/main/res/drawable/grey_circle.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_circle.xml b/app/src/main/res/drawable/ic_circle.xml new file mode 100644 index 0000000..101b3b2 --- /dev/null +++ b/app/src/main/res/drawable/ic_circle.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/color_picker_item.xml b/app/src/main/res/layout/color_picker_item.xml index 1a19a58..232a8fc 100644 --- a/app/src/main/res/layout/color_picker_item.xml +++ b/app/src/main/res/layout/color_picker_item.xml @@ -6,12 +6,12 @@ android:paddingStart="8dp" android:paddingEnd="8dp" android:paddingTop="12dp"> - + android:src="@drawable/ic_circle" + android:contentDescription="@string/content_description_circle" /> - + android:src="@drawable/ic_circle" + android:contentDescription="@string/content_description_circle" + android:tint="?attr/colorPrimary" /> @@ -106,14 +107,15 @@ android:textStyle="bold" android:text="@string/accent_color"/> - + android:tint="?attr/colorAccent" + android:src="@drawable/ic_circle" + android:contentDescription="@string/content_description_circle"/> diff --git a/app/src/main/res/layout/empty_directory_state.xml b/app/src/main/res/layout/empty_directory_state.xml index 8864709..0050409 100644 --- a/app/src/main/res/layout/empty_directory_state.xml +++ b/app/src/main/res/layout/empty_directory_state.xml @@ -13,14 +13,16 @@ android:layout_height="wrap_content" android:orientation="vertical" android:layout_centerInParent="true"> - - + + + - + - - - - - + - - - + + android:layout_height="76dp" + android:src="@drawable/ic_file" + android:contentDescription="@string/file_icon" /> + + + android:layout_toEndOf="@id/icons" + android:orientation="vertical" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:layout_centerVertical="true"> + android:textAppearance="?attr/textAppearanceListItem" + android:fontFamily="sans-serif" + android:textSize="16sp" + android:textColor="?attr/textColorPrimary" + android:ellipsize="middle" + android:singleLine="true" + tools:text="Test File"/> - + android:orientation="horizontal" + android:paddingTop="4dp" > - + + + + + + - - - \ No newline at end of file + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/no_internet_state.xml b/app/src/main/res/layout/no_internet_state.xml index e6ade3b..7b1b349 100644 --- a/app/src/main/res/layout/no_internet_state.xml +++ b/app/src/main/res/layout/no_internet_state.xml @@ -11,14 +11,16 @@ android:layout_height="wrap_content" android:orientation="vertical" android:layout_centerInParent="true"> - - + + + - + pref_key_color_primary pref_key_color_accent pref_key_dark_theme + pref_key_version_code Look and Feel Primary color Primary Color @@ -156,4 +157,5 @@ Select accent color Notifications Open system settings + circle diff --git a/build.gradle b/build.gradle index f76b4f9..8fd7939 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.1' + classpath 'com.android.tools.build:gradle:3.1.2' // NOTE: Do not place your application dependencies here; they belong