🐛 修复文件树由于缓存问题导致新增的文件无法被显示 🚩初步添加文件树菜单
This commit is contained in:
parent
9037223584
commit
2c3416fde5
@ -76,6 +76,23 @@ public abstract class AbstractMenuBuilder<B, T> {
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单项
|
||||
*
|
||||
* @param label 菜单项名称
|
||||
* @param eventHandler 事件
|
||||
* @param visible 是否可见
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenuItem(String label, EventHandler<ActionEvent> eventHandler, boolean visible) {
|
||||
MenuItem menuItem = new MenuItem(label);
|
||||
menuItem.setOnAction(eventHandler);
|
||||
menuItem.setVisible(visible);
|
||||
menuItems.put(label, menuItem);
|
||||
getItems().add(menuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单选菜单项
|
||||
*
|
||||
@ -141,6 +158,20 @@ public abstract class AbstractMenuBuilder<B, T> {
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单
|
||||
*
|
||||
* @param menu 菜单
|
||||
* @param visible 是否隐藏
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addMenu(Menu menu, boolean visible) {
|
||||
menu.setVisible(visible);
|
||||
menuItems.put(menu.getText(), menu);
|
||||
getItems().add(menu);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加分割线
|
||||
@ -166,6 +197,19 @@ public abstract class AbstractMenuBuilder<B, T> {
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分割线
|
||||
*
|
||||
* @param visible 是否可见
|
||||
* @return 建造者
|
||||
*/
|
||||
public B addSeparatorMenuItem(boolean visible) {
|
||||
SeparatorMenuItem separatorMenuItem = new SeparatorMenuItem();
|
||||
separatorMenuItem.setVisible(visible);
|
||||
getItems().add(separatorMenuItem);
|
||||
return getBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build menu
|
||||
*
|
||||
|
||||
@ -23,6 +23,10 @@ public class TextConstants {
|
||||
* 文件文本常量
|
||||
*/
|
||||
public static final String FILE = "FILE";
|
||||
/**
|
||||
* 文件夹
|
||||
*/
|
||||
public static final String FOLDER = "FOLDER";
|
||||
|
||||
/**
|
||||
* 构建文本常量
|
||||
@ -139,6 +143,16 @@ public class TextConstants {
|
||||
*/
|
||||
public static final String NEW_FILE = "NEW_FILE";
|
||||
|
||||
/**
|
||||
* 新建文件夹
|
||||
*/
|
||||
public static final String NEW_DIRECTORY = "NEW_DIRECTORY";
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public static final String DELETE = "DELETE";
|
||||
|
||||
/**
|
||||
* 行文本常量
|
||||
*/
|
||||
|
||||
@ -37,6 +37,8 @@ public class FileUtil {
|
||||
|
||||
private static final String MAC = "mac";
|
||||
|
||||
private static final String PATH = "path";
|
||||
|
||||
static {
|
||||
try {
|
||||
MESSAGE_DIGEST_SHA_256 = MessageDigest.getInstance("SHA-256");
|
||||
@ -189,9 +191,10 @@ public class FileUtil {
|
||||
if (Objects.isNull(dirFileModels) || dirFileModels.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
File rootDir = new File((String) dirFileModels.get(PATH));
|
||||
DirFileModel dirFileModel = new DirFileModel(
|
||||
(String) dirFileModels.get("path"),
|
||||
(String) dirFileModels.get("name"), new ArrayList<>(),
|
||||
rootDir.getAbsolutePath(),
|
||||
rootDir.getName(), new ArrayList<>(),
|
||||
new FontIcon(FOLDER),
|
||||
new FontIcon(FOLDER_OPEN), (Boolean) dirFileModels.get("open"));
|
||||
Optional<Object> o = Optional.ofNullable(dirFileModels.get("childFile"));
|
||||
@ -199,16 +202,29 @@ public class FileUtil {
|
||||
return null;
|
||||
}
|
||||
List<Map<String, Object>> childFile = (List<Map<String, Object>>) o.get();
|
||||
for (Map<String, Object> map : childFile) {
|
||||
Object obj = map.get("childFile");
|
||||
if (obj == null) {
|
||||
dirFileModel.getChildFile().add(new DirFileModel(
|
||||
(String) map.get("path"), (String) map.get("name"), null,
|
||||
getIconCorrespondingToFileName((String) map.get("name")),
|
||||
null));
|
||||
File[] files = rootDir.listFiles();
|
||||
if (files == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (File f : files) {
|
||||
if (f.isDirectory()) {
|
||||
Optional<Map<String, Object>> first = childFile
|
||||
.stream()
|
||||
.filter(map -> map.get(PATH).equals(f.getAbsolutePath())).findFirst();
|
||||
DirFileModel childDirFileModel;
|
||||
if (first.isPresent()) {
|
||||
childDirFileModel = getDirFileModel(first.get());
|
||||
} else {
|
||||
DirFileModel childDirFileModel = getDirFileModel(map);
|
||||
childDirFileModel = getDirFileModel(f);
|
||||
}
|
||||
dirFileModel.getChildFile().add(childDirFileModel);
|
||||
} else {
|
||||
// 在此监测文件后缀,设置对应的图标
|
||||
dirFileModel.getChildFile().add(new DirFileModel(
|
||||
f.getAbsolutePath(), f.getName(), null,
|
||||
getIconCorrespondingToFileName(f.getName()),
|
||||
null));
|
||||
}
|
||||
}
|
||||
return dirFileModel;
|
||||
@ -365,17 +381,18 @@ public class FileUtil {
|
||||
* @param folder the folder in which to open the terminal
|
||||
*/
|
||||
public static void openTerminal(File folder) {
|
||||
if (folder.exists() && folder.isDirectory()) {
|
||||
if (!folder.exists()) {
|
||||
return;
|
||||
}
|
||||
if (folder.isFile()) {
|
||||
folder = folder.getParentFile();
|
||||
}
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
|
||||
ProcessBuilder processBuilder = getProcessBuilder(folder, os);
|
||||
try {
|
||||
processBuilder.start();
|
||||
} catch (IOException e) {
|
||||
PopUpUtil.errorAlert("打开失败", "打开于终端失败", "错误原因" + e.getMessage(), null, null);
|
||||
}
|
||||
} else {
|
||||
logger.info("文件夹不存在或者不是文件夹");
|
||||
PopUpUtil.errorAlert("打开失败", "打开于终端失败", "错误原因:" + e.getMessage(), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,5 +417,18 @@ public class FileUtil {
|
||||
}
|
||||
return processBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file at the specified path.
|
||||
*
|
||||
* @param path The path to the file to be created.
|
||||
*/
|
||||
public static void createFile(Path path) {
|
||||
try {
|
||||
Files.createFile(path);
|
||||
} catch (IOException e) {
|
||||
logger.error("创建文件失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -128,19 +128,18 @@ public class TabUtil {
|
||||
* @param tab 标签页组件
|
||||
*/
|
||||
private static void handleRenameTab(CenterTab tab) {
|
||||
TextField textField = new TextField(tab.getText());
|
||||
textField.getStyleClass().add("tab-title-editable");
|
||||
// 临时记录标签页名称
|
||||
String tempName = tab.getText();
|
||||
TextField textField = new TextField(tempName);
|
||||
textField.getStyleClass().add("tab-title-editable");
|
||||
// 清空标签页名称
|
||||
tab.setText("");
|
||||
|
||||
// 监听 Enter 键,完成编辑
|
||||
textField.setOnKeyPressed(event -> {
|
||||
if (event.getCode() == KeyCode.ENTER) {
|
||||
String newTabName = textField.getText();
|
||||
// 检查是否存在相同名称的标签页
|
||||
if (isTabNameExists(newTabName)) {
|
||||
if (tabNameExists(newTabName)) {
|
||||
|
||||
// 显示弹窗并提示用户更换名称
|
||||
showDuplicateNameAlert(newTabName);
|
||||
@ -162,7 +161,7 @@ public class TabUtil {
|
||||
textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
String newTabName = textField.getText();
|
||||
// 检查是否存在相同名称的标签页
|
||||
if (isTabNameExists(newTabName)) {
|
||||
if (tabNameExists(newTabName)) {
|
||||
// 恢复原始名称
|
||||
tab.setText(tempName);
|
||||
|
||||
@ -191,7 +190,7 @@ public class TabUtil {
|
||||
* @param newTabName 要检查的新标签页名称
|
||||
* @return 如果存在具有相同名称的标签页,则返回 true;否则返回 false
|
||||
*/
|
||||
private static boolean isTabNameExists(String newTabName) {
|
||||
private static boolean tabNameExists(String newTabName) {
|
||||
CenterTabPane tabPane = CenterTabPane.getInstance();
|
||||
return tabPane.getTabs().stream()
|
||||
.anyMatch(tab -> tab.getText().equals(newTabName));
|
||||
@ -245,6 +244,22 @@ public class TabUtil {
|
||||
public static void addNewFileTab() {
|
||||
// 创建一个新的文本编辑区
|
||||
TextCodeArea textArea = new TextCodeArea();
|
||||
// 创建标签页
|
||||
CenterTab centerTab = new CenterTab(
|
||||
generateDefaultName(),
|
||||
textArea);
|
||||
// 将Tab页添加到TabPane中
|
||||
CenterTabPaneManager.getInstance().addNewTab(centerTab);
|
||||
// 更新编码信息
|
||||
BottomStatusBoxManager.getInstance().updateEncodingLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the default name for a new tab.
|
||||
*
|
||||
* @return The default name for a new tab.
|
||||
*/
|
||||
private static String generateDefaultName() {
|
||||
// 设定初始索引
|
||||
int index = 1;
|
||||
StringBuilder tabTitle = new StringBuilder();
|
||||
@ -275,14 +290,7 @@ public class TabUtil {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 创建标签页
|
||||
CenterTab centerTab = new CenterTab(
|
||||
tabTitle.toString(),
|
||||
textArea);
|
||||
// 将Tab页添加到TabPane中
|
||||
CenterTabPaneManager.getInstance().addNewTab(centerTab);
|
||||
// 更新编码信息
|
||||
BottomStatusBoxManager.getInstance().updateEncodingLabel();
|
||||
return tabTitle.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -51,9 +51,13 @@ public class OpenDirectory implements EventHandler<ActionEvent> {
|
||||
CACHE_MANAGER.addCache(cache);
|
||||
}
|
||||
flushDirSidebar(file);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the directory sidebar with the given file.
|
||||
*
|
||||
* @param file the file to be converted into an entity class
|
||||
*/
|
||||
public void flushDirSidebar(File file) {
|
||||
// 将文件转为实体类
|
||||
DirFileModel dirFileModel = FileUtil.getDirFileModel(file);
|
||||
|
||||
@ -23,6 +23,7 @@ public class DirFileModel {
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
@JsonIgnore
|
||||
private String name;
|
||||
|
||||
/**
|
||||
@ -45,13 +46,6 @@ public class DirFileModel {
|
||||
*/
|
||||
private boolean isOpen;
|
||||
|
||||
public DirFileModel(String path, String name, List<DirFileModel> childFile, boolean isOpen) {
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.childFile = childFile;
|
||||
this.isOpen = isOpen;
|
||||
}
|
||||
|
||||
public DirFileModel(String path, String name, List<DirFileModel> childFile, Node iconIsNotSelected, Node iconIsSelected) {
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
|
||||
@ -103,13 +103,13 @@ public class DirectorySidebarManager {
|
||||
*/
|
||||
public void setTreeView(DirFileModel dirFileModel) {
|
||||
TreeItem<DirFileModel> rootItem = new TreeItem<>(dirFileModel, dirFileModel.getIconIsNotSelected());
|
||||
|
||||
DIRECTORY_SIDEBAR_PANE.setRoot(rootItem);
|
||||
rootItem.expandedProperty().addListener(getTreeItemListener(rootItem));
|
||||
rootItem.setExpanded(dirFileModel.isOpen());
|
||||
expandFolder(dirFileModel, rootItem);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 递归展开 dirFileModel
|
||||
*
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
package org.jcnc.jnotepad.ui.views.manager;
|
||||
|
||||
import javafx.scene.control.Menu;
|
||||
import org.jcnc.jnotepad.api.core.views.menu.builder.MenuBuilder;
|
||||
import org.jcnc.jnotepad.app.utils.ClipboardUtil;
|
||||
import org.jcnc.jnotepad.app.utils.FileUtil;
|
||||
import org.jcnc.jnotepad.app.utils.NotificationUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.jcnc.jnotepad.app.common.constants.TextConstants.*;
|
||||
|
||||
/**
|
||||
* 菜单管理类
|
||||
*
|
||||
* @author gewuyou
|
||||
*/
|
||||
public class MenuManager {
|
||||
|
||||
private MenuManager() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a copy menu for the given file.
|
||||
*
|
||||
* @param file the file to generate the copy menu for
|
||||
* @return the generated copy menu
|
||||
*/
|
||||
public static Menu getCopyMenu(File file) {
|
||||
return new MenuBuilder(COPY)
|
||||
.addMenuItem(FILE_NAME, e -> {
|
||||
ClipboardUtil.writeTextToClipboard(file.getName());
|
||||
NotificationUtil.infoNotification("已复制文件名!");
|
||||
})
|
||||
.addMenuItem(FILE_PATH, e -> {
|
||||
ClipboardUtil.writeTextToClipboard(file.getAbsolutePath());
|
||||
NotificationUtil.infoNotification("已复制文件路径!");
|
||||
})
|
||||
.addMenuItem(FOLDER_PATH, e -> {
|
||||
ClipboardUtil.writeTextToClipboard(file.getParent());
|
||||
NotificationUtil.infoNotification("已复制所在文件夹!");
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the open menu for a given file.
|
||||
*
|
||||
* @param file the file for which to retrieve the open menu
|
||||
* @return the open menu for the given file
|
||||
*/
|
||||
public static Menu getOpenMenu(File file) {
|
||||
return new MenuBuilder(OPEN_ON)
|
||||
.addMenuItem(EXPLORER, e -> FileUtil.openExplorer(file))
|
||||
.addMenuItem(TERMINAL, e -> FileUtil.openTerminal(file))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Menu.
|
||||
*
|
||||
* @return a new Menu object
|
||||
*/
|
||||
public static Menu getNewMenu() {
|
||||
return new MenuBuilder(NEW)
|
||||
.addMenuItem(FILE, e -> {
|
||||
})
|
||||
.addMenuItem(FOLDER, e -> {
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,12 +1,19 @@
|
||||
package org.jcnc.jnotepad.ui.views.root.center.main.center.directory;
|
||||
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.control.TreeView;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import org.jcnc.jnotepad.api.core.views.menu.builder.ContextMenuBuilder;
|
||||
import org.jcnc.jnotepad.model.entity.DirFileModel;
|
||||
import org.jcnc.jnotepad.ui.views.manager.DirectorySidebarManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.MenuManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.jcnc.jnotepad.app.common.constants.TextConstants.OPEN;
|
||||
import static org.jcnc.jnotepad.app.utils.TabUtil.openFileToTab;
|
||||
|
||||
|
||||
@ -23,23 +30,64 @@ public class DirectorySidebarPane extends TreeView<DirFileModel> {
|
||||
|
||||
private static final int CLICK_COUNT = 2;
|
||||
|
||||
private final DirectorySidebarManager directorySidebarManager = DirectorySidebarManager.getInstance();
|
||||
|
||||
private ContextMenu contextMenu;
|
||||
|
||||
private DirectorySidebarPane() {
|
||||
initMouseClickEvent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the mouse click event for the Java function.
|
||||
*/
|
||||
private void initMouseClickEvent() {
|
||||
this.setOnMouseClicked(mouseEvent -> {
|
||||
if (mouseEvent.getClickCount() == CLICK_COUNT) {
|
||||
TreeItem<DirFileModel> item = DirectorySidebarPane.this.getSelectionModel().getSelectedItem();
|
||||
if (Objects.isNull(item)) {
|
||||
return;
|
||||
}
|
||||
if (mouseEvent.getClickCount() == CLICK_COUNT) {
|
||||
File file = new File(item.getValue().getPath());
|
||||
|
||||
if (!file.isFile()) {
|
||||
return;
|
||||
}
|
||||
openFileToTab(file);
|
||||
}
|
||||
if (!Objects.isNull(contextMenu)) {
|
||||
contextMenu.hide();
|
||||
}
|
||||
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
|
||||
updateContextMenu(mouseEvent, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void updateContextMenu(MouseEvent mouseEvent, TreeItem<DirFileModel> item) {
|
||||
createContextMenu(item);
|
||||
contextMenu.show(this, mouseEvent.getScreenX(), mouseEvent.getScreenY());
|
||||
}
|
||||
|
||||
private void createContextMenu(TreeItem<DirFileModel> item) {
|
||||
ContextMenuBuilder builder = new ContextMenuBuilder();
|
||||
boolean isFile = !DirFileModel.isDirectoryByDirFileModel(item.getValue());
|
||||
File file = new File(item.getValue().getPath());
|
||||
contextMenu = builder
|
||||
.addMenuItem(OPEN, e -> openFileToTab(file), isFile)
|
||||
.addSeparatorMenuItem(isFile)
|
||||
.addMenu(MenuManager.getNewMenu(), !isFile)
|
||||
// .addSeparatorMenuItem()
|
||||
// .addMenuItem(RENAME, e -> directorySidebarManager.rename(file))
|
||||
// .addMenuItem(DELETE, e -> directorySidebarManager.delete(file))
|
||||
// .addSeparatorMenuItem(isFile)
|
||||
.addMenu(MenuManager.getCopyMenu(file), isFile)
|
||||
.addSeparatorMenuItem(isFile)
|
||||
.addMenu(MenuManager.getOpenMenu(file))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
public static DirectorySidebarPane getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@ -8,12 +8,14 @@ import javafx.scene.control.CheckMenuItem;
|
||||
import javafx.scene.control.Tab;
|
||||
import org.fxmisc.flowless.VirtualizedScrollPane;
|
||||
import org.jcnc.jnotepad.api.core.views.menu.builder.ContextMenuBuilder;
|
||||
import org.jcnc.jnotepad.api.core.views.menu.builder.MenuBuilder;
|
||||
import org.jcnc.jnotepad.app.utils.*;
|
||||
import org.jcnc.jnotepad.app.utils.FileUtil;
|
||||
import org.jcnc.jnotepad.app.utils.LoggerUtil;
|
||||
import org.jcnc.jnotepad.app.utils.TabUtil;
|
||||
import org.jcnc.jnotepad.controller.config.UserConfigController;
|
||||
import org.jcnc.jnotepad.ui.component.module.TextCodeArea;
|
||||
import org.jcnc.jnotepad.ui.views.manager.BottomStatusBoxManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.CenterTabPaneManager;
|
||||
import org.jcnc.jnotepad.ui.views.manager.MenuManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
@ -163,20 +165,7 @@ public class CenterTab extends Tab {
|
||||
)
|
||||
.addSeparatorMenuItem(this.relevancePropertyProperty())
|
||||
.addMenu(
|
||||
new MenuBuilder(COPY)
|
||||
.addMenuItem(FILE_NAME, e -> {
|
||||
ClipboardUtil.writeTextToClipboard(file.getName());
|
||||
NotificationUtil.infoNotification("已复制文件名!");
|
||||
})
|
||||
.addMenuItem(FILE_PATH, e -> {
|
||||
ClipboardUtil.writeTextToClipboard(file.getAbsolutePath());
|
||||
NotificationUtil.infoNotification("已复制文件路径!");
|
||||
})
|
||||
.addMenuItem(FOLDER_PATH, e -> {
|
||||
ClipboardUtil.writeTextToClipboard(file.getParent());
|
||||
NotificationUtil.infoNotification("已复制所在文件夹!");
|
||||
})
|
||||
.build()
|
||||
MenuManager.getCopyMenu(file)
|
||||
, this.relevancePropertyProperty()
|
||||
)
|
||||
.addSeparatorMenuItem()
|
||||
@ -184,10 +173,7 @@ public class CenterTab extends Tab {
|
||||
.addMenuItem(SAVE_AS, e -> TabUtil.saveAsFile(this), this.relevancePropertyProperty())
|
||||
.addMenuItem(RENAME, e -> TabUtil.rename(this))
|
||||
.addSeparatorMenuItem(this.relevancePropertyProperty())
|
||||
.addMenu(new MenuBuilder(OPEN_ON)
|
||||
.addMenuItem(EXPLORER, e -> FileUtil.openExplorer(file))
|
||||
.addMenuItem(TERMINAL, e -> FileUtil.openTerminal(file.getParentFile()))
|
||||
.build(), this.relevancePropertyProperty())
|
||||
.addMenu(MenuManager.getOpenMenu(file), this.relevancePropertyProperty())
|
||||
.addSeparatorMenuItem()
|
||||
.addCheckMenuItem(FIXED_TAB,
|
||||
e -> centerTabPaneManager.updateTabPinnedState(this))
|
||||
@ -197,6 +183,7 @@ public class CenterTab extends Tab {
|
||||
.build());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存选中的文件标签页
|
||||
*/
|
||||
|
||||
@ -41,5 +41,5 @@ CLOSE_OTHER_TABS=关闭其他标签页
|
||||
FIXED_TAB=固定标签页
|
||||
READ_ONLY=只读
|
||||
OPEN_ON=打开于
|
||||
|
||||
FOLDER=文件夹
|
||||
|
||||
|
||||
@ -41,3 +41,4 @@ CLOSE_OTHER_TABS=Close Other Tabs
|
||||
FIXED_TAB=Fixed Tab
|
||||
READ_ONLY=Read Only
|
||||
OPEN_ON=Open On
|
||||
FOLDER=Folder
|
||||
@ -41,3 +41,4 @@ CLOSE_OTHER_TABS=关闭其他标签页
|
||||
FIXED_TAB=固定标签页
|
||||
READ_ONLY=只读
|
||||
OPEN_ON=打开于
|
||||
FOLDER=文件夹
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user