mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-28 09:47:35 +08:00
Add very basic Image support [Android only]
This adds a '+' button to the NoteEditor which allows you to add an image from either the Gallery or Take a photo. It then accordingly adds updates markdown. The file is added in the same directory as the note for now. Related to #10
This commit is contained in:
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="com.android.vending.BILLING" />
|
<uses-permission android:name="com.android.vending.BILLING" />
|
||||||
|
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||||
|
|
||||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||||
|
@ -250,6 +250,14 @@ class Note with NotesNotifier {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> addImage(File file) async {
|
||||||
|
var imageFileName = p.basename(file.path);
|
||||||
|
var imagePath = p.join(parent.folderPath, imageFileName);
|
||||||
|
await file.copy(imagePath);
|
||||||
|
|
||||||
|
body = "$body\n \n";
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => _filePath.hashCode;
|
int get hashCode => _filePath.hashCode;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -159,8 +160,9 @@ class ChecklistEditorState extends State<ChecklistEditor>
|
|||||||
Expanded(child: FocusScope(child: checklistWidget)),
|
Expanded(child: FocusScope(child: checklistWidget)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
bottomNavigationBar:
|
bottomNavigationBar: Builder(
|
||||||
buildEditorBottonBar(context, widget, this, checklist.note),
|
builder: (context) => buildEditorBottonBar(context, widget, this),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +251,17 @@ class ChecklistEditorState extends State<ChecklistEditor>
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addImage(File file) async {
|
||||||
|
var note = getNote();
|
||||||
|
await note.addImage(file);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
checklist = Checklist(note);
|
||||||
|
_noteModified = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef TextChangedFunction = void Function(String);
|
typedef TextChangedFunction = void Function(String);
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gitjournal/core/note.dart';
|
import 'package:gitjournal/core/note.dart';
|
||||||
|
import 'package:gitjournal/error_reporting.dart';
|
||||||
import 'package:share/share.dart';
|
import 'package:share/share.dart';
|
||||||
|
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
|
||||||
typedef NoteCallback = void Function(Note);
|
typedef NoteCallback = void Function(Note);
|
||||||
|
|
||||||
abstract class Editor {
|
abstract class Editor {
|
||||||
@ -15,6 +20,7 @@ abstract class Editor {
|
|||||||
|
|
||||||
abstract class EditorState {
|
abstract class EditorState {
|
||||||
Note getNote();
|
Note getNote();
|
||||||
|
Future<void> addImage(File file);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DropDownChoices { Rename, DiscardChanges, Share }
|
enum DropDownChoices { Rename, DiscardChanges, Share }
|
||||||
@ -93,27 +99,45 @@ Widget buildEditorBottonBar(
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
Editor editor,
|
Editor editor,
|
||||||
EditorState editorState,
|
EditorState editorState,
|
||||||
Note note,
|
|
||||||
) {
|
) {
|
||||||
|
var note = editorState.getNote();
|
||||||
var folderName = note.parent.pathSpec();
|
var folderName = note.parent.pathSpec();
|
||||||
if (folderName.isEmpty) {
|
if (folderName.isEmpty) {
|
||||||
folderName = "Root Folder";
|
folderName = "Root Folder";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var s = Scaffold.of(context);
|
||||||
|
print("s $s");
|
||||||
return StickyBottomAppBar(
|
return StickyBottomAppBar(
|
||||||
child: BottomAppBar(
|
child: BottomAppBar(
|
||||||
elevation: 0.0,
|
elevation: 0.0,
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FlatButton.icon(
|
IconButton(
|
||||||
icon: Icon(Icons.folder),
|
icon: Icon(Icons.add),
|
||||||
label: Text(folderName),
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
var note = editorState.getNote();
|
showModalBottomSheet(
|
||||||
editor.moveNoteToFolderSelected(note);
|
context: context,
|
||||||
|
builder: (c) => _buildAddBottomSheet(c, editor, editorState),
|
||||||
|
elevation: 0,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
|
Expanded(
|
||||||
|
child: FlatButton.icon(
|
||||||
|
icon: Icon(Icons.folder),
|
||||||
|
label: Text(folderName),
|
||||||
|
onPressed: () {
|
||||||
|
var note = editorState.getNote();
|
||||||
|
editor.moveNoteToFolderSelected(note);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 32.0,
|
||||||
|
width: 32.0,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
),
|
),
|
||||||
@ -133,3 +157,53 @@ class StickyBottomAppBar extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildAddBottomSheet(
|
||||||
|
BuildContext context,
|
||||||
|
Editor editor,
|
||||||
|
EditorState editorState,
|
||||||
|
) {
|
||||||
|
return Container(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.camera),
|
||||||
|
title: const Text("Take Photo"),
|
||||||
|
onTap: () async {
|
||||||
|
try {
|
||||||
|
var image = await ImagePicker.pickImage(
|
||||||
|
source: ImageSource.camera,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (image != null) {
|
||||||
|
await editorState.addImage(image);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reportError(e, StackTrace.current);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.image),
|
||||||
|
title: const Text("Add Image"),
|
||||||
|
onTap: () async {
|
||||||
|
try {
|
||||||
|
var image = await ImagePicker.pickImage(
|
||||||
|
source: ImageSource.gallery,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (image != null) {
|
||||||
|
await editorState.addImage(image);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reportError(e, StackTrace.current);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:gitjournal/core/note.dart';
|
import 'package:gitjournal/core/note.dart';
|
||||||
@ -84,7 +85,9 @@ class JournalEditorState extends State<JournalEditor> implements EditorState {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: buildEditorAppBar(widget, this, noteModified: _noteModified),
|
appBar: buildEditorAppBar(widget, this, noteModified: _noteModified),
|
||||||
body: editor,
|
body: editor,
|
||||||
bottomNavigationBar: buildEditorBottonBar(context, widget, this, note),
|
bottomNavigationBar: Builder(
|
||||||
|
builder: (context) => buildEditorBottonBar(context, widget, this),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +104,15 @@ class JournalEditorState extends State<JournalEditor> implements EditorState {
|
|||||||
_noteModified = true;
|
_noteModified = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addImage(File file) async {
|
||||||
|
await getNote().addImage(file);
|
||||||
|
setState(() {
|
||||||
|
_textController.text = note.body;
|
||||||
|
_noteModified = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NoteBodyEditor extends StatelessWidget {
|
class _NoteBodyEditor extends StatelessWidget {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:gitjournal/core/note.dart';
|
import 'package:gitjournal/core/note.dart';
|
||||||
@ -115,7 +116,9 @@ class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
|
|||||||
extraButtons: [extraButton],
|
extraButtons: [extraButton],
|
||||||
),
|
),
|
||||||
body: body,
|
body: body,
|
||||||
bottomNavigationBar: buildEditorBottonBar(context, widget, this, note),
|
bottomNavigationBar: Builder(
|
||||||
|
builder: (context) => buildEditorBottonBar(context, widget, this),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +147,15 @@ class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
|
|||||||
_noteModified = true;
|
_noteModified = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addImage(File file) async {
|
||||||
|
await getNote().addImage(file);
|
||||||
|
setState(() {
|
||||||
|
_textController.text = note.body;
|
||||||
|
_noteModified = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NoteBodyEditor extends StatelessWidget {
|
class _NoteBodyEditor extends StatelessWidget {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:gitjournal/core/note.dart';
|
import 'package:gitjournal/core/note.dart';
|
||||||
@ -81,7 +82,9 @@ class RawEditorState extends State<RawEditor> implements EditorState {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: buildEditorAppBar(widget, this, noteModified: _noteModified),
|
appBar: buildEditorAppBar(widget, this, noteModified: _noteModified),
|
||||||
body: editor,
|
body: editor,
|
||||||
bottomNavigationBar: buildEditorBottonBar(context, widget, this, note),
|
bottomNavigationBar: Builder(
|
||||||
|
builder: (context) => buildEditorBottonBar(context, widget, this),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +100,15 @@ class RawEditorState extends State<RawEditor> implements EditorState {
|
|||||||
_noteModified = true;
|
_noteModified = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addImage(File file) async {
|
||||||
|
await getNote().addImage(file);
|
||||||
|
setState(() {
|
||||||
|
_textController.text = note.body;
|
||||||
|
_noteModified = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NoteEditor extends StatelessWidget {
|
class _NoteEditor extends StatelessWidget {
|
||||||
|
23
pubspec.lock
23
pubspec.lock
@ -258,6 +258,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.2"
|
version: "0.3.2"
|
||||||
|
flutter_plugin_android_lifecycle:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_plugin_android_lifecycle
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.7"
|
||||||
flutter_runtime_env:
|
flutter_runtime_env:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -373,6 +380,20 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
image_picker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: image_picker
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.6+1"
|
||||||
|
image_picker_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -568,7 +589,7 @@ packages:
|
|||||||
name: plugin_platform_interface
|
name: plugin_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.2"
|
||||||
pointycastle:
|
pointycastle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -51,6 +51,7 @@ dependencies:
|
|||||||
isolate: ^2.0.3
|
isolate: ^2.0.3
|
||||||
flutter_webview_plugin:
|
flutter_webview_plugin:
|
||||||
git: https://github.com/breez/flutter_webview_plugin.git
|
git: https://github.com/breez/flutter_webview_plugin.git
|
||||||
|
image_picker: ^0.6.6+1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_launcher_icons: "^0.7.2"
|
flutter_launcher_icons: "^0.7.2"
|
||||||
|
Reference in New Issue
Block a user