Skip to content
This repository has been archived by the owner on Feb 4, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' into feature/more-settings
Browse files Browse the repository at this point in the history
  • Loading branch information
shilangyu authored Apr 21, 2021
2 parents 1e06533 + 9b032e7 commit d8dcea0
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 81 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
- Show scores setting toggle
- Default listing type for the home tab setting
- Import Lemmy settings: long press an account in account settings then choose the import option
- Editing posts
- Editing comments

### Fixed

- Fixed bug where creating post would crash after uploading a picture

## v0.4.2 - 2021-04-12

### Changed
Expand Down
146 changes: 90 additions & 56 deletions lib/pages/create_post.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import '../util/extensions/api.dart';
import '../util/extensions/spaced.dart';
import '../util/goto.dart';
import '../util/pictrs.dart';
import '../util/unawaited.dart';
import '../widgets/editor.dart';
import '../widgets/markdown_mode_icon.dart';
import '../widgets/markdown_text.dart';
import '../widgets/radio_picker.dart';
import 'full_post.dart';

/// Fab that triggers the [CreatePost] modal
/// After creation it will navigate to the newly created post
class CreatePostFab extends HookWidget {
final CommunityView? community;

Expand All @@ -32,34 +32,60 @@ class CreatePostFab extends HookWidget {
final loggedInAction = useAnyLoggedInAction();

return FloatingActionButton(
onPressed: loggedInAction((_) => showCupertinoModalPopup(
onPressed: loggedInAction((_) async {
final postView = await showCupertinoModalPopup<PostView>(
context: context,
builder: (_) => community == null
? const CreatePostPage()
: CreatePostPage.toCommunity(community!))),
: CreatePostPage.toCommunity(community!),
);

if (postView != null) {
await goTo(
context,
(_) => FullPostPage.fromPostView(postView),
);
}
}),
child: const Icon(Icons.add),
);
}
}

/// Modal for creating a post to some community in some instance
/// Pops the navigator stack with a [PostView]
class CreatePostPage extends HookWidget {
final CommunityView? community;

const CreatePostPage() : community = null;
const CreatePostPage.toCommunity(CommunityView this.community);
final bool _isEdit;
final Post? post;

const CreatePostPage()
: community = null,
_isEdit = false,
post = null;
const CreatePostPage.toCommunity(CommunityView this.community)
: _isEdit = false,
post = null;
const CreatePostPage.edit(this.post)
: _isEdit = true,
community = null;

@override
Widget build(BuildContext context) {
final urlController = useTextEditingController();
final titleController = useTextEditingController();
final bodyController = useTextEditingController();
final urlController =
useTextEditingController(text: _isEdit ? post?.url : null);
final titleController =
useTextEditingController(text: _isEdit ? post?.name : null);
final bodyController =
useTextEditingController(text: _isEdit ? post?.body : null);
final accStore = useAccountsStore();
final selectedInstance =
useState(community?.instanceHost ?? accStore.loggedInInstances.first);
final selectedInstance = useState(_isEdit
? post!.instanceHost
: community?.instanceHost ?? accStore.loggedInInstances.first);
final selectedCommunity = useState(community);
final showFancy = useState(false);
final nsfw = useState(false);
final nsfw = useState(_isEdit && post!.nsfw);
final delayed = useDelayedLoading();
final imagePicker = useImagePicker();
final imageUploadLoading = useState(false);
Expand Down Expand Up @@ -100,7 +126,6 @@ class CreatePostPage extends HookWidget {
urlController.text =
pathToPictrs(selectedInstance.value, upload.files[0].file);
}
print(urlController.text);
// ignore: avoid_catches_without_on_clauses
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
Expand All @@ -120,7 +145,7 @@ class CreatePostPage extends HookWidget {
final instanceDropdown = RadioPicker<String>(
values: accStore.loggedInInstances.toList(),
groupValue: selectedInstance.value,
onChanged: (value) => selectedInstance.value = value,
onChanged: _isEdit ? null : (value) => selectedInstance.value = value,
buttonBuilder: (context, displayValue, onPressed) => TextButton(
onPressed: onPressed,
child: Row(
Expand Down Expand Up @@ -159,7 +184,8 @@ class CreatePostPage extends HookWidget {
}

handleSubmit(Jwt token) async {
if (selectedCommunity.value == null || titleController.text.isEmpty) {
if ((!_isEdit && selectedCommunity.value == null) ||
titleController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Choosing a community and a title is required'),
));
Expand All @@ -170,15 +196,28 @@ class CreatePostPage extends HookWidget {

delayed.start();
try {
final res = await api.run(CreatePost(
url: urlController.text.isEmpty ? null : urlController.text,
body: bodyController.text.isEmpty ? null : bodyController.text,
nsfw: nsfw.value,
name: titleController.text,
communityId: selectedCommunity.value!.community.id,
auth: token.raw,
));
unawaited(goToReplace(context, (_) => FullPostPage.fromPostView(res)));
final res = await () {
if (_isEdit) {
return api.run(EditPost(
url: urlController.text.isEmpty ? null : urlController.text,
body: bodyController.text.isEmpty ? null : bodyController.text,
nsfw: nsfw.value,
name: titleController.text,
postId: post!.id,
auth: token.raw,
));
} else {
return api.run(CreatePost(
url: urlController.text.isEmpty ? null : urlController.text,
body: bodyController.text.isEmpty ? null : bodyController.text,
nsfw: nsfw.value,
name: titleController.text,
communityId: selectedCommunity.value!.community.id,
auth: token.raw,
));
}
}();
Navigator.of(context).pop(res);
return;
// ignore: avoid_catches_without_on_clauses
} catch (e) {
Expand All @@ -191,27 +230,34 @@ class CreatePostPage extends HookWidget {
// TODO: use lazy autocomplete
final communitiesDropdown = InputDecorator(
decoration: const InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 1, horizontal: 20),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)))),
contentPadding: EdgeInsets.symmetric(vertical: 1, horizontal: 20),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<int>(
value: selectedCommunity.value?.community.id,
hint: Text(L10n.of(context)!.community),
onChanged: (communityId) => selectedCommunity.value =
allCommunitiesSnap.data
?.firstWhere((e) => e.community.id == communityId),
onChanged: _isEdit
? null
: (communityId) {
selectedCommunity.value = allCommunitiesSnap.data
?.firstWhere((e) => e.community.id == communityId);
},
items: communitiesList(),
),
),
);

final enabledUrlField = pictrsDeleteToken.value == null;

final url = Row(children: [
Expanded(
child: TextField(
enabled: pictrsDeleteToken.value == null,
enabled: enabledUrlField,
controller: urlController,
autofillHints: const [AutofillHints.url],
autofillHints: enabledUrlField ? const [AutofillHints.url] : null,
keyboardType: TextInputType.url,
onSubmitted: (_) => titleFocusNode.requestFocus(),
decoration: InputDecoration(
Expand Down Expand Up @@ -246,28 +292,14 @@ class CreatePostPage extends HookWidget {
decoration: InputDecoration(labelText: L10n.of(context)!.title),
);

final body = IndexedStack(
index: showFancy.value ? 1 : 0,
children: [
TextField(
controller: bodyController,
focusNode: bodyFocusNode,
keyboardType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
onSubmitted: (_) =>
delayed.pending ? () {} : loggedInAction(handleSubmit),
maxLines: null,
minLines: 5,
decoration: InputDecoration(labelText: L10n.of(context)!.body),
),
Padding(
padding: const EdgeInsets.all(16),
child: MarkdownText(
bodyController.text,
instanceHost: selectedInstance.value,
),
),
],
final body = Editor(
controller: bodyController,
focusNode: bodyFocusNode,
onSubmitted: (_) =>
delayed.pending ? () {} : loggedInAction(handleSubmit),
labelText: L10n.of(context)!.body,
instanceHost: selectedInstance.value,
fancy: showFancy.value,
);

return Scaffold(
Expand All @@ -285,7 +317,7 @@ class CreatePostPage extends HookWidget {
padding: const EdgeInsets.all(5),
children: [
instanceDropdown,
communitiesDropdown,
if (!_isEdit) communitiesDropdown,
url,
title,
body,
Expand All @@ -311,7 +343,9 @@ class CreatePostPage extends HookWidget {
delayed.pending ? () {} : loggedInAction(handleSubmit),
child: delayed.loading
? const CircularProgressIndicator()
: Text(L10n.of(context)!.post),
: Text(_isEdit
? L10n.of(context)!.edit
: L10n.of(context)!.post),
)
],
),
Expand Down
9 changes: 7 additions & 2 deletions lib/pages/full_post.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,13 @@ class FullPostPage extends HookWidget {
IconButton(icon: const Icon(Icons.share), onPressed: sharePost),
SavePostButton(post),
IconButton(
icon: Icon(moreIcon),
onPressed: () => PostWidget.showMoreMenu(context, post)),
icon: Icon(moreIcon),
onPressed: () => PostWidget.showMoreMenu(
context: context,
post: post,
fullPost: true,
),
),
],
),
floatingActionButton: post.post.locked
Expand Down
58 changes: 58 additions & 0 deletions lib/widgets/editor.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

import 'markdown_text.dart';

/// A text field with added functionality for ease of editing
class Editor extends HookWidget {
final TextEditingController? controller;
final FocusNode? focusNode;
final ValueChanged<String>? onSubmitted;
final int? minLines;
final String? labelText;
final bool autofocus;

/// Whether the editor should be preview the contents
final bool fancy;
final String instanceHost;

const Editor({
Key? key,
this.controller,
this.focusNode,
this.onSubmitted,
this.minLines = 5,
this.labelText,
this.fancy = false,
required this.instanceHost,
this.autofocus = false,
}) : super(key: key);

@override
Widget build(BuildContext context) {
final defaultController = useTextEditingController();
final actualController = controller ?? defaultController;

if (fancy) {
return Padding(
padding: const EdgeInsets.all(8),
child: MarkdownText(
actualController.text,
instanceHost: instanceHost,
),
);
}

return TextField(
controller: actualController,
focusNode: focusNode,
autofocus: autofocus,
keyboardType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
onSubmitted: onSubmitted,
maxLines: null,
minLines: minLines,
decoration: InputDecoration(labelText: labelText),
);
}
}
Loading

0 comments on commit d8dcea0

Please sign in to comment.