Skip to content

Commit d0c3440

Browse files
committed
Add context menu "Open in Terminal" option
Fixes #2666
1 parent bdc86af commit d0c3440

28 files changed

+1738
-460
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
4141
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
4242
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
43+
<uses-permission android:name="com.termux.permission.RUN_COMMAND" />
44+
<uses-permission android:name="com.termoneplus.permission.RUN_SCRIPT" />
45+
<uses-permission android:name="jackpal.androidterm.permission.RUN_SCRIPT" />
4346

4447
<uses-feature
4548
android:name="android.hardware.touchscreen"

app/src/main/java/com/amaze/filemanager/adapters/AppsRecyclerAdapter.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,17 @@ import com.amaze.filemanager.utils.safeLet
7070
import java.io.File
7171
import kotlin.math.roundToInt
7272

73+
/**
74+
* [RecyclerView.Adapter] implementation for apps lists.
75+
*/
7376
class AppsRecyclerAdapter(
7477
private val fragment: Fragment,
7578
private val modelProvider: AppsAdapterPreloadModel,
7679
private val isBottomSheet: Boolean,
7780
private val adjustListViewCallback: AdjustListViewForTv<AppHolder>,
7881
private val appDataParcelableList: MutableList<AppDataParcelable>,
82+
// Optional, for specifying customized action on row click
83+
private val onClickRowAction: ((AppDataParcelable) -> Unit)? = null,
7984
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
8085
private val myChecked = SparseBooleanArray()
8186
private var appDataListItem: MutableList<ListItem> = mutableListOf()
@@ -209,7 +214,11 @@ class AppsRecyclerAdapter(
209214
holder.rl.isClickable = true
210215
holder.rl.nextFocusRightId = holder.about.id
211216
holder.rl.setOnClickListener {
212-
startActivityForRowItem(rowItem)
217+
if (onClickRowAction != null) {
218+
onClickRowAction.invoke(rowItem)
219+
} else {
220+
startActivityForRowItem(rowItem)
221+
}
213222
}
214223
}
215224
if (myChecked[position]) {
@@ -508,7 +517,7 @@ class AppsRecyclerAdapter(
508517
MaterialDialog.Builder(fragment.requireContext())
509518
builder1
510519
.theme(
511-
themedActivity.appTheme.getMaterialDialogTheme(),
520+
themedActivity.appTheme.materialDialogTheme,
512521
)
513522
.content(fragment.getString(R.string.unin_system_apk))
514523
.title(fragment.getString(R.string.warning))

app/src/main/java/com/amaze/filemanager/adapters/RecyclerAdapter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,13 +1435,15 @@ private void showPopup(@NonNull View view, @NonNull final LayoutElementParcelabl
14351435
if (rowItem.isDirectory) {
14361436
popupMenu.getMenu().findItem(R.id.open_with).setVisible(false);
14371437
popupMenu.getMenu().findItem(R.id.share).setVisible(false);
1438+
popupMenu.getMenu().findItem(R.id.open_in_terminal).setVisible(true);
14381439

14391440
if (mainFragment.getMainActivity().mReturnIntent) {
14401441
popupMenu.getMenu().findItem(R.id.return_select).setVisible(true);
14411442
}
14421443
} else {
14431444
popupMenu.getMenu().findItem(R.id.book).setVisible(false);
14441445
popupMenu.getMenu().findItem(R.id.compress).setVisible(true);
1446+
popupMenu.getMenu().findItem(R.id.open_in_terminal).setVisible(false);
14451447

14461448
if (description.endsWith(fileExtensionZip)
14471449
|| description.endsWith(fileExtensionJar)

app/src/main/java/com/amaze/filemanager/filesystem/HybridFile.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@
116116
import io.reactivex.schedulers.Schedulers;
117117
import jcifs.smb.SmbException;
118118
import jcifs.smb.SmbFile;
119+
import kotlin.Deprecated;
120+
import kotlin.ReplaceWith;
119121
import kotlin.collections.ArraysKt;
120122
import kotlin.io.ByteStreamsKt;
121123
import kotlin.text.Charsets;
@@ -607,6 +609,9 @@ public String getParent(Context context) {
607609
*
608610
* @deprecated use {@link #isDirectory(Context)} to handle content resolvers
609611
*/
612+
@Deprecated(
613+
replaceWith = @ReplaceWith(expression = "isDirectory(Context)", imports = ""),
614+
message = "")
610615
public boolean isDirectory() {
611616
boolean isDirectory;
612617
switch (mode) {
@@ -701,6 +706,9 @@ public Boolean execute(@NonNull SFTPClient client) {
701706
/**
702707
* @deprecated use {@link #folderSize(Context)}
703708
*/
709+
@Deprecated(
710+
replaceWith = @ReplaceWith(expression = "folderSize(Context)", imports = ""),
711+
message = "")
704712
public long folderSize() {
705713
long size = 0L;
706714

@@ -1060,6 +1068,9 @@ public FTPFile[] executeWithFtpClient(@NonNull FTPClient ftpClient)
10601068
*
10611069
* @deprecated use forEachChildrenFile()
10621070
*/
1071+
@Deprecated(
1072+
replaceWith = @ReplaceWith(expression = "forEachChildrenFile", imports = ""),
1073+
message = "")
10631074
public ArrayList<HybridFileParcelable> listFiles(Context context, boolean isRoot) {
10641075
ArrayList<HybridFileParcelable> arrayList = new ArrayList<>();
10651076
forEachChildrenFile(context, isRoot, arrayList::add);

app/src/main/java/com/amaze/filemanager/filesystem/cloud/CloudUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161
import androidx.annotation.Nullable;
6262
import androidx.documentfile.provider.DocumentFile;
6363

64+
import kotlin.Deprecated;
65+
import kotlin.ReplaceWith;
66+
6467
/**
6568
* Created by vishal on 19/4/17.
6669
*
@@ -73,6 +76,7 @@ public class CloudUtil {
7376
/**
7477
* @deprecated use getCloudFiles()
7578
*/
79+
@Deprecated(replaceWith = @ReplaceWith(expression = "getCloudFiles", imports = ""), message = "")
7680
public static ArrayList<HybridFileParcelable> listFiles(
7781
String path, CloudStorage cloudStorage, OpenMode openMode) throws CloudPluginException {
7882
final ArrayList<HybridFileParcelable> baseFiles = new ArrayList<>();

app/src/main/java/com/amaze/filemanager/filesystem/files/FileUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,11 @@ public static void installApk(
377377
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
378378
&& !permissionsActivity.getPackageManager().canRequestPackageInstalls()) {
379379
permissionsActivity.requestInstallApkPermission(
380-
() -> installApk(f, permissionsActivity), true);
380+
() -> {
381+
installApk(f, permissionsActivity);
382+
return null;
383+
},
384+
true);
381385
}
382386

383387
Intent intent = new Intent(Intent.ACTION_VIEW);

app/src/main/java/com/amaze/filemanager/ui/ItemPopupMenu.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.amaze.filemanager.ui.dialogs.EncryptAuthenticateDialog;
3838
import com.amaze.filemanager.ui.dialogs.EncryptWithPresetPasswordSaveAsDialog;
3939
import com.amaze.filemanager.ui.dialogs.GeneralDialogCreation;
40+
import com.amaze.filemanager.ui.dialogs.OpenFolderInTerminalFragment;
4041
import com.amaze.filemanager.ui.fragments.MainFragment;
4142
import com.amaze.filemanager.ui.fragments.preferencefragments.PreferencesConstants;
4243
import com.amaze.filemanager.ui.provider.UtilitiesProvider;
@@ -256,6 +257,9 @@ public void onButtonPressed(Intent intent, String password)
256257
case R.id.return_select:
257258
mainFragment.returnIntentResults(new HybridFileParcelable[] {rowItem.generateBaseFile()});
258259
return true;
260+
case R.id.open_in_terminal:
261+
OpenFolderInTerminalFragment.Companion.openTerminalOrShow(rowItem.desc, mainActivity);
262+
return true;
259263
}
260264
return false;
261265
}

app/src/main/java/com/amaze/filemanager/ui/activities/MainActivity.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@
210210
import io.reactivex.android.schedulers.AndroidSchedulers;
211211
import io.reactivex.disposables.Disposable;
212212
import io.reactivex.schedulers.Schedulers;
213+
import kotlin.Unit;
213214
import kotlin.collections.ArraysKt;
215+
import kotlin.jvm.functions.Function0;
214216
import kotlin.jvm.functions.Function1;
215217
import kotlin.text.Charsets;
216218

@@ -220,7 +222,7 @@ public class MainActivity extends PermissionsActivity
220222
CloudConnectionCallbacks,
221223
LoaderManager.LoaderCallbacks<Cursor>,
222224
FolderChooserDialog.FolderCallback,
223-
PermissionsActivity.OnPermissionGranted {
225+
Function0<Unit> {
224226

225227
private static final Logger LOG = LoggerFactory.getLogger(MainActivity.class);
226228

@@ -530,9 +532,8 @@ public void invalidateFragmentAndBundle(Bundle savedInstanceState, boolean isClo
530532
}
531533
}
532534

533-
@Override
534535
@SuppressLint("CheckResult")
535-
public void onPermissionGranted() {
536+
public Unit invoke() {
536537
drawer.refreshDrawer();
537538
TabFragment tabFragment = getTabFragment();
538539
boolean b = getBoolean(PREFERENCE_NEED_TO_SET_HOME);
@@ -561,6 +562,7 @@ public void onPermissionGranted() {
561562
if (main1 != null) ((MainFragment) main1).updateList(false);
562563
}
563564
}
565+
return null;
564566
}
565567

566568
private void checkForExternalPermission() {
@@ -1120,6 +1122,7 @@ public boolean onPrepareOptionsMenu(Menu menu) {
11201122
menu.findItem(R.id.hiddenitems).setVisible(true);
11211123
menu.findItem(R.id.view).setVisible(true);
11221124
menu.findItem(R.id.extract).setVisible(false);
1125+
menu.findItem(R.id.open_in_terminal).setVisible(true);
11231126
invalidatePasteSnackbar(true);
11241127
findViewById(R.id.buttonbarframe).setVisibility(View.VISIBLE);
11251128
} else if (fragment instanceof AppsListFragment
@@ -1133,6 +1136,7 @@ public boolean onPrepareOptionsMenu(Menu menu) {
11331136
menu.findItem(R.id.home).setVisible(false);
11341137
menu.findItem(R.id.history).setVisible(false);
11351138
menu.findItem(R.id.extract).setVisible(false);
1139+
menu.findItem(R.id.open_in_terminal).setVisible(false);
11361140
if (fragment instanceof ProcessViewerFragment) {
11371141
menu.findItem(R.id.sort).setVisible(false);
11381142
} else if (fragment instanceof FtpServerFragment) {
@@ -1156,6 +1160,7 @@ public boolean onPrepareOptionsMenu(Menu menu) {
11561160
menu.findItem(R.id.hiddenitems).setVisible(false);
11571161
menu.findItem(R.id.view).setVisible(false);
11581162
menu.findItem(R.id.extract).setVisible(true);
1163+
menu.findItem(R.id.open_in_terminal).setVisible(false);
11591164
invalidatePasteSnackbar(false);
11601165
}
11611166
return super.onPrepareOptionsMenu(menu);
@@ -1291,6 +1296,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
12911296
break;
12921297
case R.id.search:
12931298
getAppbar().getSearchView().revealSearchView();
1299+
break;
1300+
case R.id.open_in_terminal:
1301+
if (getFragmentAtFrame() instanceof MainFragment) {}
1302+
12941303
break;
12951304
}
12961305
return null;

app/src/main/java/com/amaze/filemanager/ui/activities/superclasses/BasicActivity.java renamed to app/src/main/java/com/amaze/filemanager/ui/activities/superclasses/BasicActivity.kt

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,25 @@
1717
* You should have received a copy of the GNU General Public License
1818
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1919
*/
20+
package com.amaze.filemanager.ui.activities.superclasses
2021

21-
package com.amaze.filemanager.ui.activities.superclasses;
22+
import androidx.appcompat.app.AppCompatActivity
23+
import com.amaze.filemanager.application.AppConfig
24+
import com.amaze.filemanager.ui.colors.ColorPreferenceHelper
25+
import com.amaze.filemanager.ui.provider.UtilitiesProvider
26+
import com.amaze.filemanager.ui.theme.AppTheme
2227

23-
import com.amaze.filemanager.application.AppConfig;
24-
import com.amaze.filemanager.ui.colors.ColorPreferenceHelper;
25-
import com.amaze.filemanager.ui.provider.UtilitiesProvider;
26-
import com.amaze.filemanager.ui.theme.AppTheme;
28+
/** Created by rpiotaix on 17/10/16. */
29+
open class BasicActivity : AppCompatActivity() {
30+
private val appConfig: AppConfig
31+
get() = application as AppConfig
2732

28-
import androidx.appcompat.app.AppCompatActivity;
33+
val colorPreference: ColorPreferenceHelper
34+
get() = appConfig.utilsProvider.colorPreference
2935

30-
/** Created by rpiotaix on 17/10/16. */
31-
public class BasicActivity extends AppCompatActivity {
36+
val appTheme: AppTheme
37+
get() = appConfig.utilsProvider.appTheme
3238

33-
protected AppConfig getAppConfig() {
34-
return (AppConfig) getApplication();
35-
}
36-
37-
public ColorPreferenceHelper getColorPreference() {
38-
return getAppConfig().getUtilsProvider().getColorPreference();
39-
}
40-
41-
public AppTheme getAppTheme() {
42-
return getAppConfig().getUtilsProvider().getAppTheme();
43-
}
44-
45-
public UtilitiesProvider getUtilsProvider() {
46-
return getAppConfig().getUtilsProvider();
47-
}
39+
val utilsProvider: UtilitiesProvider
40+
get() = appConfig.utilsProvider
4841
}

0 commit comments

Comments
 (0)