loris/lib/dialogues/makepost.dart

242 lines
6.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:localization/localization.dart';
import 'package:loris/business_logic/instance/instance.dart';
import 'package:loris/business_logic/network_tools/get_post_from_url.dart';
import 'package:loris/business_logic/timeline/timeline.dart' as tl;
import '../business_logic/posting/posting.dart';
import '../partials/post.dart';
import 'package:loris/global.dart' as global;
class MakePost extends StatefulWidget {
const MakePost({Key? key, this.inReplyTo}) : super(key: key);
final tl.PostModel? inReplyTo;
@override
State<MakePost> createState() => _MakePostState();
}
class _MakePostState extends State<MakePost> {
String accountid = global.settings!.activeIdentity;
int? maxLength;
String text = "";
String spoilerText = "";
// stores all identities and if available the post id you are replying to
Map<String, String?> identitiesAvailable = {};
tl.Visibility visibility = tl.Visibility.public;
void switchAccount(String acct) {
setState(() {
maxLength = null;
accountid = acct;
});
updateMaxChars();
}
void updateMaxChars() async {
final info = await instanceInformationForIdentity(accountid);
if (info.keys.first == 200) {
setState(() {
maxLength = info.values.first!.configuration.statusconfig.maxChars;
});
}
}
void updateAvailableIds() async {
if (widget.inReplyTo != null) {
global.settings!.identities.forEach((key, value) async {
final post = await getPostFromUrl(key, widget.inReplyTo!.uri);
if (post.keys.first == 200) {
setState(() {
identitiesAvailable.addAll({key: post.values.first!.id});
});
}
});
}
}
@override
void initState() {
if (widget.inReplyTo != null) {
accountid = widget.inReplyTo!.identity;
identitiesAvailable.addAll({
widget.inReplyTo!.identity: widget.inReplyTo!.id,
});
} else {
global.settings!.identities.forEach((key, value) {
if (!identitiesAvailable.containsKey(DropdownMenuItem(
value: key,
child: Text(key),
))) {
identitiesAvailable.addAll({key: null});
}
});
}
if (widget.inReplyTo != null) {
spoilerText = widget.inReplyTo!.spoilerText;
}
super.initState();
updateMaxChars();
updateAvailableIds();
}
@override
Widget build(BuildContext context) {
List<Widget> c = [];
if (widget.inReplyTo != null) {
c.add(
Post(
model: widget.inReplyTo!,
reblogVisible: false,
hideActionBar: true,
),
);
}
List<DropdownMenuItem<String>> idDropdownItems = [];
identitiesAvailable.forEach((key, value) {
idDropdownItems.add(DropdownMenuItem(
value: key,
alignment: Alignment.center,
child: Text(
key,
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
));
});
List<DropdownMenuItem<tl.Visibility>> visibilityDropdowns = [];
for (var value in tl.Visibility.values) {
visibilityDropdowns.add(DropdownMenuItem(
value: value,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(value.icon),
Text(
value.name,
style: Theme.of(context).textTheme.bodyMedium,
),
],
)));
}
List<Widget> actionButtons = [
maxLength == null
? const CircularProgressIndicator()
: SelectableText((maxLength! - text.length).toString()),
DropdownButtonHideUnderline(
child: DropdownButton<tl.Visibility>(
alignment: Alignment.center,
iconEnabledColor: Theme.of(context).colorScheme.onSurface,
items: visibilityDropdowns,
value: visibility,
onChanged: (value) {
setState(() {
visibility = value ?? tl.Visibility.private;
});
},
),
),
DropdownButtonHideUnderline(
child: DropdownButton<String>(
alignment: Alignment.center,
borderRadius: BorderRadius.circular(8),
iconEnabledColor: Theme.of(context).colorScheme.onSurface,
items: idDropdownItems,
value: accountid,
onChanged: (value) {
switchAccount(value as String);
},
),
),
OutlinedButton.icon(
label: Text(
"send-post".i18n(),
),
// send the post!!!
onPressed: () async {
final model = MakePostModel(
spoilerText: spoilerText,
identity: accountid,
status: text,
visibility: visibility,
inReplyToId: widget.inReplyTo == null
? null
: identitiesAvailable[accountid]!,
);
model.sendPost();
Navigator.of(context).pop();
},
icon: const Icon(Icons.send),
),
];
c.addAll([
TextFormField(
style: Theme.of(context).textTheme.bodyMedium,
initialValue: spoilerText,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.warning,
color: Theme.of(context).colorScheme.onSurface,
),
labelText: "content-warning".i18n(),
),
onChanged: ((value) => setState(() {
spoilerText = value;
})),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: TextFormField(
style: Theme.of(context).textTheme.bodyMedium,
maxLines: null,
expands: true,
onChanged: (value) {
setState(() {
text = value;
});
},
),
),
const SizedBox(
height: 24,
),
Wrap(
runSpacing: 8,
spacing: 24,
direction: Axis.horizontal,
crossAxisAlignment: WrapCrossAlignment.center,
alignment: WrapAlignment.spaceAround,
children: actionButtons,
),
]);
return SimpleDialog(
alignment: Alignment.center,
contentPadding: const EdgeInsets.all(24),
title: SelectableText(
textAlign: TextAlign.center,
widget.inReplyTo == null ? "make-post".i18n() : "make-reply".i18n(),
style: Theme.of(context).textTheme.displayMedium),
children: [
SingleChildScrollView(
child: Container(
width: (MediaQuery.of(context).size.width *
global.settings!.postWidth) -
56,
constraints: BoxConstraints(
maxWidth: global.settings!.maxPostWidth,
minWidth: 375,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: c,
),
),
),
],
);
}
}