Initial refactor

This commit is contained in:
shilangyu 2022-01-15 16:15:55 +01:00
parent 11d63e0522
commit a821681903
12 changed files with 313 additions and 17 deletions

View File

@ -345,5 +345,7 @@
"add_instance": "Add instance",
"@add_instance": {},
"instance_added": "Instance successfully added",
"@instance_added": {}
"@instance_added": {},
"required_field": "required field",
"@required_field": {}
}

View File

@ -16,7 +16,7 @@ import '../../util/share.dart';
import '../../widgets/failed_to_load.dart';
import '../../widgets/reveal_after_scroll.dart';
import '../../widgets/sortable_infinite_list.dart';
import '../create_post.dart';
import '../create_post/create_post_fab.dart';
import 'community_about_tab.dart';
import 'community_more_menu.dart';
import 'community_overview.dart';

View File

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/v3.dart';
import '../../hooks/logged_in_action.dart';
import '../full_post/full_post.dart';
import 'create_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;
const CreatePostFab({this.community});
@override
Widget build(BuildContext context) {
final loggedInAction = useAnyLoggedInAction();
return FloatingActionButton(
onPressed: loggedInAction((_) async {
final postView = await Navigator.of(context).push(
community == null
? CreatePostPage.route()
: CreatePostPage.toCommunityRoute(community!),
);
if (postView != null) {
await Navigator.of(context)
.push(FullPostPage.fromPostViewRoute(postView));
}
}),
child: const Icon(Icons.add),
);
}
}

View File

@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
import '../../stores/accounts_store.dart';
import '../../util/observer_consumers.dart';
import '../../widgets/radio_picker.dart';
import 'create_post_store.dart';
class CreatePostInstancePicker extends StatelessWidget {
const CreatePostInstancePicker({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final loggedInInstances =
context.watch<AccountsStore>().loggedInInstances.toList();
return ObserverBuilder<CreatePostStore>(
builder: (context, store) => RadioPicker<String>(
values: loggedInInstances,
groupValue: store.instanceHost,
onChanged: store.isEdit ? null : (value) => store.instanceHost = value,
buttonBuilder: (context, displayValue, onPressed) => TextButton(
onPressed: onPressed,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(displayValue),
const Icon(Icons.arrow_drop_down),
],
),
),
),
);
}
}

View File

@ -0,0 +1,63 @@
import 'package:lemmy_api_client/v3.dart';
import 'package:mobx/mobx.dart';
import '../../util/async_store.dart';
part 'create_post_store.g.dart';
class CreatePostStore = _CreatePostStore with _$CreatePostStore;
abstract class _CreatePostStore with Store {
final Post? postToEdit;
bool get isEdit => postToEdit != null;
_CreatePostStore({
required this.instanceHost,
this.postToEdit,
this.selectedCommunity,
}) : title = postToEdit?.name ?? '',
nsfw = postToEdit?.nsfw ?? false,
body = postToEdit?.body ?? '',
url = postToEdit?.url ?? '';
@observable
bool showFancy = false;
@observable
String instanceHost;
@observable
CommunityView? selectedCommunity;
@observable
String url;
@observable
String title;
@observable
String body;
@observable
bool nsfw;
final submitState = AsyncStore<PostView>();
@action
Future<void> submit(Jwt token) async {
await submitState.runLemmy(
instanceHost,
isEdit
? EditPost(
url: url.isEmpty ? null : url,
body: body.isEmpty ? null : body,
nsfw: nsfw,
name: title,
postId: postToEdit!.id,
auth: token.raw,
)
: CreatePost(
url: url.isEmpty ? null : url,
body: body.isEmpty ? null : body,
nsfw: nsfw,
name: title,
communityId: selectedCommunity!.community.id,
auth: token.raw,
),
);
}
}

View File

@ -0,0 +1,137 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'create_post_store.dart';
// **************************************************************************
// StoreGenerator
// **************************************************************************
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
mixin _$CreatePostStore on _CreatePostStore, Store {
final _$showFancyAtom = Atom(name: '_CreatePostStore.showFancy');
@override
bool get showFancy {
_$showFancyAtom.reportRead();
return super.showFancy;
}
@override
set showFancy(bool value) {
_$showFancyAtom.reportWrite(value, super.showFancy, () {
super.showFancy = value;
});
}
final _$instanceHostAtom = Atom(name: '_CreatePostStore.instanceHost');
@override
String get instanceHost {
_$instanceHostAtom.reportRead();
return super.instanceHost;
}
@override
set instanceHost(String value) {
_$instanceHostAtom.reportWrite(value, super.instanceHost, () {
super.instanceHost = value;
});
}
final _$selectedCommunityAtom =
Atom(name: '_CreatePostStore.selectedCommunity');
@override
CommunityView? get selectedCommunity {
_$selectedCommunityAtom.reportRead();
return super.selectedCommunity;
}
@override
set selectedCommunity(CommunityView? value) {
_$selectedCommunityAtom.reportWrite(value, super.selectedCommunity, () {
super.selectedCommunity = value;
});
}
final _$urlAtom = Atom(name: '_CreatePostStore.url');
@override
String get url {
_$urlAtom.reportRead();
return super.url;
}
@override
set url(String value) {
_$urlAtom.reportWrite(value, super.url, () {
super.url = value;
});
}
final _$titleAtom = Atom(name: '_CreatePostStore.title');
@override
String get title {
_$titleAtom.reportRead();
return super.title;
}
@override
set title(String value) {
_$titleAtom.reportWrite(value, super.title, () {
super.title = value;
});
}
final _$bodyAtom = Atom(name: '_CreatePostStore.body');
@override
String get body {
_$bodyAtom.reportRead();
return super.body;
}
@override
set body(String value) {
_$bodyAtom.reportWrite(value, super.body, () {
super.body = value;
});
}
final _$nsfwAtom = Atom(name: '_CreatePostStore.nsfw');
@override
bool get nsfw {
_$nsfwAtom.reportRead();
return super.nsfw;
}
@override
set nsfw(bool value) {
_$nsfwAtom.reportWrite(value, super.nsfw, () {
super.nsfw = value;
});
}
final _$submitAsyncAction = AsyncAction('_CreatePostStore.submit');
@override
Future<void> submit(Jwt token) {
return _$submitAsyncAction.run(() => super.submit(token));
}
@override
String toString() {
return '''
showFancy: ${showFancy},
instanceHost: ${instanceHost},
selectedCommunity: ${selectedCommunity},
url: ${url},
title: ${title},
body: ${body},
nsfw: ${nsfw}
''';
}
}

View File

@ -4,7 +4,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import '../util/extensions/brightness.dart';
import 'communities_tab.dart';
import 'create_post.dart';
import 'create_post/create_post_fab.dart';
import 'home_tab.dart';
import 'profile_tab.dart';
import 'search_tab.dart';

View File

@ -12,10 +12,16 @@ class AsyncStoreListener<T> extends SingleChildStatelessWidget {
T data,
)? successMessageBuilder;
final void Function(
BuildContext context,
T data,
)? onSuccess;
const AsyncStoreListener({
Key? key,
required this.asyncStore,
this.successMessageBuilder,
this.onSuccess,
Widget? child,
}) : super(key: key, child: child);
@ -24,20 +30,27 @@ class AsyncStoreListener<T> extends SingleChildStatelessWidget {
return ObserverListener<AsyncStore<T>>(
store: asyncStore,
listener: (context, store) {
final errorTerm = store.errorTerm;
store.map(
loading: () {},
error: (errorTerm) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(errorTerm.tr(context))));
},
data: (data) {
onSuccess?.call(context, data);
if (errorTerm != null) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(errorTerm.tr(context))));
} else if (store.asyncState is AsyncStateData &&
(successMessageBuilder != null)) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(
content: Text(successMessageBuilder!(
context, (store.asyncState as AsyncStateData).data))));
}
if (successMessageBuilder != null) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Text(successMessageBuilder!(context, data)),
),
);
}
},
);
},
child: child ?? const SizedBox(),
);

View File

@ -8,6 +8,7 @@ class Editor extends HookWidget {
final TextEditingController? controller;
final FocusNode? focusNode;
final ValueChanged<String>? onSubmitted;
final ValueChanged<String>? onChanged;
final int? minLines;
final int? maxLines;
final String? labelText;
@ -22,6 +23,7 @@ class Editor extends HookWidget {
this.controller,
this.focusNode,
this.onSubmitted,
this.onChanged,
this.minLines = 5,
this.maxLines,
this.labelText,
@ -51,6 +53,7 @@ class Editor extends HookWidget {
autofocus: autofocus,
keyboardType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
onChanged: onChanged,
onSubmitted: onSubmitted,
maxLines: maxLines,
minLines: minLines,

View File

@ -3,7 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:url_launcher/url_launcher.dart' as ul;
import '../../hooks/logged_in_action.dart';
import '../../pages/create_post.dart';
import '../../pages/create_post/create_post.dart';
import '../../pages/full_post/full_post_store.dart';
import '../../stores/accounts_store.dart';
import '../../util/icons.dart';

View File

@ -985,6 +985,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
wc_form_validators:
dependency: "direct main"
description:
name: wc_form_validators
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
web_socket_channel:
dependency: transitive
description:

View File

@ -60,6 +60,7 @@ dependencies:
sdk: flutter
flutter_localizations:
sdk: flutter
wc_form_validators: ^1.0.0
dev_dependencies:
flutter_test: