From 3a9bb3d13ee6085b4d97409a61f87834570cf614 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Fri, 24 Apr 2020 13:35:05 +0200 Subject: [PATCH] Can post PDFs --- lib/helpers/api_helper.dart | 7 ++-- lib/helpers/posts_helper.dart | 22 ++++++++---- lib/models/api_request.dart | 8 ++++- lib/models/new_post.dart | 7 ++-- lib/ui/widgets/post_create_form_widget.dart | 38 ++++++++++++++++++++- pubspec.lock | 16 ++++++++- pubspec.yaml | 4 +++ 7 files changed, 89 insertions(+), 13 deletions(-) diff --git a/lib/helpers/api_helper.dart b/lib/helpers/api_helper.dart index 03a1dd9..b8938e1 100644 --- a/lib/helpers/api_helper.dart +++ b/lib/helpers/api_helper.dart @@ -56,8 +56,11 @@ class APIHelper { var v = request.bytesFiles[key]; data.files.add(MapEntry( key, - MultipartFile.fromBytes(v.bytes, - filename: v.filename.split("/").last))); + MultipartFile.fromBytes( + v.bytes, + filename: v.filename.split("/").last, + contentType: v.type, + ))); } } diff --git a/lib/helpers/posts_helper.dart b/lib/helpers/posts_helper.dart index 76d5fb2..f78eee2 100644 --- a/lib/helpers/posts_helper.dart +++ b/lib/helpers/posts_helper.dart @@ -11,6 +11,7 @@ import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/displayed_content.dart'; import 'package:comunic/models/new_post.dart'; import 'package:comunic/models/post.dart'; +import 'package:http_parser/http_parser.dart'; /// Posts helper /// @@ -57,7 +58,7 @@ class PostsHelper { /// failure Future getLatest({int from = 0}) async { final response = - await APIRequest(uri: "posts/get_latest", needLogin: true, args: { + await APIRequest(uri: "posts/get_latest", needLogin: true, args: { "include_groups": true.toString(), "startFrom": from.toString(), }).exec(); @@ -76,7 +77,8 @@ class PostsHelper { /// Get the list of posts of a user Future getUserPosts(int userID, {int from = 0}) async { final response = await (APIRequest(uri: "posts/get_user", needLogin: true) - ..addInt("userID", userID)..addInt("startFrom", from == 0 ? 0 : from - 1)) + ..addInt("userID", userID) + ..addInt("startFrom", from == 0 ? 0 : from - 1)) .exec(); if (response.code != 200) return null; @@ -93,7 +95,8 @@ class PostsHelper { /// Get the list of posts of a group Future getGroupPosts(int groupID, {int from = 0}) async { final response = await (APIRequest(uri: "posts/get_group", needLogin: true) - ..addInt("groupID", groupID)..addInt("startFrom", from == 0 ? 0 : from - 1)) + ..addInt("groupID", groupID) + ..addInt("startFrom", from == 0 ? 0 : from - 1)) .exec(); if (response.code != 200) return null; @@ -126,11 +129,11 @@ class PostsHelper { /// This function crash in case of error Future createPost(NewPost post) async { APIRequest request = - APIRequest(uri: "posts/create", needLogin: true, args: { + APIRequest(uri: "posts/create", needLogin: true, args: { "kind-page": _APIPostsTargetKindsMap[post.target], "kind-id": post.targetID.toString(), "visibility": _APIPostsVisibilityLevelMap.map( - (s, v) => MapEntry(v, s))[post.visibility], + (s, v) => MapEntry(v, s))[post.visibility], "kind": _APIPostsKindsMap.map((s, k) => MapEntry(k, s))[post.kind], "content": post.content }); @@ -143,6 +146,13 @@ class PostsHelper { request.addFile("image", post.image); break; + case PostKind.PDF: + request.addBytesFile( + "pdf", + BytesFile("file.pdf", post.pdf, + type: MediaType.parse("application/pdf"))); + break; + default: throw Exception("Unsupported post type :" + post.kind.toString()); break; @@ -174,7 +184,7 @@ class PostsHelper { args: { "postID": id.toString(), "new_level": - _APIPostsVisibilityLevelMap.map((k, v) => MapEntry(v, k))[level] + _APIPostsVisibilityLevelMap.map((k, v) => MapEntry(v, k))[level] }, ).exec()) .isOK; diff --git a/lib/models/api_request.dart b/lib/models/api_request.dart index a172e00..238db61 100644 --- a/lib/models/api_request.dart +++ b/lib/models/api_request.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:comunic/helpers/api_helper.dart'; import 'package:comunic/models/api_response.dart'; +import 'package:http_parser/http_parser.dart'; import 'package:meta/meta.dart'; /// API Request model @@ -13,8 +14,13 @@ import 'package:meta/meta.dart'; class BytesFile { final String filename; final List bytes; + final MediaType type; - BytesFile(this.filename, this.bytes); + const BytesFile( + this.filename, + this.bytes, { + this.type, + }); } class APIRequest { diff --git a/lib/models/new_post.dart b/lib/models/new_post.dart index 0a1843e..b528b4b 100644 --- a/lib/models/new_post.dart +++ b/lib/models/new_post.dart @@ -15,19 +15,22 @@ class NewPost { final PostVisibilityLevel visibility; final String content; final File image; + final List pdf; final PostKind kind; - NewPost({ + const NewPost({ @required this.target, @required this.targetID, @required this.visibility, @required this.content, @required this.kind, @required this.image, + @required this.pdf, }) : assert(target != null), assert(targetID != null), assert(visibility != null), assert(content != null), assert(kind != PostKind.TEXT || content.length > 3), - assert(kind != PostKind.IMAGE || image != null); + assert(kind != PostKind.IMAGE || image != null), + assert(kind != PostKind.PDF || pdf != null); } diff --git a/lib/ui/widgets/post_create_form_widget.dart b/lib/ui/widgets/post_create_form_widget.dart index 89d63ff..2eed8e4 100644 --- a/lib/ui/widgets/post_create_form_widget.dart +++ b/lib/ui/widgets/post_create_form_widget.dart @@ -9,6 +9,7 @@ import 'package:comunic/utils/files_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/post_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; +import 'package:file_picker_cross/file_picker_cross.dart'; import 'package:flutter/material.dart'; /// Widget that allows to create posts @@ -47,15 +48,20 @@ class _PostCreateFormWidgetState extends State { final TextEditingController _postTextController = TextEditingController(); PostVisibilityLevel _postVisibilityLevel; File _postImage; + List _postPDF; bool get hasImage => _postImage != null; + bool get hasPDF => _postPDF != null; + bool get canSubmitForm => - !_isCreating && _postTextController.text.length > 5 || hasImage; + !_isCreating && _postTextController.text.length > 5 || hasImage || hasPDF; PostKind get postKind { if (hasImage) return PostKind.IMAGE; + else if (hasPDF) + return PostKind.PDF; else return PostKind.TEXT; } @@ -102,6 +108,13 @@ class _PostCreateFormWidgetState extends State { onTap: _pickImageForPost, ), + // Include PDF button + _PostOptionWidget( + icon: Icons.picture_as_pdf, + selected: postKind == PostKind.PDF, + onTap: _pickPDFForPost, + ), + Expanded( child: Container(), ), @@ -159,6 +172,7 @@ class _PostCreateFormWidgetState extends State { void _resetPostSelection() { setState(() { _postImage = null; + _postPDF = null; }); } @@ -175,6 +189,27 @@ class _PostCreateFormWidgetState extends State { }); } + /// Pick a PDF for the new post + Future _pickPDFForPost() async { + try { + final picker = FilePickerCross( + type: FileTypeCross.custom, + fileExtension: "pdf", + ); + + if (!await picker.pick()) return; + + _resetPostSelection(); + + setState(() { + this._postPDF = picker.toUint8List(); + }); + } catch (e, stack) { + print("Pick PDF error: $e\n$stack"); + showSimpleSnack(context, tr("Could not pick a PDF!")); + } + } + /// Submit new post Future _submitForm() async { if (!canSubmitForm) @@ -190,6 +225,7 @@ class _PostCreateFormWidgetState extends State { content: _postTextController.text, kind: postKind, image: _postImage, + pdf: _postPDF, )); setState(() => _isCreating = false); diff --git a/pubspec.lock b/pubspec.lock index 0f2e402..b1d9888 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + file_picker: + dependency: transitive + description: + name: file_picker + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.3+2" + file_picker_cross: + dependency: "direct main" + description: + name: file_picker_cross + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" flutter: dependency: "direct main" description: flutter @@ -171,7 +185,7 @@ packages: source: hosted version: "0.12.0+4" http_parser: - dependency: transitive + dependency: "direct main" description: name: http_parser url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 9734821..807fcfc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: # The HTTP client is used to make requests on the Comunic API dio: ^3.0.9 + http_parser: ^3.1.3 # This plugins allows to load remote images cached_network_image: ^2.0.0 @@ -81,6 +82,9 @@ dependencies: # Prevent phone from auto-locking during calls wakelock: ^0.1.4+1 + # Pick any kind of file + file_picker_cross: ^1.2.1 + dev_dependencies: flutter_test: sdk: flutter