lemmur-app-android/lib/pages/create_post/create_post.dart

194 lines
6.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:wc_form_validators/wc_form_validators.dart';
import '../../hooks/logged_in_action.dart';
import '../../hooks/stores.dart';
import '../../l10n/l10n.dart';
import '../../stores/accounts_store.dart';
import '../../util/async_store_listener.dart';
import '../../util/extensions/spaced.dart';
import '../../util/mobx_provider.dart';
import '../../util/observer_consumers.dart';
import '../../widgets/editor/editor.dart';
import '../../widgets/markdown_mode_icon.dart';
import 'create_post_community_picker.dart';
import 'create_post_instance_picker.dart';
import 'create_post_store.dart';
import 'create_post_url_field.dart';
/// Modal for creating a post to some community in some instance
/// Pops the navigator stack with a [PostView]
class CreatePostPage extends HookWidget {
const CreatePostPage();
@override
Widget build(BuildContext context) {
final formKey = useMemoized(GlobalKey<FormState>.new);
final loggedInAction = useLoggedInAction(
useStore((CreatePostStore store) => store.instanceHost),
);
final titleFocusNode = useFocusNode();
handleSubmit(Jwt token) async {
if (formKey.currentState!.validate()) {
await context.read<CreatePostStore>().submit(token);
}
}
final title = ObserverBuilder<CreatePostStore>(
builder: (context, store) => TextFormField(
initialValue: store.title,
focusNode: titleFocusNode,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.sentences,
textInputAction: TextInputAction.next,
validator: Validators.required(L10n.of(context).required_field),
onChanged: (title) => store.title = title,
minLines: 1,
maxLines: 2,
decoration: InputDecoration(labelText: L10n.of(context).title),
),
);
final bodyController =
useTextEditingController(text: context.read<CreatePostStore>().body);
final body = ObserverBuilder<CreatePostStore>(
builder: (context, store) => Editor(
controller: bodyController,
onChanged: (body) => store.body = body,
labelText: L10n.of(context).body,
instanceHost: store.instanceHost,
fancy: store.showFancy,
),
);
return AsyncStoreListener<PostView>(
asyncStore: context.read<CreatePostStore>().submitState,
onSuccess: (context, data) {
Navigator.of(context).pop(data);
},
child: Scaffold(
appBar: AppBar(
actions: [
ObserverBuilder<CreatePostStore>(
builder: (context, store) => IconButton(
icon: markdownModeIcon(fancy: store.showFancy),
onPressed: () => store.showFancy = !store.showFancy,
),
),
],
),
body: Stack(
children: [
SafeArea(
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.all(5),
child: Form(
key: formKey,
child: Column(
children: [
if (!context.read<CreatePostStore>().isEdit) ...const [
CreatePostInstancePicker(),
CreatePostCommunityPicker(),
],
CreatePostUrlField(titleFocusNode),
title,
body,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ObserverBuilder<CreatePostStore>(
builder: (context, store) => GestureDetector(
onTap: () => store.nsfw = !store.nsfw,
child: Row(
children: [
Checkbox(
value: store.nsfw,
onChanged: (val) {
if (val != null) store.nsfw = val;
},
),
Text(L10n.of(context).nsfw)
],
),
),
),
ObserverBuilder<CreatePostStore>(
builder: (context, store) => TextButton(
onPressed: store.submitState.isLoading
? () {}
: loggedInAction(handleSubmit),
child: store.submitState.isLoading
? const CircularProgressIndicator.adaptive()
: Text(
store.isEdit
? L10n.of(context).edit
: L10n.of(context).post,
),
),
)
],
),
EditorToolbar.safeArea,
].spaced(6),
),
),
),
),
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Spacer(),
EditorToolbar(
controller: bodyController,
instanceHost: context.read<CreatePostStore>().instanceHost,
),
],
),
),
],
),
),
);
}
static Route<PostView> route() => MaterialPageRoute(
builder: (context) => MobxProvider(
create: (context) => CreatePostStore(
instanceHost: context.read<AccountsStore>().loggedInInstances.first,
),
child: const CreatePostPage(),
),
fullscreenDialog: true,
);
static Route<PostView> toCommunityRoute(CommunityView community) =>
MaterialPageRoute(
builder: (context) => MobxProvider(
create: (context) => CreatePostStore(
instanceHost: community.instanceHost,
selectedCommunity: community,
),
child: const CreatePostPage(),
),
fullscreenDialog: true,
);
static Route<PostView> editRoute(Post post) => MaterialPageRoute(
builder: (context) => MobxProvider(
create: (context) => CreatePostStore(
instanceHost: post.instanceHost,
postToEdit: post,
),
child: const CreatePostPage(),
),
fullscreenDialog: true,
);
}