mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-03 19:54:12 +00:00 
			
		
		
		
	Can post PDFs
This commit is contained in:
		@@ -56,8 +56,11 @@ class APIHelper {
 | 
				
			|||||||
          var v = request.bytesFiles[key];
 | 
					          var v = request.bytesFiles[key];
 | 
				
			||||||
          data.files.add(MapEntry(
 | 
					          data.files.add(MapEntry(
 | 
				
			||||||
              key,
 | 
					              key,
 | 
				
			||||||
              MultipartFile.fromBytes(v.bytes,
 | 
					              MultipartFile.fromBytes(
 | 
				
			||||||
                  filename: v.filename.split("/").last)));
 | 
					                v.bytes,
 | 
				
			||||||
 | 
					                filename: v.filename.split("/").last,
 | 
				
			||||||
 | 
					                contentType: v.type,
 | 
				
			||||||
 | 
					              )));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ import 'package:comunic/models/api_request.dart';
 | 
				
			|||||||
import 'package:comunic/models/displayed_content.dart';
 | 
					import 'package:comunic/models/displayed_content.dart';
 | 
				
			||||||
import 'package:comunic/models/new_post.dart';
 | 
					import 'package:comunic/models/new_post.dart';
 | 
				
			||||||
import 'package:comunic/models/post.dart';
 | 
					import 'package:comunic/models/post.dart';
 | 
				
			||||||
 | 
					import 'package:http_parser/http_parser.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Posts helper
 | 
					/// Posts helper
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@@ -57,7 +58,7 @@ class PostsHelper {
 | 
				
			|||||||
  /// failure
 | 
					  /// failure
 | 
				
			||||||
  Future<PostsList> getLatest({int from = 0}) async {
 | 
					  Future<PostsList> getLatest({int from = 0}) async {
 | 
				
			||||||
    final response =
 | 
					    final response =
 | 
				
			||||||
    await APIRequest(uri: "posts/get_latest", needLogin: true, args: {
 | 
					        await APIRequest(uri: "posts/get_latest", needLogin: true, args: {
 | 
				
			||||||
      "include_groups": true.toString(),
 | 
					      "include_groups": true.toString(),
 | 
				
			||||||
      "startFrom": from.toString(),
 | 
					      "startFrom": from.toString(),
 | 
				
			||||||
    }).exec();
 | 
					    }).exec();
 | 
				
			||||||
@@ -76,7 +77,8 @@ class PostsHelper {
 | 
				
			|||||||
  /// Get the list of posts of a user
 | 
					  /// Get the list of posts of a user
 | 
				
			||||||
  Future<PostsList> getUserPosts(int userID, {int from = 0}) async {
 | 
					  Future<PostsList> getUserPosts(int userID, {int from = 0}) async {
 | 
				
			||||||
    final response = await (APIRequest(uri: "posts/get_user", needLogin: true)
 | 
					    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();
 | 
					        .exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response.code != 200) return null;
 | 
					    if (response.code != 200) return null;
 | 
				
			||||||
@@ -93,7 +95,8 @@ class PostsHelper {
 | 
				
			|||||||
  /// Get the list of posts of a group
 | 
					  /// Get the list of posts of a group
 | 
				
			||||||
  Future<PostsList> getGroupPosts(int groupID, {int from = 0}) async {
 | 
					  Future<PostsList> getGroupPosts(int groupID, {int from = 0}) async {
 | 
				
			||||||
    final response = await (APIRequest(uri: "posts/get_group", needLogin: true)
 | 
					    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();
 | 
					        .exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response.code != 200) return null;
 | 
					    if (response.code != 200) return null;
 | 
				
			||||||
@@ -126,11 +129,11 @@ class PostsHelper {
 | 
				
			|||||||
  /// This function crash in case of error
 | 
					  /// This function crash in case of error
 | 
				
			||||||
  Future<void> createPost(NewPost post) async {
 | 
					  Future<void> createPost(NewPost post) async {
 | 
				
			||||||
    APIRequest request =
 | 
					    APIRequest request =
 | 
				
			||||||
    APIRequest(uri: "posts/create", needLogin: true, args: {
 | 
					        APIRequest(uri: "posts/create", needLogin: true, args: {
 | 
				
			||||||
      "kind-page": _APIPostsTargetKindsMap[post.target],
 | 
					      "kind-page": _APIPostsTargetKindsMap[post.target],
 | 
				
			||||||
      "kind-id": post.targetID.toString(),
 | 
					      "kind-id": post.targetID.toString(),
 | 
				
			||||||
      "visibility": _APIPostsVisibilityLevelMap.map(
 | 
					      "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],
 | 
					      "kind": _APIPostsKindsMap.map((s, k) => MapEntry(k, s))[post.kind],
 | 
				
			||||||
      "content": post.content
 | 
					      "content": post.content
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -143,6 +146,13 @@ class PostsHelper {
 | 
				
			|||||||
        request.addFile("image", post.image);
 | 
					        request.addFile("image", post.image);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case PostKind.PDF:
 | 
				
			||||||
 | 
					        request.addBytesFile(
 | 
				
			||||||
 | 
					            "pdf",
 | 
				
			||||||
 | 
					            BytesFile("file.pdf", post.pdf,
 | 
				
			||||||
 | 
					                type: MediaType.parse("application/pdf")));
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw Exception("Unsupported post type :" + post.kind.toString());
 | 
					        throw Exception("Unsupported post type :" + post.kind.toString());
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@@ -174,7 +184,7 @@ class PostsHelper {
 | 
				
			|||||||
      args: {
 | 
					      args: {
 | 
				
			||||||
        "postID": id.toString(),
 | 
					        "postID": id.toString(),
 | 
				
			||||||
        "new_level":
 | 
					        "new_level":
 | 
				
			||||||
        _APIPostsVisibilityLevelMap.map((k, v) => MapEntry(v, k))[level]
 | 
					            _APIPostsVisibilityLevelMap.map((k, v) => MapEntry(v, k))[level]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    ).exec())
 | 
					    ).exec())
 | 
				
			||||||
        .isOK;
 | 
					        .isOK;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import 'dart:io';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:comunic/helpers/api_helper.dart';
 | 
					import 'package:comunic/helpers/api_helper.dart';
 | 
				
			||||||
import 'package:comunic/models/api_response.dart';
 | 
					import 'package:comunic/models/api_response.dart';
 | 
				
			||||||
 | 
					import 'package:http_parser/http_parser.dart';
 | 
				
			||||||
import 'package:meta/meta.dart';
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// API Request model
 | 
					/// API Request model
 | 
				
			||||||
@@ -13,8 +14,13 @@ import 'package:meta/meta.dart';
 | 
				
			|||||||
class BytesFile {
 | 
					class BytesFile {
 | 
				
			||||||
  final String filename;
 | 
					  final String filename;
 | 
				
			||||||
  final List<int> bytes;
 | 
					  final List<int> bytes;
 | 
				
			||||||
 | 
					  final MediaType type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  BytesFile(this.filename, this.bytes);
 | 
					  const BytesFile(
 | 
				
			||||||
 | 
					    this.filename,
 | 
				
			||||||
 | 
					    this.bytes, {
 | 
				
			||||||
 | 
					    this.type,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class APIRequest {
 | 
					class APIRequest {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,19 +15,22 @@ class NewPost {
 | 
				
			|||||||
  final PostVisibilityLevel visibility;
 | 
					  final PostVisibilityLevel visibility;
 | 
				
			||||||
  final String content;
 | 
					  final String content;
 | 
				
			||||||
  final File image;
 | 
					  final File image;
 | 
				
			||||||
 | 
					  final List<int> pdf;
 | 
				
			||||||
  final PostKind kind;
 | 
					  final PostKind kind;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  NewPost({
 | 
					  const NewPost({
 | 
				
			||||||
    @required this.target,
 | 
					    @required this.target,
 | 
				
			||||||
    @required this.targetID,
 | 
					    @required this.targetID,
 | 
				
			||||||
    @required this.visibility,
 | 
					    @required this.visibility,
 | 
				
			||||||
    @required this.content,
 | 
					    @required this.content,
 | 
				
			||||||
    @required this.kind,
 | 
					    @required this.kind,
 | 
				
			||||||
    @required this.image,
 | 
					    @required this.image,
 | 
				
			||||||
 | 
					    @required this.pdf,
 | 
				
			||||||
  })  : assert(target != null),
 | 
					  })  : assert(target != null),
 | 
				
			||||||
        assert(targetID != null),
 | 
					        assert(targetID != null),
 | 
				
			||||||
        assert(visibility != null),
 | 
					        assert(visibility != null),
 | 
				
			||||||
        assert(content != null),
 | 
					        assert(content != null),
 | 
				
			||||||
        assert(kind != PostKind.TEXT || content.length > 3),
 | 
					        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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import 'package:comunic/utils/files_utils.dart';
 | 
				
			|||||||
import 'package:comunic/utils/intl_utils.dart';
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
import 'package:comunic/utils/post_utils.dart';
 | 
					import 'package:comunic/utils/post_utils.dart';
 | 
				
			||||||
import 'package:comunic/utils/ui_utils.dart';
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
 | 
					import 'package:file_picker_cross/file_picker_cross.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Widget that allows to create posts
 | 
					/// Widget that allows to create posts
 | 
				
			||||||
@@ -47,15 +48,20 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
 | 
				
			|||||||
  final TextEditingController _postTextController = TextEditingController();
 | 
					  final TextEditingController _postTextController = TextEditingController();
 | 
				
			||||||
  PostVisibilityLevel _postVisibilityLevel;
 | 
					  PostVisibilityLevel _postVisibilityLevel;
 | 
				
			||||||
  File _postImage;
 | 
					  File _postImage;
 | 
				
			||||||
 | 
					  List<int> _postPDF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool get hasImage => _postImage != null;
 | 
					  bool get hasImage => _postImage != null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get hasPDF => _postPDF != null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool get canSubmitForm =>
 | 
					  bool get canSubmitForm =>
 | 
				
			||||||
      !_isCreating && _postTextController.text.length > 5 || hasImage;
 | 
					      !_isCreating && _postTextController.text.length > 5 || hasImage || hasPDF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PostKind get postKind {
 | 
					  PostKind get postKind {
 | 
				
			||||||
    if (hasImage)
 | 
					    if (hasImage)
 | 
				
			||||||
      return PostKind.IMAGE;
 | 
					      return PostKind.IMAGE;
 | 
				
			||||||
 | 
					    else if (hasPDF)
 | 
				
			||||||
 | 
					      return PostKind.PDF;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      return PostKind.TEXT;
 | 
					      return PostKind.TEXT;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -102,6 +108,13 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
 | 
				
			|||||||
                onTap: _pickImageForPost,
 | 
					                onTap: _pickImageForPost,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // Include PDF button
 | 
				
			||||||
 | 
					              _PostOptionWidget(
 | 
				
			||||||
 | 
					                icon: Icons.picture_as_pdf,
 | 
				
			||||||
 | 
					                selected: postKind == PostKind.PDF,
 | 
				
			||||||
 | 
					                onTap: _pickPDFForPost,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              Expanded(
 | 
					              Expanded(
 | 
				
			||||||
                child: Container(),
 | 
					                child: Container(),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
@@ -159,6 +172,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
 | 
				
			|||||||
  void _resetPostSelection() {
 | 
					  void _resetPostSelection() {
 | 
				
			||||||
    setState(() {
 | 
					    setState(() {
 | 
				
			||||||
      _postImage = null;
 | 
					      _postImage = null;
 | 
				
			||||||
 | 
					      _postPDF = null;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -175,6 +189,27 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Pick a PDF for the new post
 | 
				
			||||||
 | 
					  Future<void> _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
 | 
					  /// Submit new post
 | 
				
			||||||
  Future<void> _submitForm() async {
 | 
					  Future<void> _submitForm() async {
 | 
				
			||||||
    if (!canSubmitForm)
 | 
					    if (!canSubmitForm)
 | 
				
			||||||
@@ -190,6 +225,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
 | 
				
			|||||||
        content: _postTextController.text,
 | 
					        content: _postTextController.text,
 | 
				
			||||||
        kind: postKind,
 | 
					        kind: postKind,
 | 
				
			||||||
        image: _postImage,
 | 
					        image: _postImage,
 | 
				
			||||||
 | 
					        pdf: _postPDF,
 | 
				
			||||||
      ));
 | 
					      ));
 | 
				
			||||||
      setState(() => _isCreating = false);
 | 
					      setState(() => _isCreating = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -113,6 +113,20 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.1.1"
 | 
					    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:
 | 
					  flutter:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description: flutter
 | 
					    description: flutter
 | 
				
			||||||
@@ -171,7 +185,7 @@ packages:
 | 
				
			|||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "0.12.0+4"
 | 
					    version: "0.12.0+4"
 | 
				
			||||||
  http_parser:
 | 
					  http_parser:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: http_parser
 | 
					      name: http_parser
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,7 @@ dependencies:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  # The HTTP client is used to make requests on the Comunic API
 | 
					  # The HTTP client is used to make requests on the Comunic API
 | 
				
			||||||
  dio: ^3.0.9
 | 
					  dio: ^3.0.9
 | 
				
			||||||
 | 
					  http_parser: ^3.1.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # This plugins allows to load remote images
 | 
					  # This plugins allows to load remote images
 | 
				
			||||||
  cached_network_image: ^2.0.0
 | 
					  cached_network_image: ^2.0.0
 | 
				
			||||||
@@ -81,6 +82,9 @@ dependencies:
 | 
				
			|||||||
  # Prevent phone from auto-locking during calls
 | 
					  # Prevent phone from auto-locking during calls
 | 
				
			||||||
  wakelock: ^0.1.4+1
 | 
					  wakelock: ^0.1.4+1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Pick any kind of file
 | 
				
			||||||
 | 
					  file_picker_cross: ^1.2.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
    sdk: flutter
 | 
					    sdk: flutter
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user