1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-22 21:09:21 +00:00

Can create YouTube posts

This commit is contained in:
Pierre HUBERT 2020-04-25 17:16:33 +02:00
parent bb62a3a159
commit da48328c92
6 changed files with 128 additions and 41 deletions

View File

@ -167,6 +167,10 @@ class PostsHelper {
request.addString("answers", post.survey.answers.join("<>")); request.addString("answers", post.survey.answers.join("<>"));
break; break;
case PostKind.YOUTUBE:
request.addString("youtube_id", post.youtubeId);
break;
default: default:
throw Exception("Unsupported post type :" + post.kind.toString()); throw Exception("Unsupported post type :" + post.kind.toString());
break; break;

View File

@ -31,6 +31,7 @@ class NewPost {
final PostKind kind; final PostKind kind;
final DateTime timeEnd; final DateTime timeEnd;
final NewSurvey survey; final NewSurvey survey;
final String youtubeId;
const NewPost({ const NewPost({
@required this.target, @required this.target,
@ -43,6 +44,7 @@ class NewPost {
@required this.pdf, @required this.pdf,
@required this.timeEnd, @required this.timeEnd,
@required this.survey, @required this.survey,
@required this.youtubeId,
}) : assert(target != null), }) : assert(target != null),
assert(targetID != null), assert(targetID != null),
assert(visibility != null), assert(visibility != null),
@ -52,5 +54,6 @@ class NewPost {
assert(kind != PostKind.WEB_LINK || url != null), assert(kind != PostKind.WEB_LINK || url != null),
assert(kind != PostKind.PDF || pdf != null), assert(kind != PostKind.PDF || pdf != null),
assert(kind != PostKind.COUNTDOWN || timeEnd != null), assert(kind != PostKind.COUNTDOWN || timeEnd != null),
assert(kind != PostKind.SURVEY || survey != null); assert(kind != PostKind.SURVEY || survey != null),
assert(kind != PostKind.YOUTUBE || youtubeId != null);
} }

View File

@ -0,0 +1,28 @@
import 'package:comunic/ui/dialogs/single_input_dialog.dart';
import 'package:comunic/utils/input_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
/// Ask the user to enter an URL
///
/// @author Pierre Hubert
/// Ask the user to enter an URL
Future<String> showInputURLDialog({
@required BuildContext context,
@required String title,
String initialURL,
}) async {
return await showDialog(
context: context,
builder: (c) => SingleInputDialog(
title: title,
icon: Icons.link,
initialValue: initialURL,
label: "http://...",
checkInput: (s) => validateUrl(s),
errorMessage: tr("Invalid URL!"),
),
);
}

View File

@ -0,0 +1,29 @@
import 'package:comunic/ui/dialogs/single_input_dialog.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
/// Add YouTube link dialog
///
/// @author Pierre Hubert
/// Ask the user to input a YouTube ID
Future<String> showInputYouTubeIDDialog(
BuildContext context, String initialID) async {
final value = await showDialog<String>(
context: context,
builder: (b) => SingleInputDialog(
title: tr("Input YouTube URL"),
icon: Icons.ondemand_video,
initialValue: initialID == null
? null
: "https://www.youtube.com/watch/?v=" + initialID,
label: tr("https://www.youtube.com/watch/?v="),
checkInput: (s) => RegExp(r'watch\/\?v=[\w\-\_]+').hasMatch(s),
errorMessage: tr("Invalid YouTube link!"),
));
if (value == null) return null;
return value.split("v=")[1].split("&")[0].split("#")[0];
}

View File

@ -1,52 +1,45 @@
import 'package:comunic/utils/input_utils.dart';
import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// Ask the user to enter an URL /// Ask the user to enter an URL
/// class SingleInputDialog extends StatefulWidget {
/// @author Pierre Hubert
/// Ask the user to enter an URL
Future<String> showInputURLDialog({
@required BuildContext context,
@required String title,
String initialURL,
}) async {
return await showDialog(
context: context,
builder: (c) => _InputURLDialog(
title: title,
initialURL: initialURL,
),
);
}
class _InputURLDialog extends StatefulWidget {
final String title; final String title;
final String initialURL; final IconData icon;
final String initialValue;
final String label;
final bool Function(String) checkInput;
final String errorMessage;
const _InputURLDialog({ const SingleInputDialog({
Key key, Key key,
@required this.title, @required this.title,
@required this.initialURL, @required this.icon,
@required this.initialValue,
@required this.label,
@required this.checkInput,
@required this.errorMessage,
}) : assert(title != null), }) : assert(title != null),
assert(icon != null),
assert(label != null),
assert(checkInput != null),
assert(errorMessage != null),
super(key: key); super(key: key);
@override @override
__InputURLDialogState createState() => __InputURLDialogState(); __InputURLDialogState createState() => __InputURLDialogState();
} }
class __InputURLDialogState extends State<_InputURLDialog> { class __InputURLDialogState extends State<SingleInputDialog> {
TextEditingController _controller; TextEditingController _controller;
bool get _isValid => bool get _isValid =>
_controller.text.isNotEmpty && validateUrl(_controller.text); _controller.text.isNotEmpty && widget.checkInput(_controller.text);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_controller = new TextEditingController(text: widget.initialURL); _controller = new TextEditingController(text: widget.initialValue);
} }
@override @override
@ -57,11 +50,11 @@ class __InputURLDialogState extends State<_InputURLDialog> {
controller: _controller, controller: _controller,
onChanged: (s) => setState(() {}), onChanged: (s) => setState(() {}),
decoration: InputDecoration( decoration: InputDecoration(
icon: Icon(Icons.link), icon: Icon(widget.icon),
alignLabelWithHint: true, alignLabelWithHint: true,
labelText: "http://...", labelText: widget.label,
errorText: _controller.text.isNotEmpty && !_isValid errorText: _controller.text.isNotEmpty && !_isValid
? tr("Invalid URL!") ? widget.errorMessage
: null, : null,
), ),
), ),

View File

@ -5,8 +5,9 @@ import 'package:comunic/enums/post_target.dart';
import 'package:comunic/enums/post_visibility_level.dart'; import 'package:comunic/enums/post_visibility_level.dart';
import 'package:comunic/helpers/posts_helper.dart'; import 'package:comunic/helpers/posts_helper.dart';
import 'package:comunic/models/new_post.dart'; import 'package:comunic/models/new_post.dart';
import 'package:comunic/ui/dialogs/input_url_dialog.dart';
import 'package:comunic/ui/dialogs/input_youtube_link_dialog.dart';
import 'package:comunic/ui/dialogs/new_survey_dialog.dart'; import 'package:comunic/ui/dialogs/new_survey_dialog.dart';
import 'package:comunic/ui/dialogs/url_dialog.dart';
import 'package:comunic/utils/files_utils.dart'; 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';
@ -54,6 +55,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
List<int> _postPDF; List<int> _postPDF;
DateTime _timeEnd; DateTime _timeEnd;
NewSurvey _postSurvey; NewSurvey _postSurvey;
String _youtubeID;
bool get hasImage => _postImage != null; bool get hasImage => _postImage != null;
@ -65,6 +67,8 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
bool get hasSurvey => _postSurvey != null; bool get hasSurvey => _postSurvey != null;
bool get hasYoutTubeID => _youtubeID != null;
bool get canSubmitForm => bool get canSubmitForm =>
!_isCreating && _postTextController.text.length > 5 || !_isCreating && _postTextController.text.length > 5 ||
postKind != PostKind.TEXT; postKind != PostKind.TEXT;
@ -80,6 +84,8 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
return PostKind.COUNTDOWN; return PostKind.COUNTDOWN;
else if (hasSurvey) else if (hasSurvey)
return PostKind.SURVEY; return PostKind.SURVEY;
else if (hasYoutTubeID)
return PostKind.YOUTUBE;
else else
return PostKind.TEXT; return PostKind.TEXT;
} }
@ -158,6 +164,13 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
selected: postKind == PostKind.SURVEY, selected: postKind == PostKind.SURVEY,
onTap: _pickSurvey, onTap: _pickSurvey,
), ),
// Specify YouTube video ID
_PostOptionWidget(
icon: Icons.ondemand_video,
selected: postKind == PostKind.YOUTUBE,
onTap: _pickYouTubeVideo,
),
], ],
), ),
), ),
@ -222,6 +235,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
_postPDF = null; _postPDF = null;
_timeEnd = null; _timeEnd = null;
_postSurvey = null; _postSurvey = null;
_youtubeID = null;
}); });
} }
@ -322,6 +336,20 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
}); });
} }
/// Pick a new YouTube video
Future<void> _pickYouTubeVideo() async {
final youtubeID = await showInputYouTubeIDDialog(context, _youtubeID);
if (youtubeID == null) return;
_resetPostSelection();
setState(() {
_youtubeID = youtubeID;
});
}
/// Submit new post /// Submit new post
Future<void> _submitForm() async { Future<void> _submitForm() async {
if (!canSubmitForm) if (!canSubmitForm)
@ -340,7 +368,9 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
url: _postURL, url: _postURL,
pdf: _postPDF, pdf: _postPDF,
timeEnd: _timeEnd, timeEnd: _timeEnd,
survey: _postSurvey)); survey: _postSurvey,
youtubeId: _youtubeID,
));
setState(() => _isCreating = false); setState(() => _isCreating = false);
showSimpleSnack(context, tr("The post has been successfully created!")); showSimpleSnack(context, tr("The post has been successfully created!"));