Create new note when clicking on non existing Wiki Link

Fixes #240
This commit is contained in:
Vishesh Handa
2020-10-22 23:57:53 +02:00
parent f1ccae1db0
commit bc06efc446
7 changed files with 81 additions and 6 deletions

View File

@ -269,6 +269,7 @@ widgets:
failed: Purchase Failed failed: Purchase Failed
NoteViewer: NoteViewer:
linkNotFound: Link '{}' not found linkNotFound: Link '{}' not found
linkInvalid: Link '{}' is invalid.
FolderSelectionDialog: FolderSelectionDialog:
title: Select a Folder title: Select a Folder

View File

@ -9,6 +9,7 @@
- text: "Add Shortcuts support in iOS - #262" - text: "Add Shortcuts support in iOS - #262"
image: ios_shortcuts.png image: ios_shortcuts.png
- text: "Custom SSH keys with passwords can now be used - #227" - text: "Custom SSH keys with passwords can now be used - #227"
- text: "Create new note when clicking on non existing Wiki Link - #240"
bugs: bugs:
- text: "Fix notes not always showing up - #270" - text: "Fix notes not always showing up - #270"

View File

@ -104,7 +104,11 @@ class Note with NotesNotifier {
noteSerializer = NoteSerializer.fromConfig(parent.config); noteSerializer = NoteSerializer.fromConfig(parent.config);
} }
Note.newNote(this.parent, {Map<String, dynamic> extraProps = const {}}) { Note.newNote(
this.parent, {
Map<String, dynamic> extraProps = const {},
String fileName = "",
}) {
created = DateTime.now(); created = DateTime.now();
_loadState = NoteLoadState.Loaded; _loadState = NoteLoadState.Loaded;
_fileFormat = NoteFileFormat.Markdown; _fileFormat = NoteFileFormat.Markdown;
@ -116,6 +120,17 @@ class Note with NotesNotifier {
}); });
noteSerializer.decode(_data, this); noteSerializer.decode(_data, this);
} }
if (fileName.isNotEmpty) {
// FIXME: We should ensure a note with this fileName does not already
// exist
if (!NoteFileFormatInfo.isAllowedFileName(fileName)) {
fileName +=
NoteFileFormatInfo.defaultExtension(NoteFileFormat.Markdown);
}
_filePath = p.join(parent.folderPath, fileName);
Log.i("Constructing new note with path $_filePath");
}
} }
String get filePath { String get filePath {

View File

@ -1,13 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:gitjournal/core/note.dart'; import 'package:gitjournal/core/note.dart';
import 'package:gitjournal/core/notes_folder.dart'; import 'package:gitjournal/core/notes_folder.dart';
import 'package:gitjournal/core/notes_folder_fs.dart';
import 'package:gitjournal/folder_views/card_view.dart'; import 'package:gitjournal/folder_views/card_view.dart';
import 'package:gitjournal/folder_views/grid_view.dart'; import 'package:gitjournal/folder_views/grid_view.dart';
import 'package:gitjournal/folder_views/journal_view.dart'; import 'package:gitjournal/folder_views/journal_view.dart';
import 'package:gitjournal/screens/note_editor.dart'; import 'package:gitjournal/screens/note_editor.dart';
import 'package:gitjournal/settings.dart';
import 'package:gitjournal/state_container.dart'; import 'package:gitjournal/state_container.dart';
import 'package:gitjournal/utils.dart'; import 'package:gitjournal/utils.dart';
import 'package:gitjournal/utils/logger.dart'; import 'package:gitjournal/utils/logger.dart';
@ -83,7 +86,8 @@ void openNoteEditor(
bool editMode = false, bool editMode = false,
}) async { }) async {
var route = MaterialPageRoute( var route = MaterialPageRoute(
builder: (context) => NoteEditor.fromNote(note, parentFolder, editMode: editMode), builder: (context) =>
NoteEditor.fromNote(note, parentFolder, editMode: editMode),
settings: const RouteSettings(name: '/note/'), settings: const RouteSettings(name: '/note/'),
); );
var showUndoSnackBar = await Navigator.of(context).push(route); var showUndoSnackBar = await Navigator.of(context).push(route);
@ -97,3 +101,33 @@ void openNoteEditor(
..showSnackBar(snackBar); ..showSnackBar(snackBar);
} }
} }
bool openNewNoteEditor(BuildContext context, String term) {
var rootFolder = Provider.of<NotesFolderFS>(context, listen: false);
var parentFolder = rootFolder;
var settings = Provider.of<Settings>(context, listen: false);
var defaultEditor = settings.defaultEditor.toEditorType();
var fileName = term;
if (fileName.contains(p.separator)) {
parentFolder = rootFolder.getFolderWithSpec(p.dirname(fileName));
if (parentFolder == null) {
return false;
}
Log.i("New Note Parent Folder: ${parentFolder.folderPath}");
fileName = p.basename(term);
}
var route = MaterialPageRoute(
builder: (context) => NoteEditor.newNote(
parentFolder,
parentFolder,
defaultEditor,
newNoteFileName: fileName,
),
settings: const RouteSettings(name: '/newNote/'),
);
Navigator.of(context).push(route);
return true;
}

View File

@ -37,6 +37,7 @@ class NoteEditor extends StatefulWidget {
final List<String> existingImages; final List<String> existingImages;
final Map<String, dynamic> newNoteExtraProps; final Map<String, dynamic> newNoteExtraProps;
final String newNoteFileName;
final bool editMode; final bool editMode;
NoteEditor.fromNote( NoteEditor.fromNote(
@ -47,6 +48,7 @@ class NoteEditor extends StatefulWidget {
defaultEditorType = null, defaultEditorType = null,
existingText = null, existingText = null,
existingImages = null, existingImages = null,
newNoteFileName = "",
newNoteExtraProps = null; newNoteExtraProps = null;
NoteEditor.newNote( NoteEditor.newNote(
@ -56,6 +58,7 @@ class NoteEditor extends StatefulWidget {
this.existingText, this.existingText,
this.existingImages, this.existingImages,
this.newNoteExtraProps = const {}, this.newNoteExtraProps = const {},
this.newNoteFileName = "",
}) : note = null, }) : note = null,
editMode = true; editMode = true;
@ -67,6 +70,7 @@ class NoteEditor extends StatefulWidget {
existingText, existingText,
existingImages, existingImages,
newNoteExtraProps, newNoteExtraProps,
newNoteFileName,
); );
} else { } else {
return NoteEditorState.fromNote(note); return NoteEditorState.fromNote(note);
@ -95,8 +99,9 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
String existingText, String existingText,
List<String> existingImages, List<String> existingImages,
Map<String, dynamic> extraProps, Map<String, dynamic> extraProps,
String fileName,
) { ) {
note = Note.newNote(folder, extraProps: extraProps); note = Note.newNote(folder, extraProps: extraProps, fileName: fileName);
if (existingText != null) { if (existingText != null) {
note.body = existingText; note.body = existingText;
} }

View File

@ -22,15 +22,22 @@ class LinkResolver {
} }
Note resolve(String link) { Note resolve(String link) {
if (link.startsWith('[[') && link.endsWith(']]') && link.length > 4) { if (isWikiLink(link)) {
// FIXME: What if the case is different? // FIXME: What if the case is different?
var wikiLinkTerm = link.substring(2, link.length - 2).trim(); return resolveWikiLink(stripWikiSyntax(link));
return resolveWikiLink(wikiLinkTerm);
} }
return _getNoteWithSpec(inputNote.parent, link); return _getNoteWithSpec(inputNote.parent, link);
} }
static bool isWikiLink(String link) {
return link.startsWith('[[') && link.endsWith(']]') && link.length > 4;
}
static String stripWikiSyntax(String link) {
return link.substring(2, link.length - 2).trim();
}
Note resolveWikiLink(String term) { Note resolveWikiLink(String term) {
if (term.contains(p.separator)) { if (term.contains(p.separator)) {
var spec = p.normalize(term); var spec = p.normalize(term);

View File

@ -89,6 +89,18 @@ class NoteViewer extends StatelessWidget {
return; return;
} }
if (LinkResolver.isWikiLink(link)) {
var opened = openNewNoteEditor(
context, LinkResolver.stripWikiSyntax(link));
if (!opened) {
showSnackbar(
context,
tr('wigets.NoteViewer.linkInvalid', args: [link]),
);
}
return;
}
// External Link // External Link
try { try {
await launch(link); await launch(link);