You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fluffychat/lib/pangea/widgets/class/add_space_toggles.dart

269 lines
8.2 KiB
Dart

import 'package:collection/collection.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
import '../../../widgets/matrix.dart';
import '../../utils/firebase_analytics.dart';
//PTODO - auto invite students when you add a space and delete the add_class_and_invite.dart file
class AddToSpaceToggles extends StatefulWidget {
final String? roomId;
final bool startOpen;
final String? activeSpaceId;
final bool spaceMode;
const AddToSpaceToggles({
super.key,
this.roomId,
this.startOpen = false,
this.activeSpaceId,
this.spaceMode = false,
});
@override
AddToSpaceState createState() => AddToSpaceState();
}
class AddToSpaceState extends State<AddToSpaceToggles> {
late Room? room;
late Room? parent;
late List<Room> possibleParents;
late bool isOpen;
late bool isSuggested;
AddToSpaceState({Key? key});
@override
void initState() {
initialize();
super.initState();
}
@override
void didUpdateWidget(AddToSpaceToggles oldWidget) {
if (oldWidget.roomId != widget.roomId) {
initialize();
}
super.didUpdateWidget(oldWidget);
}
void initialize() {
//if roomId is null, it means this widget is being used in the creation flow
room = widget.roomId != null
? Matrix.of(context).client.getRoomById(widget.roomId!)
: null;
isSuggested = true;
room?.isSuggested().then((value) => isSuggested = value);
possibleParents = Matrix.of(context)
.client
.rooms
.where(
(Room r) => r.isSpace && widget.roomId != r.id,
)
.toList();
parent = widget.roomId != null
? possibleParents.firstWhereOrNull(
(r) => r.spaceChildren.any((room) => room.roomId == widget.roomId),
)
: null;
//sort possibleParents
//if possibleParent in parents, put first
//use sort but use any instead of contains because contains uses == and we want to compare by id
possibleParents.sort((a, b) {
if (parent?.id == a.id) {
return -1;
} else if (parent?.id == b.id) {
return 1;
} else {
return a.name.compareTo(b.name);
}
});
isOpen = widget.startOpen;
if (widget.activeSpaceId != null) {
final activeSpace =
Matrix.of(context).client.getRoomById(widget.activeSpaceId!);
if (activeSpace == null) {
ErrorHandler.logError(
e: Exception('activeSpaceId ${widget.activeSpaceId} not found'),
);
return;
}
if (activeSpace.canSendEvent(EventTypes.SpaceChild)) {
parent = activeSpace;
}
}
}
Future<void> _addSingleSpace(String roomToAddId, Room newParent) async {
GoogleAnalytics.addParent(roomToAddId, newParent.classCode);
await newParent.pangeaSetSpaceChild(
roomToAddId,
suggested: isSuggested,
);
}
Future<void> addSpaces(String roomToAddId) async {
if (parent == null) return;
await _addSingleSpace(roomToAddId, parent!);
}
Future<void> handleAdd(bool add, Room possibleParent) async {
//in this case, the room has already been made so we handle adding as it happens
if (room != null) {
await showFutureLoadingDialog(
context: context,
future: () => add
? _addSingleSpace(room!.id, possibleParent)
: possibleParent.removeSpaceChild(room!.id),
onError: (e) {
// if error occurs, do not change value of toggle
add = !add;
return (e as Object?)?.toLocalizedString(context) ??
e?.toString() ??
L10n.of(context)!.oopsSomethingWentWrong;
},
);
}
setState(
() => add ? parent = possibleParent : parent = null,
);
}
Widget getAddToSpaceToggleItem(int index) {
final Room possibleParent = possibleParents[index];
final bool canAdd = possibleParent.canAddAsParentOf(
room,
spaceMode: widget.spaceMode,
);
return Opacity(
opacity: canAdd ? 1 : 0.5,
child: Column(
children: [
SwitchListTile.adaptive(
title: possibleParent.nameAndRoomTypeIcon(),
activeColor: AppConfig.activeToggleColor,
value: parent?.id == possibleParent.id,
onChanged: (bool add) => canAdd
? handleAdd(add, possibleParent)
: ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(L10n.of(context)!.noPermission),
),
),
),
Divider(
height: 0.5,
color: Theme.of(context).colorScheme.secondary.withAlpha(25),
),
],
),
);
}
Future<void> setSuggested(bool suggested) async {
setState(() => isSuggested = suggested);
if (room != null) {
await showFutureLoadingDialog(
context: context,
future: () async => await room?.setSuggested(suggested),
);
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ListTile(
title: Text(
L10n.of(context)!.addToSpace,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
widget.spaceMode || (room?.isSpace ?? false)
? L10n.of(context)!.addSpaceToSpaceDesc
: L10n.of(context)!.addChatToSpaceDesc,
),
leading: CircleAvatar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).textTheme.bodyLarge!.color,
child: const Icon(Icons.workspaces_outlined),
),
trailing: Icon(
isOpen
? Icons.keyboard_arrow_down_outlined
: Icons.keyboard_arrow_right_outlined,
),
onTap: () {
setState(() => isOpen = !isOpen);
},
),
if (isOpen) ...[
const Divider(height: 1),
possibleParents.isNotEmpty
? Column(
children: [
SwitchListTile.adaptive(
title: Text(
widget.spaceMode || (room?.isSpace ?? false)
? L10n.of(context)!.suggestToSpace
: L10n.of(context)!.suggestToChat,
),
secondary: Icon(
isSuggested
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
),
subtitle: Text(
widget.spaceMode || (room?.isSpace ?? false)
? L10n.of(context)!.suggestToSpaceDesc
: L10n.of(context)!.suggestToChatDesc,
),
activeColor: AppConfig.activeToggleColor,
value: isSuggested,
onChanged: (bool add) => setSuggested(add),
),
Divider(
height: 0.5,
color:
Theme.of(context).colorScheme.secondary.withAlpha(25),
),
...possibleParents.mapIndexed(
(index, _) => getAddToSpaceToggleItem(index),
),
],
)
: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
L10n.of(context)!.inNoSpaces,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
),
),
),
),
],
],
);
}
}