Skip to content

Commit 3e01412

Browse files
committed
Add context menu "Open in Terminal" option
Fixes #2666
1 parent 5494c67 commit 3e01412

28 files changed

+1737
-460
lines changed

app/src/main/AndroidManifest.xml

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

4548
<uses-feature
4649
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
@@ -118,6 +118,8 @@
118118
import io.reactivex.schedulers.Schedulers;
119119
import jcifs.smb.SmbException;
120120
import jcifs.smb.SmbFile;
121+
import kotlin.Deprecated;
122+
import kotlin.ReplaceWith;
121123
import kotlin.collections.ArraysKt;
122124
import kotlin.io.ByteStreamsKt;
123125
import kotlin.text.Charsets;
@@ -609,6 +611,9 @@ public String getParent(Context context) {
609611
*
610612
* @deprecated use {@link #isDirectory(Context)} to handle content resolvers
611613
*/
614+
@Deprecated(
615+
replaceWith = @ReplaceWith(expression = "isDirectory(Context)", imports = ""),
616+
message = "")
612617
public boolean isDirectory() {
613618
boolean isDirectory;
614619
switch (mode) {
@@ -703,6 +708,9 @@ public Boolean execute(@NonNull SFTPClient client) {
703708
/**
704709
* @deprecated use {@link #folderSize(Context)}
705710
*/
711+
@Deprecated(
712+
replaceWith = @ReplaceWith(expression = "folderSize(Context)", imports = ""),
713+
message = "")
706714
public long folderSize() {
707715
long size = 0L;
708716

@@ -1062,6 +1070,9 @@ public FTPFile[] executeWithFtpClient(@NonNull FTPClient ftpClient)
10621070
*
10631071
* @deprecated use forEachChildrenFile()
10641072
*/
1073+
@Deprecated(
1074+
replaceWith = @ReplaceWith(expression = "forEachChildrenFile", imports = ""),
1075+
message = "")
10651076
public ArrayList<HybridFileParcelable> listFiles(Context context, boolean isRoot) {
10661077
ArrayList<HybridFileParcelable> arrayList = new ArrayList<>();
10671078
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;
@@ -251,6 +252,9 @@ public void onButtonPressed(Intent intent, String password)
251252
} else if (item.getItemId() == R.id.return_select) {
252253
mainFragment.returnIntentResults(new HybridFileParcelable[] {rowItem.generateBaseFile()});
253254
return true;
255+
} else if (item.getItemId() == R.id.open_in_terminal) {
256+
OpenFolderInTerminalFragment.Companion.openTerminalOrShow(rowItem.desc, mainActivity);
257+
return true;
254258
}
255259
return false;
256260
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@
212212
import io.reactivex.android.schedulers.AndroidSchedulers;
213213
import io.reactivex.disposables.Disposable;
214214
import io.reactivex.schedulers.Schedulers;
215+
import kotlin.Unit;
215216
import kotlin.collections.ArraysKt;
217+
import kotlin.jvm.functions.Function0;
216218
import kotlin.jvm.functions.Function1;
217219
import kotlin.text.Charsets;
218220

@@ -222,7 +224,7 @@ public class MainActivity extends PermissionsActivity
222224
CloudConnectionCallbacks,
223225
LoaderManager.LoaderCallbacks<Cursor>,
224226
FolderChooserDialog.FolderCallback,
225-
PermissionsActivity.OnPermissionGranted {
227+
Function0<Unit> {
226228

227229
private static final Logger LOG = LoggerFactory.getLogger(MainActivity.class);
228230

@@ -532,9 +534,8 @@ public void invalidateFragmentAndBundle(Bundle savedInstanceState, boolean isClo
532534
}
533535
}
534536

535-
@Override
536537
@SuppressLint("CheckResult")
537-
public void onPermissionGranted() {
538+
public Unit invoke() {
538539
drawer.refreshDrawer();
539540
TabFragment tabFragment = getTabFragment();
540541
boolean b = getBoolean(PREFERENCE_NEED_TO_SET_HOME);
@@ -563,6 +564,7 @@ public void onPermissionGranted() {
563564
if (main1 != null) ((MainFragment) main1).updateList(false);
564565
}
565566
}
567+
return null;
566568
}
567569

568570
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);
@@ -1279,6 +1284,8 @@ public boolean onOptionsItemSelected(MenuItem item) {
12791284
}
12801285
} else if (item.getItemId() == R.id.search) {
12811286
getAppbar().getSearchView().revealSearchView();
1287+
} else if (item.getItemId() == R.id.open_in_terminal) {
1288+
// do nothing
12821289
}
12831290
return null;
12841291
},

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)