feat: 로컬 파일 복사/잘라내기/붙여넣기 기능 구현

This commit is contained in:
2026-01-05 01:29:02 +09:00
parent e77dae403c
commit 5be5124b47

View File

@@ -3,6 +3,12 @@ package be.gyu.android.file.explorer;
// ... (imports)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
@@ -14,103 +20,94 @@ public class MainActivity extends AppCompatActivity implements FileAdapter.OnIte
private List<FileItem> clipboard = new ArrayList<>();
private boolean isCutOperation = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... (onCreate remains the same)
}
// ... (Action Mode methods)
private final ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu_local, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
MenuItem renameItem = menu.findItem(R.id.action_rename);
renameItem.setVisible(fileAdapter.getSelectedItemCount() == 1);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.action_copy) {
copyToClipboard();
mode.finish();
return true;
} else if (itemId == R.id.action_cut) {
cutToClipboard();
mode.finish();
return true;
} else if (itemId == R.id.action_delete) {
showDeleteConfirmationDialog();
mode.finish();
return true;
} else if (itemId == R.id.action_rename) {
showRenameDialog();
mode.finish();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
fileAdapter.clearSelections();
}
};
private void copyToClipboard() {
clipboard.clear();
clipboard.addAll(fileAdapter.getSelectedItems());
isCutOperation = false;
Toast.makeText(this, clipboard.size() + " items copied", Toast.LENGTH_SHORT).show();
invalidateOptionsMenu(); // To show paste button
}
private void cutToClipboard() {
clipboard.clear();
clipboard.addAll(fileAdapter.getSelectedItems());
isCutOperation = true;
Toast.makeText(this, clipboard.size() + " items cut", Toast.LENGTH_SHORT).show();
invalidateOptionsMenu(); // To show paste button
}
// ... (Delete and Rename methods)
// ... (onCreate and Action Mode methods)
// --- Menu Methods ---
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
// Show paste button only if there's something in the clipboard
MenuItem pasteItem = menu.findItem(R.id.action_paste);
pasteItem.setVisible(!clipboard.isEmpty());
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// Show paste button only if there's something in the clipboard and not in remote mode
MenuItem pasteItem = menu.findItem(R.id.action_paste);
pasteItem.setVisible(!clipboard.isEmpty() && !isRemoteMode);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.action_paste) {
// TODO: Implement paste logic
Toast.makeText(this, "Paste clicked", Toast.LENGTH_SHORT).show();
return true;
} else if (itemId == R.id.select_storage) {
showStorageSelectionDialog();
return true;
} else if (itemId == R.id.remote_storage) {
Intent intent = new Intent(this, RemoteStorageActivity.class);
startActivity(intent);
pasteFiles();
return true;
}
// ... (other menu items)
return super.onOptionsItemSelected(item);
}
// --- File Operation Methods ---
private void pasteFiles() {
if (clipboard.isEmpty()) return;
Toast.makeText(this, "Pasting " + clipboard.size() + " items...", Toast.LENGTH_SHORT).show();
new Thread(() -> {
int successCount = 0;
for (FileItem item : clipboard) {
File sourceFile = new File(item.getPath());
File destFile = new File(currentDirectory, sourceFile.getName());
try {
if (isCutOperation) {
if (sourceFile.renameTo(destFile)) {
successCount++;
}
} else {
copyFileOrDirectory(sourceFile, destFile);
successCount++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
int finalSuccessCount = successCount;
runOnUiThread(() -> {
Toast.makeText(this, finalSuccessCount + " items pasted.", Toast.LENGTH_SHORT).show();
clipboard.clear();
isCutOperation = false;
invalidateOptionsMenu(); // Hide paste button
loadFiles(currentDirectory); // Refresh list
});
}).start();
}
private void copyFileOrDirectory(File source, File dest) throws IOException {
if (source.isDirectory()) {
if (!dest.exists()) {
dest.mkdirs();
}
String[] files = source.list();
if (files != null) {
for (String file : files) {
copyFileOrDirectory(new File(source, file), new File(dest, file));
}
}
} else {
try (InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(dest)) {
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
}
}
}
// ... (rest of the file remains the same)
}