diff --git a/app/src/main/java/com/termux/widget/ShortcutFile.java b/app/src/main/java/com/termux/widget/ShortcutFile.java index dfefba3..7036701 100644 --- a/app/src/main/java/com/termux/widget/ShortcutFile.java +++ b/app/src/main/java/com/termux/widget/ShortcutFile.java @@ -10,10 +10,12 @@ import android.os.Build; import android.widget.RemoteViews; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import com.google.common.base.Joiner; +import com.termux.shared.data.DataUtils; import com.termux.shared.file.FileUtils; import com.termux.shared.file.TermuxFileUtils; import com.termux.shared.file.filesystem.FileType; @@ -32,18 +34,57 @@ public final class ShortcutFile { private static final String LOG_TAG = "ShortcutFile"; - public final File file; - public final String label; + public final String mPath; + public String mLabel; - public ShortcutFile(File file, int depth) { - this.file = file; - this.label = (depth > 0 ? (file.getParentFile().getName() + "/") : "") - + file.getName(); + public ShortcutFile(@NonNull String path) { + this(path, null); + } + + public ShortcutFile(@NonNull File file) { + this(file.getAbsolutePath(), null); + } + + public ShortcutFile(@NonNull File file, int depth) { + this(file.getAbsolutePath(), + (depth > 0 && file.getParentFile() != null ? (file.getParentFile().getName() + "/") : "") + file.getName()); + } + + public ShortcutFile(@NonNull String path, @Nullable String defaultLabel) { + mPath = path; + mLabel = getLabelForShortcut(defaultLabel); + } + + @NonNull + public String getPath() { + return mPath; + } + + @NonNull + public String getCanonicalPath() { + return FileUtils.getCanonicalPath(getPath(), null); + } + + @NonNull + public String getUnExpandedPath() { + return TermuxFileUtils.getUnExpandedTermuxPath(getCanonicalPath()); + } + + @NonNull + public String getLabel() { + return mLabel; + } + + @NonNull + public String getLabelForShortcut(@Nullable String defaultLabel) { + if (!DataUtils.isNullOrEmpty(defaultLabel)) + return defaultLabel; + else + return ShellUtils.getExecutableBasename(mPath); } public Intent getExecutionIntent(Context context) { - String path = file.getAbsolutePath(); - Uri scriptUri = new Uri.Builder().scheme(TERMUX_SERVICE.URI_SCHEME_SERVICE_EXECUTE).path(path).build(); + Uri scriptUri = new Uri.Builder().scheme(TERMUX_SERVICE.URI_SCHEME_SERVICE_EXECUTE).path(getPath()).build(); Intent executionIntent = new Intent(context, TermuxLaunchShortcutActivity.class); executionIntent.setAction(TERMUX_SERVICE.ACTION_SERVICE_EXECUTE); // Mandatory for pinned shortcuts executionIntent.setData(scriptUri); @@ -53,14 +94,12 @@ public Intent getExecutionIntent(Context context) { @RequiresApi(api = Build.VERSION_CODES.N_MR1) public ShortcutInfo getShortcutInfo(Context context) { - String path = file.getAbsolutePath(); - - ShortcutInfo.Builder builder = new ShortcutInfo.Builder(context, path); - builder.setIntent(this.getExecutionIntent(context)); - builder.setShortLabel(this.label); + ShortcutInfo.Builder builder = new ShortcutInfo.Builder(context, getPath()); + builder.setIntent(getExecutionIntent(context)); + builder.setShortLabel(getLabel()); // Set icon if existent. - File shortcutIconFile = TermuxCreateShortcutActivity.getShortcutIconFile(context, ShellUtils.getExecutableBasename(path)); + File shortcutIconFile = getIconFile(context); if (shortcutIconFile != null) builder.setIcon(Icon.createWithBitmap(((BitmapDrawable) Drawable.createFromPath(shortcutIconFile.getAbsolutePath())).getBitmap())); else @@ -69,26 +108,40 @@ public ShortcutInfo getShortcutInfo(Context context) { return builder.build(); } + public Intent getStaticShortcutIntent(Context context) { + Intent intent = new Intent(); + intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, getExecutionIntent(context)); + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getLabel()); + + // Set icon if existent. + File shortcutIconFile = getIconFile(context); + if (shortcutIconFile != null) + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, ((BitmapDrawable) Drawable.createFromPath(shortcutIconFile.getAbsolutePath())).getBitmap()); + else + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context, R.drawable.ic_launcher)); + + return intent; + } + public RemoteViews getListWidgetView(Context context) { // Position will always range from 0 to getCount() - 1. // Construct remote views item based on the item xml file and set text based on position. - RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_item); - rv.setTextViewText(R.id.widget_item, this.label); + RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_item); + remoteViews.setTextViewText(R.id.widget_item, getLabel()); // Next, we set a fill-intent which will be used to fill-in the pending intent template // which is set on the collection view in TermuxAppWidgetProvider. - Intent fillInIntent = new Intent().putExtra(TERMUX_WIDGET_PROVIDER.EXTRA_FILE_CLICKED, this.file.getAbsolutePath()); - rv.setOnClickFillInIntent(R.id.widget_item_layout, fillInIntent); + Intent fillInIntent = new Intent().putExtra(TERMUX_WIDGET_PROVIDER.EXTRA_FILE_CLICKED, getPath()); + remoteViews.setOnClickFillInIntent(R.id.widget_item_layout, fillInIntent); - return rv; + return remoteViews; } @Nullable private File getIconFile(Context context) { String errmsg; - String shortcutIconFilePath = FileUtils.getCanonicalPath( - TermuxConstants.TERMUX_SHORTCUT_SCRIPT_ICONS_DIR_PATH + - "/" + ShellUtils.getExecutableBasename(file.getAbsolutePath()) + ".png", null); + String shortcutIconFilePath = TermuxConstants.TERMUX_SHORTCUT_SCRIPT_ICONS_DIR_PATH + + "/" + ShellUtils.getExecutableBasename(getPath()) + ".png"; FileType fileType = FileUtils.getFileType(shortcutIconFilePath, true); // Ensure file or symlink points to a regular file that exists diff --git a/app/src/main/java/com/termux/widget/TermuxCreateShortcutActivity.java b/app/src/main/java/com/termux/widget/TermuxCreateShortcutActivity.java index 3bf5d1f..383d1b3 100644 --- a/app/src/main/java/com/termux/widget/TermuxCreateShortcutActivity.java +++ b/app/src/main/java/com/termux/widget/TermuxCreateShortcutActivity.java @@ -4,32 +4,16 @@ import android.app.Activity; import android.app.AlertDialog; import android.content.Context; -import android.content.Intent; -import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.view.MenuItem; import android.widget.ArrayAdapter; import android.widget.ListView; -import androidx.annotation.Nullable; - -import com.google.common.base.Joiner; import com.termux.shared.data.DataUtils; -import com.termux.shared.file.FileUtils; -import com.termux.shared.file.TermuxFileUtils; -import com.termux.shared.file.filesystem.FileType; import com.termux.shared.logger.Logger; -import com.termux.shared.settings.preferences.TermuxWidgetAppSharedPreferences; -import com.termux.shared.shell.ShellUtils; import com.termux.shared.termux.TermuxConstants; -import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE; -import com.termux.shared.termux.TermuxConstants.TERMUX_WIDGET; import com.termux.shared.termux.TermuxUtils; import com.termux.widget.utils.ShortcutUtils; @@ -124,102 +108,36 @@ private void createShortcut(Context context, File clickedFile) { isPinnedShortcutSupported = true; } - String shortcutFilePath = FileUtils.getCanonicalPath(clickedFile.getAbsolutePath(), null); + ShortcutFile shortcutFile = new ShortcutFile(clickedFile); try { if (isPinnedShortcutSupported) - createPinnedShortcut(context, shortcutFilePath); + createPinnedShortcut(context, shortcutFile); else - createStaticShortcut(context, shortcutFilePath); + createStaticShortcut(context, shortcutFile); } catch (Exception e) { String message = context.getString( isPinnedShortcutSupported ? R.string.error_create_pinned_shortcut_failed : R.string.error_create_static_shortcut_failed, - TermuxFileUtils.getUnExpandedTermuxPath(shortcutFilePath)); + shortcutFile.getUnExpandedPath()); Logger.logErrorAndShowToast(context, LOG_TAG, message + ": " + e.getMessage()); Logger.logStackTraceWithMessage(LOG_TAG, message, e); } } @TargetApi(Build.VERSION_CODES.O) - private void createPinnedShortcut(Context context, String shortcutFilePath) { + private void createPinnedShortcut(Context context, ShortcutFile shortcutFile) { ShortcutManager shortcutManager = (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE); if (shortcutManager == null) return; - String shortcutFileName = ShellUtils.getExecutableBasename(shortcutFilePath); - - ShortcutInfo.Builder builder = new ShortcutInfo.Builder(context, shortcutFilePath); - builder.setIntent(TermuxCreateShortcutActivity.getExecutionIntent(context, shortcutFilePath)); - builder.setShortLabel(shortcutFileName); - - File shortcutIconFile = TermuxCreateShortcutActivity.getShortcutIconFile(context, shortcutFileName); - if (shortcutIconFile != null) - builder.setIcon(Icon.createWithBitmap(((BitmapDrawable) Drawable.createFromPath(shortcutIconFile.getAbsolutePath())).getBitmap())); - else - builder.setIcon(Icon.createWithResource(context, R.drawable.ic_launcher)); - Logger.showToast(context, context.getString(R.string.msg_request_create_pinned_shortcut, - TermuxFileUtils.getUnExpandedTermuxPath(shortcutFilePath)), true); - shortcutManager.requestPinShortcut(builder.build(), null); + shortcutFile.getUnExpandedPath()), true); + shortcutManager.requestPinShortcut(shortcutFile.getShortcutInfo(context), null); } - private void createStaticShortcut(Context context, String shortcutFilePath) { - String shortcutFileName = ShellUtils.getExecutableBasename(shortcutFilePath); - - Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, TermuxCreateShortcutActivity.getExecutionIntent(context, shortcutFilePath)); - intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutFileName); - - File shortcutIconFile = TermuxCreateShortcutActivity.getShortcutIconFile(context, shortcutFileName); - if (shortcutIconFile != null) - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, ((BitmapDrawable) Drawable.createFromPath(shortcutIconFile.getAbsolutePath())).getBitmap()); - else - intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(context, R.drawable.ic_launcher)); - + private void createStaticShortcut(Context context, ShortcutFile shortcutFile) { Logger.showToast(context, context.getString(R.string.msg_request_create_static_shortcut, - TermuxFileUtils.getUnExpandedTermuxPath(shortcutFilePath)), true); - setResult(RESULT_OK, intent); - } - - public static Intent getExecutionIntent(Context context, String shortcutFilePath) { - Uri scriptUri = new Uri.Builder().scheme(TERMUX_SERVICE.URI_SCHEME_SERVICE_EXECUTE).path(shortcutFilePath).build(); - Intent executionIntent = new Intent(context, TermuxLaunchShortcutActivity.class); - executionIntent.setAction(TERMUX_SERVICE.ACTION_SERVICE_EXECUTE); // Mandatory for pinned shortcuts - executionIntent.setData(scriptUri); - executionIntent.putExtra(TERMUX_WIDGET.EXTRA_TOKEN_NAME, TermuxWidgetAppSharedPreferences.getGeneratedToken(context)); - return executionIntent; - } - - @Nullable - public static File getShortcutIconFile(Context context, String shortcutFileName) { - String errmsg; - String shortcutIconFilePath = FileUtils.getCanonicalPath( - TermuxConstants.TERMUX_SHORTCUT_SCRIPT_ICONS_DIR_PATH + - "/" + shortcutFileName + ".png", null); - - FileType fileType = FileUtils.getFileType(shortcutIconFilePath, true); - // Ensure file or symlink points to a regular file that exists - if (fileType != FileType.REGULAR) { - if (fileType != FileType.NO_EXIST) { - errmsg = context.getString(R.string.error_icon_not_a_regular_file, fileType.getName()) + - "\n" + context.getString(R.string.msg_icon_absolute_path, shortcutIconFilePath); - Logger.logErrorAndShowToast(context, LOG_TAG, errmsg); - } - return null; - } - - // Do not allow shortcut icons files not under SHORTCUT_ICONS_FILES_ALLOWED_PATHS_LIST - if (!FileUtils.isPathInDirPaths(shortcutIconFilePath, ShortcutUtils.SHORTCUT_ICONS_FILES_ALLOWED_PATHS_LIST, true)) { - errmsg = context.getString(R.string.error_icon_not_under_shortcut_icons_directories, - Joiner.on(", ").skipNulls().join(TermuxFileUtils.getUnExpandedTermuxPaths(ShortcutUtils.SHORTCUT_ICONS_FILES_ALLOWED_PATHS_LIST))) + - "\n" + context.getString(R.string.msg_icon_absolute_path, shortcutIconFilePath); - Logger.logErrorAndShowToast(context, LOG_TAG, errmsg); - return null; - } - - Logger.logInfo(LOG_TAG, "Using file at \"" + shortcutIconFilePath + "\" as shortcut icon file"); - Logger.showToast(context, "Using file at \"" + shortcutIconFilePath + "\" as shortcut icon file", true); - - return new File(shortcutIconFilePath); + shortcutFile.getUnExpandedPath()), true); + setResult(RESULT_OK, shortcutFile.getStaticShortcutIntent(context)); } }