Browse Source

DC: impl pick image/video in post

pull/18/head
Sun 4 years ago
parent
commit
078d606faf
  1. 110
      lib/apps/file/editor.dart
  2. 2
      lib/l10n/localizations.dart
  3. 4
      lib/l10n/localizations_en.dart
  4. 4
      lib/l10n/localizations_zh.dart
  5. 25
      lib/utils/pick_image.dart

110
lib/apps/file/editor.dart

@ -1,11 +1,13 @@ @@ -1,11 +1,13 @@
import 'dart:io' show File;
import 'dart:io' show File, Directory;
import 'dart:convert' show jsonDecode, jsonEncode;
import 'package:path/path.dart' show basename;
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter_quill/flutter_quill.dart' hide Text;
import 'package:esse/utils/adaptive.dart';
import 'package:esse/utils/pick_image.dart';
import 'package:esse/l10n/localizations.dart';
import 'package:esse/provider.dart';
import 'package:esse/global.dart';
@ -29,6 +31,7 @@ class _EditorPageState extends State<EditorPage> { @@ -29,6 +31,7 @@ class _EditorPageState extends State<EditorPage> {
TextEditingController _nameController = TextEditingController();
bool _nameEdit = false;
String _filePath = '';
bool _edit = false;
readFile() async {
try {
@ -49,6 +52,25 @@ class _EditorPageState extends State<EditorPage> { @@ -49,6 +52,25 @@ class _EditorPageState extends State<EditorPage> {
}
}
save(String saveOk) async {
final j = this._controller!.document.toDelta().toJson();
final s = jsonEncode(j);
await File(this._filePath).writeAsString(s);
this._fToast!.showToast(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 10.0),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(25.0),
color: Color(0x2F008000)),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [Icon(Icons.check, color: Colors.green),
const SizedBox(width: 12.0), Text(saveOk, style: TextStyle(color: Colors.green))],
)),
gravity: ToastGravity.BOTTOM,
toastDuration: Duration(seconds: 2),
);
}
@override
initState() {
super.initState();
@ -135,31 +157,27 @@ class _EditorPageState extends State<EditorPage> { @@ -135,31 +157,27 @@ class _EditorPageState extends State<EditorPage> {
),
])
: TextButton(child: Text(widget.path.showName()),
onPressed: () => setState(() { this._nameEdit = true; }),
onPressed: this._edit ? () => setState(() { this._nameEdit = true; }) : null,
),
actions: [
IconButton(icon: Icon(Icons.save_rounded), onPressed: () async {
final j = this._controller!.document.toDelta().toJson();
final s = jsonEncode(j);
await File(this._filePath).writeAsString(s);
this._fToast!.showToast(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 10.0),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(25.0),
color: Colors.green),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [Icon(Icons.check), const SizedBox(width: 12.0), Text(lang.saveOk)],
)),
gravity: ToastGravity.BOTTOM,
toastDuration: Duration(seconds: 2),
);
if (this._edit)
IconButton(icon: Icon(Icons.save_rounded), onPressed: () => save(lang.saveOk)),
if (this._edit)
IconButton(icon: Icon(Icons.menu_book_rounded, color: Colors.green),
onPressed: () async {
await save(lang.saveOk);
setState(() { this._edit = false; });
}),
if (!this._edit)
IconButton(icon: Icon(Icons.edit_rounded, color: Colors.green), onPressed: () {
setState(() { this._edit = true; });
}),
const SizedBox(width: 10.0),
]
),
body: Column(
children: [
if (this._edit)
Container(
width: double.infinity,
decoration: BoxDecoration(color: color.secondary),
@ -168,6 +186,10 @@ class _EditorPageState extends State<EditorPage> { @@ -168,6 +186,10 @@ class _EditorPageState extends State<EditorPage> {
controller: this._controller!,
showAlignmentButtons: true,
multiRowsDisplay: isDesktop,
onImagePickCallback: _onImagePickCallback,
onVideoPickCallback: _onImagePickCallback,
mediaPickSettingSelector: _selectMediaPickSetting,
filePickImpl: pickMedia,
showLink: false,
)
),
@ -176,7 +198,7 @@ class _EditorPageState extends State<EditorPage> { @@ -176,7 +198,7 @@ class _EditorPageState extends State<EditorPage> {
padding: const EdgeInsets.all(10.0),
child: QuillEditor.basic(
controller: this._controller!,
readOnly: false, // true for view only mode
readOnly: !this._edit,
),
),
)
@ -184,4 +206,54 @@ class _EditorPageState extends State<EditorPage> { @@ -184,4 +206,54 @@ class _EditorPageState extends State<EditorPage> {
)
);
}
Future<MediaPickSetting?> _selectMediaPickSetting(BuildContext context) {
final lang = AppLocalizations.of(context);
return showDialog<MediaPickSetting>(
context: context,
builder: (ctx) => AlertDialog(
contentPadding: const EdgeInsets.all(20.0),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextButton.icon(
icon: const Icon(Icons.collections),
label: Text(lang.gallery),
onPressed: () => Navigator.pop(ctx, MediaPickSetting.Gallery),
),
const Divider(height: 32.0),
TextButton.icon(
icon: const Icon(Icons.link),
label: Text(lang.link),
onPressed: () => Navigator.pop(ctx, MediaPickSetting.Link),
)
],
),
),
);
}
Future<String> _checkName(String path, String name) async {
String tryName = name;
for( var i=0; i >= 0; i++) {
if (await File(path + tryName).exists()) {
tryName = "${i}_" + name;
} else {
return path + tryName;
}
}
return path + name;
}
Future<String> _onImagePickCallback(File file) async {
final dir = Directory(Global.filePath + widget.path.did + '_assets');
final isExists = await dir.exists();
if (!isExists) {
await dir.create(recursive: true);
}
final pathname = await _checkName(dir.path + '/', basename(file.path));
final copiedFile = await file.copy(pathname);
return copiedFile.path.toString();
}
}

2
lib/l10n/localizations.dart

@ -98,6 +98,8 @@ abstract class AppLocalizations { @@ -98,6 +98,8 @@ abstract class AppLocalizations {
String get notExist;
String get skip;
String get register;
String get gallery;
String get link;
// theme
String get themeDark;

4
lib/l10n/localizations_en.dart

@ -120,6 +120,10 @@ class AppLocalizationsEn extends AppLocalizations { @@ -120,6 +120,10 @@ class AppLocalizationsEn extends AppLocalizations {
String get skip => 'Skip';
@override
String get register => 'Register';
@override
String get gallery => 'Gallery';
@override
String get link => 'Link';
// theme
@override

4
lib/l10n/localizations_zh.dart

@ -120,6 +120,10 @@ class AppLocalizationsZh extends AppLocalizations { @@ -120,6 +120,10 @@ class AppLocalizationsZh extends AppLocalizations {
String get skip => '跳过';
@override
String get register => '注册';
@override
String get gallery => '图库';
@override
String get link => '链接';
// theme
@override

25
lib/utils/pick_image.dart

@ -7,7 +7,30 @@ Future<String?> pickImage() async { @@ -7,7 +7,30 @@ Future<String?> pickImage() async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
final XTypeGroup typeGroup = XTypeGroup(
label: 'images',
extensions: ['jpg', 'png'],
extensions: ['jpg', 'jpeg', 'png', 'svg', 'webp', 'gif', 'bmp', 'wbmp']
);
final List<XFile>? files = await FileSelectorPlatform.instance.openFiles(acceptedTypeGroups: [typeGroup]);
if (files != null && files.length > 0) {
final XFile file = files[0];
return file.path;
}
} else {
final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
return pickedFile.path;
}
}
return null;
}
Future<String?> pickMedia([_=null]) async {
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
final XTypeGroup typeGroup = XTypeGroup(
label: 'medias',
extensions: ['jpg', 'jpeg', 'png', 'svg', 'webp', 'gif', 'bmp', 'wbmp',
'flv', 'mp4', 'm4v', 'mov', 'avi', 'wmv', 'asf', 'dat', 'vob', '3gp', 'mkv', 'rm', 'rmvb'
],
);
final List<XFile>? files = await FileSelectorPlatform.instance.openFiles(acceptedTypeGroups: [typeGroup]);
if (files != null && files.length > 0) {

Loading…
Cancel
Save