loris/lib/dialogues/full_post_view.dart

274 lines
8.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:localization/localization.dart';
import 'package:loris/business_logic/network_tools/get_post_from_url.dart';
import 'package:loris/business_logic/posts/posts.dart';
import 'package:loris/business_logic/timeline/timeline.dart';
import 'package:loris/global.dart' as global;
import 'package:loris/themes/themes.dart' as themes;
import '../partials/post.dart';
class FullPostView extends StatefulWidget {
const FullPostView({
super.key,
required this.originPostModel,
this.identities,
this.hidden = true,
this.ancestors,
this.descendants,
this.forceSensitive = false,
});
final PostModel originPostModel;
final Map<String, PostModel>? identities;
final bool hidden;
final List<PostModel>? ancestors;
final List<PostModel>? descendants;
final bool forceSensitive;
@override
State<FullPostView> createState() => _FullPostViewState();
}
class _FullPostViewState extends State<FullPostView> {
List<PostModel> ancestors = [];
List<PostModel> descendants = [];
Map<String, PostModel> identities = {};
String activeIdentity = "";
int idsChecked = 1;
bool sensitive = false;
void loadIdentities() async {
global.settings!.identities.forEach((key, value) async {
if (!identities.containsKey(key)) {
final r = await getPostFromUrl(key, widget.originPostModel.uri);
if (r.values.first != null && mounted) {
setState(() {
identities.addAll({key: r.values.first!});
});
}
if (mounted) {
setState(() {
idsChecked++;
});
}
}
});
}
void loadPosts() async {
if (widget.ancestors == null || widget.descendants == null) {
final r = await getContextForPost(widget.originPostModel);
if (r.value != null && mounted) {
setState(() {
ancestors = r.value!.ancestors;
descendants = r.value!.descendants;
});
}
for (var a in ancestors) {
if (a.sensitive) {
sensitive = true;
}
}
for (var d in descendants) {
if (d.sensitive) {
sensitive = true;
}
}
}
}
@override
void initState() {
if (widget.ancestors != null) {
ancestors = widget.ancestors!;
}
if (widget.descendants != null) {
descendants = widget.descendants!;
}
sensitive = widget.originPostModel.sensitive;
if (widget.identities != null) {
idsChecked = global.settings!.identities.length;
}
identities = widget.identities ?? {};
identities.addAll({
widget.originPostModel.identity: widget.originPostModel,
});
activeIdentity = widget.originPostModel.identity;
loadPosts();
loadIdentities();
super.initState();
}
@override
Widget build(BuildContext context) {
List<DropdownMenuItem<String>> dropdownButtons = [];
identities.forEach((key, value) {
dropdownButtons.add(
DropdownMenuItem(
alignment: Alignment.center,
value: key,
child: Text(key, style: Theme.of(context).textTheme.bodyMedium),
),
);
});
return SimpleDialog(
contentPadding: const EdgeInsets.fromLTRB(0, 24, 0, 0),
children: [
global.settings!.identities.length > idsChecked
? Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SelectableText(
"${"post-found-on".i18n()} $idsChecked ${idsChecked == 1 ? "instance".i18n() : "instances".i18n()}",
textAlign: TextAlign.center,
),
const LinearProgressIndicator(),
],
)
: Padding(
padding: themes.defaultInsideMargins,
child: Wrap(
alignment: WrapAlignment.spaceAround,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
DropdownButtonHideUnderline(
child: DropdownButton<String>(
alignment: Alignment.center,
value: activeIdentity,
style: Theme.of(context).textTheme.bodyMedium,
iconEnabledColor:
Theme.of(context).colorScheme.onSurface,
items: dropdownButtons,
onChanged: (value) {
setState(() {
Navigator.of(context).pop();
showDialog(
context: context,
builder: (context) => FullPostView(
originPostModel: identities[value]!,
identities: identities,
),
);
});
loadPosts();
},
),
),
if (sensitive || widget.forceSensitive)
ElevatedButton.icon(
onPressed: () {
setState(() {
Navigator.of(context).pop();
showDialog(
context: context,
builder: (context) => FullPostView(
originPostModel: widget.originPostModel,
hidden: !widget.hidden,
identities: identities,
ancestors: ancestors,
descendants: descendants,
forceSensitive: true,
),
);
});
},
icon: Icon(widget.hidden
? Icons.visibility
: Icons.visibility_off),
label: Text(
widget.hidden ? "show".i18n() : "hide".i18n(),
),
),
],
),
),
Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 2 / 3,
maxWidth: global.getConstraints(context).maxWidth),
width: global.getWidth(context),
child: SingleChildScrollView(
child: Padding(
padding: themes.defaultMargins,
child: SingleFullPostDisplay(
ancestors: ancestors,
descendants: descendants,
hidden: widget.hidden,
level: 0,
model: identities[activeIdentity]!.reblog ??
identities[activeIdentity]!,
),
),
),
)
],
);
}
}
class SingleFullPostDisplay extends StatelessWidget {
const SingleFullPostDisplay({
super.key,
required this.level,
required this.model,
required this.ancestors,
required this.descendants,
this.hidden = true,
});
final int level;
final PostModel model;
final List<PostModel> ancestors;
final List<PostModel> descendants;
final bool hidden;
@override
Widget build(BuildContext context) {
List<Post> ancestorWidgets = ancestors
.map(
(e) => Post(model: e, hideSensitive: hidden),
)
.toList();
List<Widget> descendantsWidgets = [];
// seems most efficient
// considering that lists aren't v long
for (var element in descendants) {
if (element.inReplyTo == model.id) {
descendantsWidgets.add(SingleFullPostDisplay(
level: level + 1,
model: element,
ancestors: const [],
descendants: descendants,
hidden: hidden,
));
}
}
List<Widget> c = [];
c.addAll(ancestorWidgets);
c.add(Post(
model: model,
hideSensitive: hidden,
));
c.addAll(descendantsWidgets);
return Container(
padding:
EdgeInsets.fromLTRB(level == 0 ? 0 : 4, 0, level == 0 ? 0 : 4, 0),
decoration: BoxDecoration(
border: level == 0
? const Border()
: Border(
left: BorderSide(
width: 4,
color: level.isEven
? Theme.of(context).colorScheme.secondary
: Theme.of(context).colorScheme.primary,
),
),
),
child: Column(children: c));
}
}