Skip to content

Commit

Permalink
Ability to create post without being in community feed (#836)
Browse files Browse the repository at this point in the history
* Ability to create post without being in community feed

* Show subscriptions as new post community suggestions
  • Loading branch information
micahmo authored Oct 19, 2023
1 parent 1e9403c commit 12564cb
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Added support for accessibility profiles in settings - contribution from @micahmo
- Added option to enable/disable full screen navigation swipe gesture to go back (applies when LTR gestures are disabled)
- Introduced support for reporting comments. - contribution from @ggichure
- Added ability to create post from home feed - contribution from @micahmo
- Added option to enter reader mode when tapping on a link in iOS

### Changed
Expand Down
78 changes: 58 additions & 20 deletions lib/community/pages/create_post_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:markdown_editable_textinput/format_markdown.dart';
import 'package:markdown_editable_textinput/markdown_buttons.dart';
import 'package:markdown_editable_textinput/markdown_text_input_field.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/account/bloc/account_bloc.dart';

import 'package:thunder/community/bloc/image_bloc.dart';
import 'package:thunder/core/enums/view_mode.dart';
Expand All @@ -21,15 +22,15 @@ import 'package:thunder/utils/image.dart';
import 'package:thunder/utils/instance.dart';

class CreatePostPage extends StatefulWidget {
final int communityId;
final FullCommunityView? communityInfo;
final int? communityId;
final CommunityView? communityView;
final void Function(DraftPost? draftPost)? onUpdateDraft;
final DraftPost? previousDraftPost;

const CreatePostPage({
super.key,
required this.communityId,
this.communityInfo,
this.communityView,
this.previousDraftPost,
this.onUpdateDraft,
});
Expand All @@ -48,6 +49,9 @@ class _CreatePostPageState extends State<CreatePostPage> {
String? urlError;
DraftPost newDraftPost = DraftPost();

int? communityId;
CommunityView? communityView;

final TextEditingController _bodyTextController = TextEditingController();
final TextEditingController _titleTextController = TextEditingController();
final TextEditingController _urlTextController = TextEditingController();
Expand All @@ -58,6 +62,9 @@ class _CreatePostPageState extends State<CreatePostPage> {
void initState() {
super.initState();

communityId = widget.communityId;
communityView = widget.communityView;

_titleTextController.addListener(() {
_validateSubmission();

Expand Down Expand Up @@ -104,6 +111,8 @@ class _CreatePostPageState extends State<CreatePostPage> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final AccountState accountState = context.read<AccountBloc>().state;

return GestureDetector(
onTap: () {
// Dismiss keyboard when we go tap anywhere on the screen
Expand All @@ -120,8 +129,8 @@ class _CreatePostPageState extends State<CreatePostPage> {
: () {
newDraftPost.saveAsDraft = false;
url != ''
? context.read<FeedBloc>().add(CreatePostEvent(communityId: widget.communityId, name: _titleTextController.text, body: _bodyTextController.text, nsfw: isNSFW, url: url))
: context.read<FeedBloc>().add(CreatePostEvent(communityId: widget.communityId, name: _titleTextController.text, body: _bodyTextController.text, nsfw: isNSFW));
? context.read<FeedBloc>().add(CreatePostEvent(communityId: communityId!, name: _titleTextController.text, body: _bodyTextController.text, nsfw: isNSFW, url: url))
: context.read<FeedBloc>().add(CreatePostEvent(communityId: communityId!, name: _titleTextController.text, body: _bodyTextController.text, nsfw: isNSFW));
Navigator.of(context).pop();
},
icon: Icon(
Expand Down Expand Up @@ -166,21 +175,50 @@ class _CreatePostPageState extends State<CreatePostPage> {
Expanded(
child: SingleChildScrollView(
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
const SizedBox(height: 12.0),
Row(
children: [
CommunityIcon(community: widget.communityInfo?.communityView.community, radius: 16),
const SizedBox(
width: 12,
),
Text(
'${widget.communityInfo?.communityView.community.name} '
'· ${fetchInstanceNameFromUrl(widget.communityInfo?.communityView.community.actorId)}',
style: theme.textTheme.titleSmall,
Transform.translate(
offset: const Offset(-8, 0),
child: InkWell(
onTap: () {
showCommunityInputDialog(
context,
title: AppLocalizations.of(context)!.community,
onCommunitySelected: (cv) {
setState(() {
communityId = cv.community.id;
communityView = cv;
});
_validateSubmission();
},
emptySuggestions: accountState.subsciptions,
);
},
borderRadius: const BorderRadius.all(Radius.circular(50)),
child: Padding(
padding: const EdgeInsets.only(left: 8, top: 12, bottom: 12),
child: Row(
children: [
CommunityIcon(community: communityView?.community, radius: 16),
const SizedBox(
width: 12,
),
communityId != null
? Text(
'${communityView?.community.name} '
'· ${fetchInstanceNameFromUrl(communityView?.community.actorId)}',
style: theme.textTheme.titleSmall,
)
: Text(
AppLocalizations.of(context)!.selectCommunity,
style: theme.textTheme.bodyMedium?.copyWith(
fontStyle: FontStyle.italic,
color: theme.colorScheme.error,
),
),
],
),
),
],
),
),
const SizedBox(height: 12.0),
const UserIndicator(),
const SizedBox(height: 12.0),
TextFormField(
Expand Down Expand Up @@ -352,15 +390,15 @@ class _CreatePostPageState extends State<CreatePostPage> {

if (isSubmitButtonDisabled) {
// It's disabled, check if we can enable it.
if (_titleTextController.text.isNotEmpty && parsedUrl != null) {
if (_titleTextController.text.isNotEmpty && parsedUrl != null && communityId != null) {
setState(() {
isSubmitButtonDisabled = false;
urlError = null;
});
}
} else {
// It's enabled, check if we need to disable it.
if (_titleTextController.text.isEmpty || parsedUrl == null) {
if (_titleTextController.text.isEmpty || parsedUrl == null || communityId == null) {
setState(() {
isSubmitButtonDisabled = true;
urlError = parsedUrl == null ? AppLocalizations.of(context)!.notValidUrl : null;
Expand Down
2 changes: 1 addition & 1 deletion lib/community/widgets/community_sidebar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ class CommunityActions extends StatelessWidget {
],
child: CreatePostPage(
communityId: communityView.community.id,
communityInfo: fullCommunityView,
communityView: fullCommunityView.communityView,
previousDraftPost: previousDraftPost,
onUpdateDraft: (p) => newDraftPost = p,
),
Expand Down
10 changes: 4 additions & 6 deletions lib/feed/widgets/feed_fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ class FeedFAB extends StatelessWidget {
final FeedState feedState = context.watch<FeedBloc>().state;

// A list of actions that are not supported through the general feed
List<FeedFabAction> unsupportedGeneralFeedFabActions = [
FeedFabAction.newPost,
];
List<FeedFabAction> unsupportedGeneralFeedFabActions = [];

// A list of actions that are not supported through the navigated community feed
List<FeedFabAction> unsupportedNavigatedCommunityFeedFabActions = [
Expand Down Expand Up @@ -221,7 +219,7 @@ class FeedFAB extends StatelessWidget {
triggerScrollToTop(context);
},
),
if (enableNewPost && context.read<FeedBloc>().state.feedType == FeedType.community)
if (enableNewPost)
ActionButton(
title: FeedFabAction.newPost.title,
icon: Icon(FeedFabAction.newPost.icon),
Expand Down Expand Up @@ -305,8 +303,8 @@ class FeedFAB extends StatelessWidget {
BlocProvider<AccountBloc>.value(value: accountBloc),
],
child: CreatePostPage(
communityId: feedBloc.state.communityId!,
communityInfo: feedBloc.state.fullCommunityView,
communityId: feedBloc.state.communityId,
communityView: feedBloc.state.fullCommunityView?.communityView,
previousDraftPost: previousDraftPost,
onUpdateDraft: (p) => newDraftPost = p,
),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"@trendingCommunities": {},
"confirmLogOut": "Log out?",
"@confirmLogOut": {},
"selectCommunity": "Select a community",
"feed": "Feed",
"@feed": {},
"search": "Search",
Expand Down
8 changes: 4 additions & 4 deletions lib/shared/input_dialogs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Widget buildUserSuggestionWidget(PersonViewSafe payload, {void Function(PersonVi
}

/// Shows a dialog which allows typing/search for a community
void showCommunityInputDialog(BuildContext context, {required String title, required void Function(CommunityView) onCommunitySelected}) async {
void showCommunityInputDialog(BuildContext context, {required String title, required void Function(CommunityView) onCommunitySelected, Iterable<CommunityView>? emptySuggestions}) async {
Future<String?> onSubmitted({CommunityView? payload, String? value}) async {
if (payload != null) {
onCommunitySelected(payload);
Expand Down Expand Up @@ -123,14 +123,14 @@ void showCommunityInputDialog(BuildContext context, {required String title, requ
title: title,
inputLabel: AppLocalizations.of(context)!.community,
onSubmitted: onSubmitted,
getSuggestions: getCommunitySuggestions,
getSuggestions: (query) => getCommunitySuggestions(query, emptySuggestions),
suggestionBuilder: buildCommunitySuggestionWidget,
);
}

Future<Iterable<CommunityView>> getCommunitySuggestions(String query) async {
Future<Iterable<CommunityView>> getCommunitySuggestions(String query, Iterable<CommunityView>? emptySuggestions) async {
if (query.isNotEmpty != true) {
return const Iterable.empty();
return emptySuggestions ?? const Iterable.empty();
}
Account? account = await fetchActiveProfileAccount();
final SearchResults searchReults = await LemmyClient.instance.lemmyApiV3.run(Search(
Expand Down

0 comments on commit 12564cb

Please sign in to comment.