feat(gui): added support view and open more resource files (PR #2483)
* feat(gui): added support view and open more resource files * fix(gui): remove svg extension from resource types * fix(gui): use error dialog from common utils * fix: reformat code
@@ -10,9 +10,15 @@ public enum ResourceType {
|
||||
CODE(".dex", ".jar", ".class"),
|
||||
XML(".xml"),
|
||||
ARSC(".arsc"),
|
||||
FONT(".ttf", ".otf"),
|
||||
IMG(".png", ".gif", ".jpg", ".webp"),
|
||||
MEDIA(".mp3", ".wav"),
|
||||
APK(".apk", ".apkm", ".apks"),
|
||||
FONT(".ttf", ".ttc", ".otf"),
|
||||
IMG(".png", ".gif", ".jpg", ".webp", ".bmp", ".tiff"),
|
||||
ARCHIVE(".zip", ".rar", ".7zip", ".7z", ".arj", ".tar", ".gzip", ".bzip", ".bzip2", ".cab", ".cpio", ".ar", ".gz", ".tgz", ".bz2"),
|
||||
VIDEOS(".mp4", ".mkv", ".webm", ".avi", ".flv", ".3gp"),
|
||||
SOUNDS(".aac", ".ogg", ".opus", ".mp3", ".wav", ".wma", ".mid", ".midi"),
|
||||
JSON(".json"),
|
||||
TEXT(".txt", ".ini", ".conf", ".yaml", ".properties", ".js"),
|
||||
HTML(".html"),
|
||||
LIB(".so"),
|
||||
MANIFEST,
|
||||
UNKNOWN;
|
||||
|
||||
@@ -25,6 +25,7 @@ import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.ui.codearea.BinaryContentPanel;
|
||||
import jadx.gui.ui.codearea.CodeContentPanel;
|
||||
import jadx.gui.ui.panel.ContentPanel;
|
||||
import jadx.gui.ui.panel.FontPanel;
|
||||
import jadx.gui.ui.panel.ImagePanel;
|
||||
import jadx.gui.ui.popupmenu.JResourcePopupMenu;
|
||||
import jadx.gui.ui.tab.TabbedPane;
|
||||
@@ -43,6 +44,14 @@ public class JResource extends JLoadableNode {
|
||||
private static final ImageIcon SO_ICON = UiUtils.openSvgIcon("nodes/binaryFile");
|
||||
private static final ImageIcon MANIFEST_ICON = UiUtils.openSvgIcon("nodes/manifest");
|
||||
private static final ImageIcon JAVA_ICON = UiUtils.openSvgIcon("nodes/java");
|
||||
private static final ImageIcon APK_ICON = UiUtils.openSvgIcon("nodes/archiveApk");
|
||||
private static final ImageIcon AUDIO_ICON = UiUtils.openSvgIcon("nodes/audioFile");
|
||||
private static final ImageIcon VIDEO_ICON = UiUtils.openSvgIcon("nodes/videoFile");
|
||||
private static final ImageIcon FONT_ICON = UiUtils.openSvgIcon("nodes/fontFile");
|
||||
private static final ImageIcon HTML_ICON = UiUtils.openSvgIcon("nodes/html");
|
||||
private static final ImageIcon JSON_ICON = UiUtils.openSvgIcon("nodes/json");
|
||||
private static final ImageIcon TEXT_ICON = UiUtils.openSvgIcon("nodes/text");
|
||||
private static final ImageIcon ARCHIVE_ICON = UiUtils.openSvgIcon("nodes/archive");
|
||||
private static final ImageIcon UNKNOWN_ICON = UiUtils.openSvgIcon("nodes/unknown");
|
||||
|
||||
public static final Comparator<JResource> RESOURCES_COMPARATOR =
|
||||
@@ -150,6 +159,9 @@ public class JResource extends JLoadableNode {
|
||||
if (resFile.getType() == ResourceType.LIB) {
|
||||
return new BinaryContentPanel(tabbedPane, this, false);
|
||||
}
|
||||
if (resFile.getType() == ResourceType.FONT) {
|
||||
return new FontPanel(tabbedPane, this);
|
||||
}
|
||||
if (getSyntaxByExtension(resFile.getDeobfName()) == null) {
|
||||
return new BinaryContentPanel(tabbedPane, this);
|
||||
}
|
||||
@@ -287,6 +299,22 @@ public class JResource extends JLoadableNode {
|
||||
return SO_ICON;
|
||||
case CODE:
|
||||
return JAVA_ICON;
|
||||
case APK:
|
||||
return APK_ICON;
|
||||
case VIDEOS:
|
||||
return VIDEO_ICON;
|
||||
case SOUNDS:
|
||||
return AUDIO_ICON;
|
||||
case FONT:
|
||||
return FONT_ICON;
|
||||
case HTML:
|
||||
return HTML_ICON;
|
||||
case JSON:
|
||||
return JSON_ICON;
|
||||
case TEXT:
|
||||
return TEXT_ICON;
|
||||
case ARCHIVE:
|
||||
return ARCHIVE_ICON;
|
||||
case UNKNOWN:
|
||||
return UNKNOWN_ICON;
|
||||
}
|
||||
@@ -298,8 +326,10 @@ public class JResource extends JLoadableNode {
|
||||
public static boolean isSupportedForView(ResourceType type) {
|
||||
switch (type) {
|
||||
case CODE:
|
||||
case FONT:
|
||||
case MEDIA:
|
||||
case SOUNDS:
|
||||
case VIDEOS:
|
||||
case ARCHIVE:
|
||||
case APK:
|
||||
return false;
|
||||
|
||||
case MANIFEST:
|
||||
@@ -307,12 +337,26 @@ public class JResource extends JLoadableNode {
|
||||
case ARSC:
|
||||
case IMG:
|
||||
case LIB:
|
||||
case FONT:
|
||||
case TEXT:
|
||||
case JSON:
|
||||
case HTML:
|
||||
case UNKNOWN:
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isOpenInExternalTool(ResourceType type) {
|
||||
switch (type) {
|
||||
case SOUNDS:
|
||||
case VIDEOS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceFile getResFile() {
|
||||
return resFile;
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ import jadx.gui.utils.dbg.UIWatchDog;
|
||||
import jadx.gui.utils.fileswatcher.LiveReloadWorker;
|
||||
import jadx.gui.utils.shortcut.ShortcutsController;
|
||||
import jadx.gui.utils.ui.ActionHandler;
|
||||
import jadx.gui.utils.ui.FileOpenerHelper;
|
||||
import jadx.gui.utils.ui.NodeLabel;
|
||||
|
||||
public class MainWindow extends JFrame {
|
||||
@@ -888,9 +889,15 @@ public class MainWindow extends JFrame {
|
||||
if (obj instanceof JResource) {
|
||||
JResource res = (JResource) obj;
|
||||
ResourceFile resFile = res.getResFile();
|
||||
if (resFile != null && JResource.isSupportedForView(resFile.getType())) {
|
||||
tabsController.selectTab(res, true);
|
||||
return true;
|
||||
if (resFile != null) {
|
||||
if (JResource.isOpenInExternalTool(resFile.getType())) {
|
||||
FileOpenerHelper.openFile(this, res);
|
||||
return true;
|
||||
}
|
||||
if (JResource.isSupportedForView(resFile.getType())) {
|
||||
tabsController.selectTab(res, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (obj instanceof JNode) {
|
||||
JNode treeNode = (JNode) obj;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package jadx.gui.ui.panel;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.api.ResourcesLoader;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.xmlgen.ResContainer;
|
||||
import jadx.gui.treemodel.JResource;
|
||||
import jadx.gui.ui.codearea.AbstractCodeArea;
|
||||
import jadx.gui.ui.tab.TabbedPane;
|
||||
import jadx.gui.utils.NLS;
|
||||
|
||||
public class FontPanel extends ContentPanel {
|
||||
private static final long serialVersionUID = 695370628262996993L;
|
||||
private static final String DEFAULT_PREVIEW_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
|
||||
+ "abcdefghijklmnopqrstuvwxyz\n"
|
||||
+ "1234567890!@#$%^&*()_-=+[]{}<,.>";
|
||||
|
||||
public FontPanel(TabbedPane panel, JResource res) {
|
||||
super(panel, res);
|
||||
setLayout(new BorderLayout());
|
||||
RSyntaxTextArea textArea = AbstractCodeArea.getDefaultArea(panel.getMainWindow());
|
||||
add(textArea, BorderLayout.CENTER);
|
||||
try {
|
||||
Font selectedFont = loadFont(res);
|
||||
if (selectedFont.canDisplay(DEFAULT_PREVIEW_STRING.codePointAt(0))) {
|
||||
textArea.setFont(selectedFont);
|
||||
textArea.setText(DEFAULT_PREVIEW_STRING);
|
||||
} else {
|
||||
textArea.setText(NLS.str("message.unable_preview_font"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
textArea.setText("Font load error:\n" + Utils.getStackTrace(e));
|
||||
}
|
||||
}
|
||||
|
||||
private Font loadFont(JResource res) {
|
||||
ResourceFile resFile = res.getResFile();
|
||||
ResContainer resContainer = resFile.loadContent();
|
||||
ResContainer.DataType dataType = resContainer.getDataType();
|
||||
if (dataType == ResContainer.DataType.DECODED_DATA) {
|
||||
try {
|
||||
return Font.createFont(Font.TRUETYPE_FONT, new ByteArrayInputStream(resContainer.getDecodedData())).deriveFont(12f);
|
||||
} catch (Exception e) {
|
||||
throw new JadxRuntimeException("Failed to load font", e);
|
||||
}
|
||||
} else if (dataType == ResContainer.DataType.RES_LINK) {
|
||||
try {
|
||||
return ResourcesLoader.decodeStream(resFile, (size, is) -> {
|
||||
try {
|
||||
return Font.createFont(Font.TRUETYPE_FONT, is).deriveFont(12f);
|
||||
} catch (FontFormatException e) {
|
||||
throw new JadxRuntimeException("Failed to load font", e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new JadxRuntimeException("Failed to load font", e);
|
||||
}
|
||||
} else {
|
||||
throw new JadxRuntimeException("Unsupported resource font data type: " + resFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadSettings() {
|
||||
// no op
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.gui.ui.popupmenu;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -17,13 +15,13 @@ import javax.swing.JPopupMenu;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.ResourcesLoader;
|
||||
import jadx.api.plugins.utils.CommonFileUtils;
|
||||
import jadx.gui.treemodel.JResource;
|
||||
import jadx.gui.ui.MainWindow;
|
||||
import jadx.gui.ui.filedialog.FileDialogWrapper;
|
||||
import jadx.gui.ui.filedialog.FileOpenMode;
|
||||
import jadx.gui.utils.NLS;
|
||||
import jadx.gui.utils.ui.FileOpenerHelper;
|
||||
|
||||
public class JResourcePopupMenu extends JPopupMenu {
|
||||
private static final long serialVersionUID = -7781009781149260806L;
|
||||
@@ -141,7 +139,7 @@ public class JResourcePopupMenu extends JPopupMenu {
|
||||
exportString(resource, savePath);
|
||||
break;
|
||||
default:
|
||||
exportBinary(resource, savePath);
|
||||
FileOpenerHelper.exportBinary(resource, savePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -154,16 +152,4 @@ public class JResourcePopupMenu extends JPopupMenu {
|
||||
}
|
||||
}
|
||||
|
||||
private static void exportBinary(JResource resource, Path savePath) {
|
||||
try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(savePath.toFile()))) {
|
||||
byte[] bytes = ResourcesLoader.decodeStream(resource.getResFile(), (size, is) -> is.readAllBytes());
|
||||
|
||||
if (bytes == null) {
|
||||
bytes = new byte[0];
|
||||
}
|
||||
os.write(bytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error saving file " + resource.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import jadx.gui.ui.codearea.ClassCodeContentPanel;
|
||||
import jadx.gui.ui.codearea.EditorViewState;
|
||||
import jadx.gui.ui.codearea.SmaliArea;
|
||||
import jadx.gui.ui.panel.ContentPanel;
|
||||
import jadx.gui.ui.panel.FontPanel;
|
||||
import jadx.gui.ui.panel.HtmlPanel;
|
||||
import jadx.gui.ui.panel.IViewStateSupport;
|
||||
import jadx.gui.ui.panel.ImagePanel;
|
||||
@@ -577,6 +578,10 @@ public class TabbedPane extends JTabbedPane implements ITabStatesListener {
|
||||
pane.addFocusListener(INSTANCE);
|
||||
return;
|
||||
}
|
||||
if (pane instanceof FontPanel) {
|
||||
pane.addFocusListener(INSTANCE);
|
||||
return;
|
||||
}
|
||||
// throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane);
|
||||
}
|
||||
|
||||
@@ -597,6 +602,10 @@ public class TabbedPane extends JTabbedPane implements ITabStatesListener {
|
||||
SwingUtilities.invokeLater(((ImagePanel) pane)::requestFocusInWindow);
|
||||
return;
|
||||
}
|
||||
if (pane instanceof FontPanel) {
|
||||
SwingUtilities.invokeLater(((FontPanel) pane)::requestFocusInWindow);
|
||||
return;
|
||||
}
|
||||
// throw new JadxRuntimeException("Add the new ContentPanel to TabbedPane.FocusManager: " + pane);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package jadx.gui.utils.ui;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Frame;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.api.ResourcesLoader;
|
||||
import jadx.core.plugins.files.TempFilesGetter;
|
||||
import jadx.gui.treemodel.JResource;
|
||||
import jadx.gui.utils.NLS;
|
||||
import jadx.gui.utils.UiUtils;
|
||||
|
||||
public class FileOpenerHelper {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileOpenerHelper.class);
|
||||
|
||||
public static void exportBinary(JResource resource, Path savePath) {
|
||||
try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(savePath.toFile()))) {
|
||||
byte[] bytes = ResourcesLoader.decodeStream(resource.getResFile(), (size, is) -> is.readAllBytes());
|
||||
|
||||
if (bytes == null) {
|
||||
bytes = new byte[0];
|
||||
}
|
||||
os.write(bytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error saving file " + resource.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void openFile(Frame frame, JResource res) {
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
Desktop desktop = Desktop.getDesktop();
|
||||
Path tempDir = TempFilesGetter.INSTANCE.getTempDir();
|
||||
ResourceFile resFile = res.getResFile();
|
||||
Path path = Paths.get(resFile.getDeobfName());
|
||||
Path fileNamePath = path.getFileName();
|
||||
Path filePath = tempDir.resolve(fileNamePath);
|
||||
exportBinary(res, filePath);
|
||||
|
||||
if (!Files.exists(filePath)) {
|
||||
UiUtils.errorMessage(frame, NLS.str("error_dialog.not_found_file", filePath));
|
||||
return;
|
||||
}
|
||||
if (Files.isDirectory(filePath)) {
|
||||
UiUtils.errorMessage(frame, NLS.str("error_dialog.path_is_directory", filePath));
|
||||
return;
|
||||
}
|
||||
if (!Files.isReadable(filePath)) {
|
||||
UiUtils.errorMessage(frame, NLS.str("error_dialog.cannot_read", filePath));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
desktop.open(filePath.toFile());
|
||||
} catch (IOException ex) {
|
||||
UiUtils.errorMessage(frame, NLS.str("error_dialog.open_failed", ex.getMessage()));
|
||||
LOG.error("Unable to open file: {0}", ex);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
UiUtils.errorMessage(frame, NLS.str("error_dialog.invalid_path_format", ex.getMessage()));
|
||||
LOG.error("Invalid file path: {0}", ex);
|
||||
}
|
||||
|
||||
} else {
|
||||
UiUtils.errorMessage(frame, NLS.str("error_dialog.desktop_unsupported"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,12 @@ progress.canceling=Breche ab
|
||||
|
||||
error_dialog.title=Fehler
|
||||
error_dialog.not_found=%s nicht gefunden
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=Vorheriges
|
||||
search.next=Nächstes
|
||||
@@ -125,6 +131,7 @@ message.confirm_remove_script=Willst du das Skript wirklich entfernen?
|
||||
message.desktop_entry_creation_error=Erstellen des Desktop-Eintrags fehlgeschlagen (Details findest du im Protokoll).
|
||||
message.desktop_entry_creation_success=Desktop-Eintrag erfolgreich erstellt!
|
||||
message.success_title=Erfolg
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=JADX-Speicherauslastung: %.2f GB von %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=Canceling
|
||||
|
||||
error_dialog.title=Error
|
||||
error_dialog.not_found=%s not found
|
||||
error_dialog.not_found_file=File not found at path:\n%s
|
||||
error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
error_dialog.cannot_read=Cannot read file:\n%s
|
||||
error_dialog.open_failed=Failed to open file:\n%s
|
||||
error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=Previous
|
||||
search.next=Next
|
||||
@@ -125,6 +131,7 @@ message.confirm_remove_script=Do you really want to remove script?
|
||||
message.desktop_entry_creation_error=Failed to create desktop entry (check log for details).
|
||||
message.desktop_entry_creation_success=Desktop entry created successfully!
|
||||
message.success_title=Success
|
||||
message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=JADX memory usage: %.2f GB of %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.decompile=Decompiling
|
||||
|
||||
#error_dialog.title=Error
|
||||
#error_dialog.not_found=%s not found
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=Anterior
|
||||
search.next=Siguiente
|
||||
@@ -125,6 +131,7 @@ nav.forward=Adelante
|
||||
#message.desktop_entry_creation_error=Failed to create desktop entry (check log for details).
|
||||
#message.desktop_entry_creation_success=Desktop entry created successfully!
|
||||
#message.success_title=Success
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
#heapUsage.text=JADX memory usage: %.2f GB of %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=Membatalkan
|
||||
|
||||
error_dialog.title=Kesalahan
|
||||
error_dialog.not_found=%s tidak ditemukan
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=Sebelumnya
|
||||
search.next=Berikutnya
|
||||
@@ -125,6 +131,7 @@ message.indexingClassesSkipped=<html>JADX kekurangan memori. Oleh karena itu %d
|
||||
#message.desktop_entry_creation_error=Failed to create desktop entry (check log for details).
|
||||
#message.desktop_entry_creation_success=Desktop entry created successfully!
|
||||
#message.success_title=Success
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=Penggunaan memori JADX: %.2f GB dari %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=취소 중
|
||||
|
||||
error_dialog.title=오류
|
||||
#error_dialog.not_found=%s not found
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=이전
|
||||
search.next=다음
|
||||
@@ -125,6 +131,7 @@ message.indexingClassesSkipped=<html>Jadx의 메모리가 부족합니다. 따
|
||||
#message.desktop_entry_creation_error=Failed to create desktop entry (check log for details).
|
||||
#message.desktop_entry_creation_success=Desktop entry created successfully!
|
||||
#message.success_title=Success
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=JADX 메모리 사용량 : %.2f GB / %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=Cancelando
|
||||
|
||||
error_dialog.title=Erro
|
||||
#error_dialog.not_found=%s not found
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=Anterior
|
||||
search.next=Próximo
|
||||
@@ -125,6 +131,7 @@ message.indexingClassesSkipped=<html>Jadx está rodando com pouca memória. Por
|
||||
#message.desktop_entry_creation_error=Failed to create desktop entry (check log for details).
|
||||
#message.desktop_entry_creation_success=Desktop entry created successfully!
|
||||
#message.success_title=Success
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=Uso de memória do JADX: %.2f GB of %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=Прерывание
|
||||
|
||||
error_dialog.title=Ошибка
|
||||
error_dialog.not_found= %s не найден
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=Назад
|
||||
search.next=Вперед
|
||||
@@ -125,6 +131,7 @@ message.indexingClassesSkipped=<html>JaDX запущен с малым коли
|
||||
#message.desktop_entry_creation_error=Failed to create desktop entry (check log for details).
|
||||
#message.desktop_entry_creation_success=Desktop entry created successfully!
|
||||
#message.success_title=Success
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=JADX использует: %.2f ГБ из %.2f ГБ
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=正在取消
|
||||
|
||||
error_dialog.title=错误
|
||||
error_dialog.not_found=未找到 %s
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=上一个
|
||||
search.next=下一个
|
||||
@@ -125,6 +131,7 @@ message.confirm_remove_script=您真的要删除脚本吗?
|
||||
message.desktop_entry_creation_error=创建桌面入口失败(请检查日志以了解详细信息)。
|
||||
message.desktop_entry_creation_success=创建桌面入口创建成功!
|
||||
message.success_title=成功
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=JADX 内存使用率:%.2f GB / %.2f GB
|
||||
|
||||
|
||||
@@ -74,6 +74,12 @@ progress.canceling=正在取消
|
||||
|
||||
error_dialog.title=錯誤
|
||||
error_dialog.not_found=找不到 %s
|
||||
#error_dialog.not_found_file=File not found at path:\n%s
|
||||
#error_dialog.path_is_directory=The specified path is a directory:\n%s
|
||||
#error_dialog.cannot_read=Cannot read file:\n%s
|
||||
#error_dialog.open_failed=Failed to open file:\n%s
|
||||
#error_dialog.invalid_path_format=Invalid file path:\n%s
|
||||
#error_dialog.desktop_unsupported=Desktop is not supported in this environment.
|
||||
|
||||
search.previous=上一個
|
||||
search.next=下一個
|
||||
@@ -125,6 +131,7 @@ message.confirm_remove_script=您確定要移除指令碼嗎?
|
||||
message.desktop_entry_creation_error=建立桌面項目失敗(詳情請查閱日誌)。
|
||||
message.desktop_entry_creation_success=成功建立桌面項目!
|
||||
message.success_title=成功
|
||||
#message.unable_preview_font=Unable preview font
|
||||
|
||||
heapUsage.text=JADX 記憶體使用率:%.2f GB / %.2f GB
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="6 1 3 1 3 5 3 15 6 15"/>
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="10 15 13 15 13 1 10 1"/>
|
||||
<polygon fill="#40B6E0" points="7.6 2 6 2 6.8 3 8.401 3"/>
|
||||
<polygon fill="#40B6E0" points="7.6 8 6 8 6.8 9 8.401 9"/>
|
||||
<polygon fill="#40B6E0" points="7.6 10 6 10 6.8 11 8.401 11"/>
|
||||
<polygon fill="#40B6E0" points="7.6 12 6 12 6.8 13 8.401 13"/>
|
||||
<polygon fill="#40B6E0" points="7.6 14 6 14 6.8 15 8.401 15"/>
|
||||
<polygon fill="#40B6E0" points="7.6 4 6 4 6.8 5 8.401 5"/>
|
||||
<polygon fill="#40B6E0" points="7.6 6 6 6 6.8 7 8.401 7"/>
|
||||
<polygon fill="#40B6E0" points="8.4 3 10 3 9.2 4 7.599 4"/>
|
||||
<polygon fill="#40B6E0" points="8.4 1 10 1 9.2 2 7.599 2"/>
|
||||
<polygon fill="#40B6E0" points="8.4 9 10 9 9.2 10 7.599 10"/>
|
||||
<polygon fill="#40B6E0" points="8.4 11 10 11 9.2 12 7.599 12"/>
|
||||
<polygon fill="#40B6E0" points="8.4 13 10 13 9.2 14 7.599 14"/>
|
||||
<polygon fill="#40B6E0" points="8.4 5 10 5 9.2 6 7.599 6"/>
|
||||
<polygon fill="#40B6E0" points="8.4 7 10 7 9.2 8 7.599 8"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,5 @@
|
||||
<!-- Copyright © 2000–2024 JetBrains s.r.o. -->
|
||||
<svg width="16" height="16" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#9aa7b0" d="M24.78 56h2.09l-4.73-13H20l-4.73 13h2.09l1.2-3.53h5.02l1.2 3.53Zm-5.68-5.13 1.95-5.74h.05l1.95 5.74h-3.94ZM33.13 43H28.3v13h1.99v-4.46h2.84c2.25.13 4.17-1.59 4.3-3.84v-.45A4.053 4.053 0 0 0 33.57 43zm2.28 4.29a2.444 2.444 0 0 1-2.77 2.58H30.3v-5.19h2.34c1.8 0 2.77.97 2.77 2.58v.02ZM46.84 56h2.47l-5.36-7.25L48.87 43h-2.36l-5.27 6.23h-.05V43H39.2v13h1.99v-4.35l1.33-1.53L46.83 56Z"/>
|
||||
<path fill="#3DDC84" d="m46.17 15.2 4.67-8.1c.38-.65.16-1.45-.4-1.85-.22-.16-.49-.25-.8-.26-.5 0-.97.27-1.22.7l-4.75 8.23a28.542 28.542 0 0 0-11.66-2.39c-4.01-.03-7.99.78-11.66 2.39L15.6 5.69c-.26-.46-.74-.71-1.23-.7-.23 0-.46.06-.68.19-.71.41-.89 1.29-.51 1.92l4.67 8.1C9.08 20.23 4.33 29.51 4.02 37h56c-.31-7.49-5.06-16.78-13.83-21.8ZM18 30c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3m28 0c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3" opacity=".6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1022 B |
@@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 2C5.67157 2 5 2.67157 5 3.5V10.2676C4.70583 10.0974 4.36429 10 4 10C2.89543 10 2 10.8954 2 12C2 13.1046 2.89543 14 4 14C5.10457 14 6 13.1046 6 12V6H12V10.2676C11.7058 10.0974 11.3643 10 11 10C9.89543 10 9 10.8954 9 12C9 13.1046 9.89543 14 11 14C12.1046 14 13 13.1046 13 12V3.5C13 2.67157 12.3284 2 11.5 2H6.5ZM12 12C12 11.4477 11.5523 11 11 11C10.4477 11 10 11.4477 10 12C10 12.5523 10.4477 13 11 13C11.5523 13 12 12.5523 12 12ZM5 12C5 11.4477 4.55228 11 4 11C3.44772 11 3 11.4477 3 12C3 12.5523 3.44772 13 4 13C4.55228 13 5 12.5523 5 12ZM12 5H6V3.5C6 3.22386 6.22386 3 6.5 3H11.5C11.7761 3 12 3.22386 12 3.5V5Z" fill="#9AA7B0"/>
|
||||
<path d="M6 3.5C6 3.22386 6.22386 3 6.5 3H11.5C11.7761 3 12 3.22386 12 3.5V5H6V3.5Z" fill="#40B6E0"/>
|
||||
<path d="M12 12C12 12.5523 11.5523 13 11 13C10.4477 13 10 12.5523 10 12C10 11.4477 10.4477 11 11 11C11.5523 11 12 11.4477 12 12Z" fill="#40B6E0"/>
|
||||
<path d="M4 13C4.55228 13 5 12.5523 5 12C5 11.4477 4.55228 11 4 11C3.44772 11 3 11.4477 3 12C3 12.5523 3.44772 13 4 13Z" fill="#40B6E0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,5 @@
|
||||
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.07937 12L2.8805 9.69032H6.2896L7.08647 12H8.4842L5.34357 3.27271H3.82227L0.681641 12H2.07937ZM3.26403 8.58236L4.55096 4.85793H4.61914L5.90607 8.58236H3.26403Z" fill="#9AA7B0"/>
|
||||
<path d="M11.5471 12.1449C12.6294 12.1449 13.2388 11.5951 13.4817 11.1051H13.5328V12H14.7772V7.65339C14.7772 5.74856 13.2772 5.3693 12.2374 5.3693C11.0527 5.3693 9.96183 5.84657 9.53569 7.03975L10.7331 7.31248C10.9206 6.84799 11.3979 6.40055 12.2544 6.40055C13.0769 6.40055 13.4988 6.83094 13.4988 7.57242V7.60225C13.4988 8.06674 13.0215 8.05822 11.8453 8.19458C10.6053 8.33947 9.33541 8.66333 9.33541 10.1505C9.33541 11.4375 10.3027 12.1449 11.5471 12.1449ZM11.824 11.1221C11.1039 11.1221 10.584 10.7983 10.584 10.1676C10.584 9.48577 11.1891 9.24288 11.9263 9.14486C12.3397 9.08947 13.3198 8.97867 13.503 8.79543V9.63918C13.503 10.4148 12.8851 11.1221 11.824 11.1221Z" fill="#9AA7B0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,9 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<polygon fill="#62B543" fill-opacity=".7" points="1 16 16 16 16 9 1 9"/>
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="7 1 3 5 7 5"/>
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="8 1 8 6 3 6 3 8 13 8 13 1"/>
|
||||
<polygon fill="#231F20" fill-opacity=".7" points="0 0 1 0 1 2 3 2 3 0 4 0 4 5 3 5 3 3 1 3 1 5 0 5" transform="translate(3 10)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 663 B |
@@ -0,0 +1,9 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#40B6E0" fill-opacity=".7" d="M8.416 13.8965C8.416 13.7395 8.437 13.3185 8.437 13.1395 8.437 12.3195 8.127 11.9835 7.269 11.9835L7 11.9835 7 11.0155 7.269 11.0155C8.127 11.0155 8.437 10.6685 8.437 9.8485 8.437 9.6695 8.416 9.2505 8.416 9.0915 8.416 8.0195 8.882 7.3465 10.765 7.0005L10.981 7.8405C9.74 8.1885 9.575 8.5135 9.575 9.2815 9.575 9.4925 9.596 9.8385 9.596 10.0595 9.596 10.8795 9.203 11.2785 8.52 11.5005 9.213 11.7305 9.596 12.1205 9.596 12.9405 9.596 13.1615 9.575 13.5075 9.575 13.7185 9.575 14.4855 9.74 14.8115 10.981 15.1585L10.765 16.0005C8.882 15.6525 8.416 14.9795 8.416 13.8965M12.0186 15.1582C13.2596 14.8112 13.4246 14.4852 13.4246 13.7192 13.4246 13.5082 13.4046 13.1612 13.4046 12.9402 13.4046 12.1202 13.7966 11.7202 14.4796 11.5002 13.7876 11.2682 13.4046 10.8802 13.4046 10.0592 13.4046 9.8392 13.4246 9.4922 13.4246 9.2812 13.4246 8.5132 13.2596 8.1882 12.0186 7.8412L12.2356 7.0002C14.1186 7.3462 14.5836 8.0192 14.5836 9.0922 14.5836 9.2502 14.5626 9.6702 14.5626 9.8482 14.5626 10.6692 14.8726 11.0152 15.7316 11.0152L15.9996 11.0152 15.9996 11.9832 15.7316 11.9832C14.8726 11.9832 14.5626 12.3192 14.5626 13.1392 14.5626 13.3182 14.5836 13.7392 14.5836 13.8962 14.5836 14.9792 14.1186 15.6522 12.2356 16.0002L12.0186 15.1582z"/>
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="7 1 3 5 7 5"/>
|
||||
<path fill="#9AA7B0" fill-opacity=".8" d="M10.5957,12.9404 C10.5957,13.0624 10.5847,13.9504 10.5907,13.9754 C10.5907,13.9744 10.5927,13.9734 10.5927,13.9734 C10.6227,13.9734 11.4997,14.2654 11.4997,14.2654 C11.4997,14.2654 12.3717,13.9764 12.4247,13.9404 C12.4177,13.9274 12.4047,13.0624 12.4047,12.9404 C12.4047,12.4914 12.4937,11.9654 12.8087,11.5034 C12.5397,11.1134 12.4047,10.6304 12.4047,10.0594 C12.4047,9.9374 12.4147,9.0494 12.4087,9.0244 C12.4087,9.0254 12.4077,9.0254 12.4077,9.0254 C12.3767,9.0254 11.4997,8.7344 11.4997,8.7344 C11.4997,8.7344 10.6277,9.0234 10.5747,9.0584 C10.5817,9.0724 10.5957,9.9374 10.5957,10.0594 C10.5957,10.5084 10.5057,11.0334 10.1917,11.4964 C10.4597,11.8854 10.5957,12.3684 10.5957,12.9404"/>
|
||||
<path fill="#9AA7B0" fill-opacity=".8" d="M7.416,13.8965 C7.416,13.8125 7.435,13.0285 7.432,12.9905 C7.392,12.9865 6,12.9835 6,12.9835 L6,10.0155 C6,10.0155 7.391,10.0125 7.431,10.0075 C7.435,9.9685 7.416,9.1765 7.416,9.0915 C7.416,6.8825 9.108,6.2885 10.584,6.0165 L11.5,5.8475 L12.416,6.0165 C12.608,6.0515 12.805,6.0935 13,6.1425 L13,1.0005 L8,1.0005 L8,6.0005 L3,6.0005 L3,15.0005 L7.609,15.0005 C7.496,14.6815 7.416,14.3285 7.416,13.8965"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,8 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="7 1 3 5 7 5"/>
|
||||
<polygon fill="#9AA7B0" fill-opacity=".8" points="8 1 8 6 3 6 3 15 13 15 13 1"/>
|
||||
<path fill="#231F20" fill-opacity=".7" d="M5,12 L9,12 L9,11 L5,11 L5,12 Z M5,10 L11,10 L11,9 L5,9 L5,10 Z M5,8 L11,8 L11,7 L5,7 L5,8 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 597 B |
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
|
||||
<path d="M15,5,12,7.25V5a1,1,0,0,0-1-1H3A1,1,0,0,0,2,5v6a1,1,0,0,0,1,1h8a1,1,0,0,0,1-1V8.75L15,11Zm-4.5,5.5h-7v-5h7Z" fill="#9AA7B0" fill-rule="evenodd"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 393 B |