mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-28 01:45:55 +08:00
Add support for moving a Note to another folder
The Folder selection dialog needs a lot of work, but it's a start.
This commit is contained in:
@ -81,6 +81,19 @@ class GitNoteRepository {
|
||||
return NoteRepoResult(noteFilePath: newFullPath, error: false);
|
||||
}
|
||||
|
||||
Future<NoteRepoResult> moveNote(
|
||||
String oldFullPath,
|
||||
String newFullPath,
|
||||
) async {
|
||||
// FIXME: This is a hacky way of adding the changes, ideally we should be calling rm + add or something
|
||||
await _gitRepo.add(".");
|
||||
await _gitRepo.commit(
|
||||
message: "Note Moved",
|
||||
);
|
||||
|
||||
return NoteRepoResult(noteFilePath: newFullPath, error: false);
|
||||
}
|
||||
|
||||
Future<NoteRepoResult> removeNote(String noteFilePath) async {
|
||||
var pathSpec = noteFilePath.replaceFirst(gitDirPath, "").substring(1);
|
||||
|
||||
|
@ -172,6 +172,22 @@ class Note with ChangeNotifier implements Comparable<Note> {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool move(NotesFolder destFolder) {
|
||||
var destPath = p.join(destFolder.folderPath, fileName);
|
||||
if (File(destPath).existsSync()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File(filePath).renameSync(destPath);
|
||||
|
||||
parent.remove(this);
|
||||
parent = destFolder;
|
||||
destFolder.add(this);
|
||||
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => _filePath.hashCode;
|
||||
|
||||
|
@ -4,7 +4,7 @@ import 'package:gitjournal/core/note.dart';
|
||||
import 'package:gitjournal/widgets/note_viewer.dart';
|
||||
|
||||
typedef NoteCallback = void Function(Note);
|
||||
enum DropDownChoices { Rename }
|
||||
enum DropDownChoices { Rename, MoveToFolder }
|
||||
|
||||
class MarkdownEditor extends StatefulWidget {
|
||||
final Note note;
|
||||
@ -12,6 +12,7 @@ class MarkdownEditor extends StatefulWidget {
|
||||
final NoteCallback noteEditorChooserSelected;
|
||||
final NoteCallback exitEditorSelected;
|
||||
final NoteCallback renameNoteSelected;
|
||||
final NoteCallback moveNoteToFolderSelected;
|
||||
final bool autofocusOnEditor;
|
||||
|
||||
MarkdownEditor({
|
||||
@ -21,6 +22,7 @@ class MarkdownEditor extends StatefulWidget {
|
||||
@required this.noteEditorChooserSelected,
|
||||
@required this.exitEditorSelected,
|
||||
@required this.renameNoteSelected,
|
||||
@required this.moveNoteToFolderSelected,
|
||||
this.autofocusOnEditor = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -108,8 +110,17 @@ class MarkdownEditorState extends State<MarkdownEditor> {
|
||||
),
|
||||
PopupMenuButton<DropDownChoices>(
|
||||
onSelected: (DropDownChoices choice) {
|
||||
_updateNote();
|
||||
widget.renameNoteSelected(note);
|
||||
switch (choice) {
|
||||
case DropDownChoices.Rename:
|
||||
_updateNote();
|
||||
widget.renameNoteSelected(note);
|
||||
return;
|
||||
|
||||
case DropDownChoices.MoveToFolder:
|
||||
_updateNote();
|
||||
widget.moveNoteToFolderSelected(note);
|
||||
return;
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) =>
|
||||
<PopupMenuEntry<DropDownChoices>>[
|
||||
@ -117,6 +128,10 @@ class MarkdownEditorState extends State<MarkdownEditor> {
|
||||
value: DropDownChoices.Rename,
|
||||
child: Text('Edit File Name'),
|
||||
),
|
||||
const PopupMenuItem<DropDownChoices>(
|
||||
value: DropDownChoices.MoveToFolder,
|
||||
child: Text('Move to Folder'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
@ -4,7 +4,7 @@ import 'package:gitjournal/core/note.dart';
|
||||
import 'package:gitjournal/core/note_data_serializers.dart';
|
||||
|
||||
typedef NoteCallback = void Function(Note);
|
||||
enum DropDownChoices { Rename }
|
||||
enum DropDownChoices { Rename, MoveToFolder }
|
||||
|
||||
class RawEditor extends StatefulWidget {
|
||||
final Note note;
|
||||
@ -12,6 +12,7 @@ class RawEditor extends StatefulWidget {
|
||||
final NoteCallback noteEditorChooserSelected;
|
||||
final NoteCallback exitEditorSelected;
|
||||
final NoteCallback renameNoteSelected;
|
||||
final NoteCallback moveNoteToFolderSelected;
|
||||
|
||||
RawEditor({
|
||||
Key key,
|
||||
@ -20,6 +21,7 @@ class RawEditor extends StatefulWidget {
|
||||
@required this.noteEditorChooserSelected,
|
||||
@required this.exitEditorSelected,
|
||||
@required this.renameNoteSelected,
|
||||
@required this.moveNoteToFolderSelected,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -88,8 +90,17 @@ class RawEditorState extends State<RawEditor> {
|
||||
),
|
||||
PopupMenuButton<DropDownChoices>(
|
||||
onSelected: (DropDownChoices choice) {
|
||||
_updateNote();
|
||||
widget.renameNoteSelected(note);
|
||||
switch (choice) {
|
||||
case DropDownChoices.Rename:
|
||||
_updateNote();
|
||||
widget.renameNoteSelected(note);
|
||||
return;
|
||||
|
||||
case DropDownChoices.MoveToFolder:
|
||||
_updateNote();
|
||||
widget.moveNoteToFolderSelected(note);
|
||||
return;
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) =>
|
||||
<PopupMenuEntry<DropDownChoices>>[
|
||||
@ -97,6 +108,10 @@ class RawEditorState extends State<RawEditor> {
|
||||
value: DropDownChoices.Rename,
|
||||
child: Text('Edit File Name'),
|
||||
),
|
||||
const PopupMenuItem<DropDownChoices>(
|
||||
value: DropDownChoices.MoveToFolder,
|
||||
child: Text('Move to Folder'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
@ -8,10 +8,9 @@ import 'package:gitjournal/editors/raw_editor.dart';
|
||||
import 'package:gitjournal/state_container.dart';
|
||||
import 'package:gitjournal/core/note_data_serializers.dart';
|
||||
import 'package:gitjournal/utils.dart';
|
||||
import 'package:gitjournal/widgets/folder_selection_dialog.dart';
|
||||
import 'package:gitjournal/widgets/rename_dialog.dart';
|
||||
|
||||
enum NoteEditorDropDownChoices { Discard, SwitchEditor }
|
||||
|
||||
class NoteEditor extends StatefulWidget {
|
||||
final Note note;
|
||||
final NotesFolder notesFolder;
|
||||
@ -73,6 +72,7 @@ class NoteEditorState extends State<NoteEditor> {
|
||||
noteEditorChooserSelected: _noteEditorChooserSelected,
|
||||
exitEditorSelected: _exitEditorSelected,
|
||||
renameNoteSelected: _renameNoteSelected,
|
||||
moveNoteToFolderSelected: _moveNoteToFolderSelected,
|
||||
autofocusOnEditor: _isNewNote,
|
||||
);
|
||||
case EditorType.Raw:
|
||||
@ -83,6 +83,7 @@ class NoteEditorState extends State<NoteEditor> {
|
||||
noteEditorChooserSelected: _noteEditorChooserSelected,
|
||||
exitEditorSelected: _exitEditorSelected,
|
||||
renameNoteSelected: _renameNoteSelected,
|
||||
moveNoteToFolderSelected: _moveNoteToFolderSelected,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@ -227,4 +228,15 @@ class NoteEditorState extends State<NoteEditor> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void _moveNoteToFolderSelected(Note note) async {
|
||||
var destFolder = await showDialog<NotesFolder>(
|
||||
context: context,
|
||||
builder: (context) => FolderSelectionDialog(),
|
||||
);
|
||||
if (destFolder != null) {
|
||||
final stateContainer = StateContainer.of(context);
|
||||
stateContainer.moveNote(note, destFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ class StateContainerState extends State<StateContainer> {
|
||||
});
|
||||
}
|
||||
|
||||
void renameFolder(NotesFolder folder, String newFolderName) async {
|
||||
void renameFolder(NotesFolder folder, String newFolderName) {
|
||||
var oldFolderPath = folder.folderPath;
|
||||
folder.rename(newFolderName);
|
||||
|
||||
@ -150,7 +150,7 @@ class StateContainerState extends State<StateContainer> {
|
||||
});
|
||||
}
|
||||
|
||||
void renameNote(Note note, String newFileName) async {
|
||||
void renameNote(Note note, String newFileName) {
|
||||
var oldNotePath = note.filePath;
|
||||
note.rename(newFileName);
|
||||
|
||||
@ -159,6 +159,15 @@ class StateContainerState extends State<StateContainer> {
|
||||
});
|
||||
}
|
||||
|
||||
void moveNote(Note note, NotesFolder destFolder) {
|
||||
var oldNotePath = note.filePath;
|
||||
note.move(destFolder);
|
||||
|
||||
_gitRepo.moveNote(oldNotePath, note.filePath).then((NoteRepoResult _) {
|
||||
syncNotes();
|
||||
});
|
||||
}
|
||||
|
||||
void addNote(Note note) {
|
||||
insertNote(0, note);
|
||||
}
|
||||
|
31
lib/widgets/folder_selection_dialog.dart
Normal file
31
lib/widgets/folder_selection_dialog.dart
Normal file
@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gitjournal/core/notes_folder.dart';
|
||||
import 'package:gitjournal/widgets/folder_tree_view.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
typedef NoteFolderCallback = void Function(NotesFolder);
|
||||
|
||||
class FolderSelectionDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final notesFolder = Provider.of<NotesFolder>(context);
|
||||
|
||||
var body = Container(
|
||||
width: double.maxFinite,
|
||||
child: FolderTreeView(
|
||||
rootFolder: notesFolder,
|
||||
onFolderEntered: (NotesFolder destFolder) {
|
||||
Navigator.of(context).pop(destFolder);
|
||||
},
|
||||
longPressAllowed: false,
|
||||
),
|
||||
);
|
||||
|
||||
return AlertDialog(
|
||||
title: const Text('Select a Folder'),
|
||||
content: body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Add the previously as a radio button selected Folder
|
@ -10,17 +10,21 @@ class FolderTreeView extends StatefulWidget {
|
||||
final FolderSelectedCallback onFolderSelected;
|
||||
final Function onFolderUnselected;
|
||||
final FolderSelectedCallback onFolderEntered;
|
||||
final bool longPressAllowed;
|
||||
|
||||
FolderTreeView({
|
||||
Key key,
|
||||
@required this.rootFolder,
|
||||
@required this.onFolderSelected,
|
||||
@required this.onFolderUnselected,
|
||||
@required this.onFolderEntered,
|
||||
this.onFolderSelected = _doNothing,
|
||||
this.onFolderUnselected = _doNothing,
|
||||
this.longPressAllowed = true,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
FolderTreeViewState createState() => FolderTreeViewState();
|
||||
|
||||
static void _doNothing(NotesFolder f) {}
|
||||
}
|
||||
|
||||
class FolderTreeViewState extends State<FolderTreeView> {
|
||||
@ -43,6 +47,7 @@ class FolderTreeViewState extends State<FolderTreeView> {
|
||||
}
|
||||
},
|
||||
onLongPress: (folder) {
|
||||
if (!widget.longPressAllowed) return;
|
||||
setState(() {
|
||||
inSelectionMode = true;
|
||||
selectedFolder = folder;
|
||||
|
Reference in New Issue
Block a user