go back to fluffychat new space/group pages, delete add to space toggles widget

pull/1428/head
ggurdin 1 year ago
parent 162019221a
commit 89a61c03ed
No known key found for this signature in database
GPG Key ID: A01CB41737CBB478

@ -233,11 +233,7 @@ abstract class AppRoutes {
pageBuilder: (context, state) => defaultPageBuilder( pageBuilder: (context, state) => defaultPageBuilder(
context, context,
state, state,
NewGroup( const NewGroup(),
// #Pangea
spaceId: state.uri.queryParameters['spaceId'],
// Pangea#
),
), ),
redirect: loggedOutRedirect, redirect: loggedOutRedirect,
// #Pangea // #Pangea

@ -5,7 +5,6 @@ import 'package:fluffychat/pages/chat_details/chat_details_view.dart';
import 'package:fluffychat/pages/settings/settings.dart'; import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_description_button.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_description_button.dart';
import 'package:fluffychat/pangea/utils/set_class_name.dart'; import 'package:fluffychat/pangea/utils/set_class_name.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart'; import 'package:fluffychat/widgets/app_lock.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
@ -41,9 +40,7 @@ class ChatDetailsController extends State<ChatDetails> {
String? get roomId => widget.roomId; String? get roomId => widget.roomId;
// #Pangea // #Pangea
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>(); final GlobalKey<ChatDetailsController> addConversationBotKey =
final GlobalKey<ChatDetailsController>
addConversationBotKey =
GlobalKey<ChatDetailsController>(); GlobalKey<ChatDetailsController>();
bool displayAddStudentOptions = false; bool displayAddStudentOptions = false;

@ -10,7 +10,6 @@ import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_inv
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_name_button.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_name_button.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/utils/lock_room.dart'; import 'package:fluffychat/pangea/utils/lock_room.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/fluffy_share.dart'; import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
@ -395,13 +394,6 @@ class ChatDetailsView extends StatelessWidget {
room: room, room: room,
), ),
const Divider(height: 1), const Divider(height: 1),
if (!room.isDirectChat && room.isRoomAdmin)
AddToSpaceToggles(
roomId: room.id,
key: controller.addToSpaceKey,
startOpen: false,
),
const Divider(height: 1),
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context)!.leave, L10n.of(context)!.leave,

@ -1,33 +1,14 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:fluffychat/pages/new_group/new_group_view.dart'; import 'package:fluffychat/pages/new_group/new_group_view.dart';
import 'package:fluffychat/pangea/constants/bot_mode.dart'; import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/models/chat_topic_model.dart';
import 'package:fluffychat/pangea/models/lemma.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/class_chat_power_levels.dart';
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart' as sdk;
class NewGroup extends StatefulWidget { class NewGroup extends StatefulWidget {
// #Pangea const NewGroup({super.key});
final String? spaceId;
const NewGroup({
super.key,
this.spaceId,
});
// Pangea#
@override @override
NewGroupController createState() => NewGroupController(); NewGroupController createState() => NewGroupController();
@ -47,50 +28,25 @@ class NewGroupController extends State<NewGroup> {
bool loading = false; bool loading = false;
// #Pangea
PangeaController pangeaController = MatrixState.pangeaController;
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>();
final GlobalKey<ConversationBotSettingsState> addConversationBotKey =
GlobalKey<ConversationBotSettingsState>();
final GlobalKey<RoomCapacityButtonState> addCapacityKey =
GlobalKey<RoomCapacityButtonState>();
ChatTopic chatTopic = ChatTopic.empty;
void setVocab(List<Lemma> vocab) => setState(() => chatTopic.vocab = vocab);
String? get activeSpaceId =>
GoRouterState.of(context).uri.queryParameters['spaceId'];
// Pangea#
void setPublicGroup(bool b) => setState(() => publicGroup = b); void setPublicGroup(bool b) => setState(() => publicGroup = b);
void setGroupCanBeFound(bool b) => setState(() => groupCanBeFound = b); void setGroupCanBeFound(bool b) => setState(() => groupCanBeFound = b);
void selectPhoto() async { void selectPhoto() async {
final photo = await FilePicker.platform.pickFiles( final photo = await selectFiles(
type: FileType.image, context,
type: FileSelectorType.images,
allowMultiple: false, allowMultiple: false,
withData: true,
); );
final bytes = await photo.singleOrNull?.readAsBytes();
setState(() { setState(() {
avatarUrl = null; avatarUrl = null;
avatar = photo?.files.singleOrNull?.bytes; avatar = bytes;
}); });
} }
void submitAction([_]) async { void submitAction([_]) async {
// #Pangea
if (nameController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(L10n.of(context)!.emptyChatNameWarning),
),
);
return;
}
// Pangea#
final client = Matrix.of(context).client; final client = Matrix.of(context).client;
try { try {
@ -104,67 +60,12 @@ class NewGroupController extends State<NewGroup> {
if (!mounted) return; if (!mounted) return;
// #Pangea
// validate init bot options
if (addConversationBotKey.currentState?.formKey.currentState != null) {
final isValid = addConversationBotKey
.currentState!.formKey.currentState!
.validate();
if (isValid == false) {
setState(() {
error = L10n.of(context)!
.conversationBotCustomZone_customSystemPromptEmptyError;
loading = false;
});
return;
}
}
addConversationBotKey.currentState?.updateAllBotOptions();
final addBot = addConversationBotKey.currentState?.addBot ?? false;
if (addBot) {
final botOptions = addConversationBotKey.currentState!.botOptions;
if (botOptions.mode == BotMode.custom) {
if (botOptions.customSystemPrompt == null ||
botOptions.customSystemPrompt!.isEmpty) {
setState(() {
error = L10n.of(context)!
.conversationBotCustomZone_customSystemPromptEmptyError;
loading = false;
});
return;
}
} else if (botOptions.mode == BotMode.textAdventure) {
if (botOptions.textAdventureGameMasterInstructions == null ||
botOptions.textAdventureGameMasterInstructions!.isEmpty) {
setState(() {
error = L10n.of(context)!
.conversationBotCustomZone_instructionSystemPromptEmptyError;
loading = false;
});
return;
}
}
}
// Pangea#
final roomId = await client.createGroupChat( final roomId = await client.createGroupChat(
// #Pangea visibility:
// visibility: groupCanBeFound ? sdk.Visibility.public : sdk.Visibility.private,
// publicGroup ? sdk.Visibility.public : sdk.Visibility.private, preset: publicGroup
// preset: publicGroup ? sdk.CreateRoomPreset.publicChat
// ? sdk.CreateRoomPreset.publicChat : sdk.CreateRoomPreset.privateChat,
// : sdk.CreateRoomPreset.privateChat,
preset: sdk.CreateRoomPreset.publicChat,
powerLevelContentOverride:
await ClassChatPowerLevels.powerLevelOverrideForClassChat(
context,
addToSpaceKey.currentState!.parent,
),
invite: [
if (addConversationBotKey.currentState?.addBot ?? false)
BotName.byEnvironment,
],
// Pangea#
groupName: nameController.text.isNotEmpty ? nameController.text : null, groupName: nameController.text.isNotEmpty ? nameController.text : null,
initialState: [ initialState: [
if (avatar != null) if (avatar != null)
@ -172,29 +73,9 @@ class NewGroupController extends State<NewGroup> {
type: sdk.EventTypes.RoomAvatar, type: sdk.EventTypes.RoomAvatar,
content: {'url': avatarUrl.toString()}, content: {'url': avatarUrl.toString()},
), ),
// #Pangea
if (addConversationBotKey.currentState?.addBot ?? false)
addConversationBotKey.currentState!.botOptions.toStateEvent,
// Pangea#
], ],
); );
if (!mounted) return; if (!mounted) return;
if (publicGroup && groupCanBeFound) {
await client.setRoomVisibilityOnDirectory(
roomId,
visibility: sdk.Visibility.public,
);
}
// #Pangea
GoogleAnalytics.createChat(roomId);
await addToSpaceKey.currentState!.addSpaces(roomId);
final capacity = addCapacityKey.currentState?.capacity;
final room = client.getRoomById(roomId);
if (capacity != null && room != null) {
room.updateRoomCapacity(capacity);
}
// Pangea#
context.go('/rooms/$roomId/invite'); context.go('/rooms/$roomId/invite');
} catch (e, s) { } catch (e, s) {
sdk.Logs().d('Unable to create group', e, s); sdk.Logs().d('Unable to create group', e, s);
@ -205,20 +86,6 @@ class NewGroupController extends State<NewGroup> {
} }
} }
//#Pangea
@override
void initState() {
Future.delayed(Duration.zero, () {
chatTopic.langCode =
pangeaController.languageController.userL2?.langCode ??
pangeaController.pLanguageStore.targetOptions.first.langCode;
setState(() {});
});
super.initState();
}
//Pangea#
@override @override
Widget build(BuildContext context) => NewGroupView(this); Widget build(BuildContext context) => NewGroupView(this);
} }

@ -1,8 +1,5 @@
import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/new_group/new_group.dart'; import 'package:fluffychat/pages/new_group/new_group.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart';
@ -27,20 +24,8 @@ class NewGroupView extends StatelessWidget {
onPressed: controller.loading ? null : Navigator.of(context).pop, onPressed: controller.loading ? null : Navigator.of(context).pop,
), ),
), ),
// #Pangea title: Text(L10n.of(context)!.createGroup),
// title: Text(L10n.of(context)!.createGroup),
title: Text(L10n.of(context)!.createChat),
// Pangea#
),
// #Pangea
floatingActionButton: FloatingActionButton.extended(
onPressed: controller.loading ? null : controller.submitAction,
icon: controller.loading ? null : const Icon(Icons.chat_bubble_outline),
label: controller.loading
? const CircularProgressIndicator.adaptive()
: Text(L10n.of(context)!.createChat),
), ),
// Pangea#
body: MaxWidthBody( body: MaxWidthBody(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -68,9 +53,6 @@ class NewGroupView extends StatelessWidget {
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: TextField( child: TextField(
// #Pangea
maxLength: 64,
// Pangea#
autofocus: true, autofocus: true,
controller: controller.nameController, controller: controller.nameController,
autocorrect: false, autocorrect: false,
@ -85,40 +67,31 @@ class NewGroupView extends StatelessWidget {
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// #Pangea SwitchListTile.adaptive(
RoomCapacityButton( contentPadding: const EdgeInsets.symmetric(horizontal: 32),
key: controller.addCapacityKey, secondary: const Icon(Icons.public_outlined),
), title: Text(L10n.of(context)!.groupIsPublic),
ConversationBotSettings( value: controller.publicGroup,
key: controller.addConversationBotKey, onChanged: controller.loading ? null : controller.setPublicGroup,
activeSpaceId: controller.activeSpaceId,
), ),
const Divider(height: 1), AnimatedSize(
AddToSpaceToggles( duration: FluffyThemes.animationDuration,
key: controller.addToSpaceKey, child: controller.publicGroup
startOpen: true, ? SwitchListTile.adaptive(
activeSpaceId: controller.activeSpaceId, contentPadding:
const EdgeInsets.symmetric(horizontal: 32),
secondary: const Icon(Icons.search_outlined),
title: Text(L10n.of(context)!.groupCanBeFoundViaSearch),
value: controller.groupCanBeFound,
onChanged: controller.loading
? null
: controller.setGroupCanBeFound,
)
: const SizedBox.shrink(),
), ),
// #Pangea
// SwitchListTile.adaptive( // SwitchListTile.adaptive(
// secondary: const Icon(Icons.public_outlined), // contentPadding: const EdgeInsets.symmetric(horizontal: 32),
// title: Text(L10n.of(context)!.groupIsPublic),
// value: controller.publicGroup,
// onChanged: controller.loading ? null : controller.setPublicGroup,
// ),
// AnimatedSize(
// duration: FluffyThemes.animationDuration,
// child: controller.publicGroup
// ? SwitchListTile.adaptive(
// secondary: const Icon(Icons.search_outlined),
// title: Text(L10n.of(context)!.groupCanBeFoundViaSearch),
// value: controller.groupCanBeFound,
// onChanged: controller.loading
// ? null
// : controller.setGroupCanBeFound,
// )
// : const SizedBox.shrink(),
// ),
// SwitchListTile.adaptive(
// secondary: Icon( // secondary: Icon(
// Icons.lock_outlined, // Icons.lock_outlined,
// color: theme.colorScheme.onSurface, // color: theme.colorScheme.onSurface,
@ -132,29 +105,20 @@ class NewGroupView extends StatelessWidget {
// value: !controller.publicGroup, // value: !controller.publicGroup,
// onChanged: null, // onChanged: null,
// ), // ),
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: SizedBox(
// width: double.infinity,
// child: ElevatedButton(
// onPressed:
// controller.loading ? null : controller.submitAction,
// child: controller.loading
// ? const LinearProgressIndicator()
// : Row(
// children: [
// Expanded(
// child: Text(
// L10n.of(context)!.createGroupAndInviteUsers,
// ),
// ),
// Icon(Icons.adaptive.arrow_forward_outlined),
// ],
// ),
// ),
// ),
// ),
// Pangea# // Pangea#
Padding(
padding: const EdgeInsets.all(16.0),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed:
controller.loading ? null : controller.submitAction,
child: controller.loading
? const LinearProgressIndicator()
: Text(L10n.of(context)!.createGroupAndInviteUsers),
),
),
),
AnimatedSize( AnimatedSize(
duration: FluffyThemes.animationDuration, duration: FluffyThemes.animationDuration,
child: error == null child: error == null

@ -1,20 +1,19 @@
import 'package:file_picker/file_picker.dart'; import 'dart:typed_data';
import 'package:fluffychat/pages/new_space/new_space_view.dart'; import 'package:fluffychat/pages/new_space/new_space_view.dart';
import 'package:fluffychat/pangea/constants/class_default_values.dart'; import 'package:fluffychat/pangea/constants/class_default_values.dart';
import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart';
import 'package:fluffychat/pangea/utils/class_chat_power_levels.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
import 'package:fluffychat/pangea/utils/space_code.dart'; import 'package:fluffychat/pangea/utils/space_code.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; import 'package:fluffychat/utils/file_selector.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart';
import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart' as sdk;
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
@ -28,48 +27,32 @@ class NewSpace extends StatefulWidget {
class NewSpaceController extends State<NewSpace> { class NewSpaceController extends State<NewSpace> {
TextEditingController nameController = TextEditingController(); TextEditingController nameController = TextEditingController();
TextEditingController topicController = TextEditingController(); TextEditingController topicController = TextEditingController();
// #Pangea
bool publicGroup = false; bool publicGroup = false;
// bool publicGroup = true;
// final GlobalKey<RoomRulesState> rulesEditorKey = GlobalKey<RoomRulesState>();
final GlobalKey<AddToSpaceState> addToSpaceKey = GlobalKey<AddToSpaceState>();
// commenting out language settings in spaces for now
// final GlobalKey<LanguageSettingsState> languageSettingsKey =
// GlobalKey<LanguageSettingsState>();
final GlobalKey<RoomCapacityButtonState> addCapacityKey =
GlobalKey<RoomCapacityButtonState>();
//Pangea#
bool loading = false; bool loading = false;
// #Pangea String? nameError;
// String? nameError; String? topicError;
// String? topicError;
// Pangea#
Uint8List? avatar; Uint8List? avatar;
Uri? avatarUrl; Uri? avatarUrl;
void selectPhoto() async { void selectPhoto() async {
final photo = await FilePicker.platform.pickFiles( final photo = await selectFiles(
type: FileType.image, context,
allowMultiple: false, type: FileSelectorType.images,
withData: true,
); );
final bytes = await photo.firstOrNull?.readAsBytes();
setState(() { setState(() {
avatarUrl = null; avatarUrl = null;
avatar = photo?.files.singleOrNull?.bytes; avatar = bytes;
}); });
} }
void setPublicGroup(bool b) => setState(() => publicGroup = b); void setPublicGroup(bool b) => setState(() => publicGroup = b);
// #Pangea // #Pangea
List<StateEvent> get initialState { List<StateEvent> initialState(String joinCode) {
final events = <StateEvent>[]; return [
events.add(
StateEvent( StateEvent(
type: EventTypes.RoomPowerLevels, type: EventTypes.RoomPowerLevels,
stateKey: '', stateKey: '',
@ -84,153 +67,70 @@ class NewSpaceController extends State<NewSpace> {
}, },
}, },
), ),
); StateEvent(
type: sdk.EventTypes.RoomJoinRules,
// commenting out pangea room rules in spaces for now content: {
// if (rulesEditorKey.currentState?.rules != null) { ModelKey.joinRule:
// events.add(rulesEditorKey.currentState!.rules.toStateEvent); sdk.JoinRules.knock.toString().replaceAll('JoinRules.', ''),
// } else { ModelKey.accessCode: joinCode,
// debugger(when: kDebugMode); },
// } ),
// commenting out language settings in spaces for now ];
// if (languageSettingsKey.currentState != null) {
// events
// .add(languageSettingsKey.currentState!.languageSettings.toStateEvent);
// }
return events;
} }
//Pangea# //Pangea#
void submitAction([_]) async { void submitAction([_]) async {
final client = Matrix.of(context).client; final client = Matrix.of(context).client;
setState(() { setState(() {
// #Pangea nameError = topicError = null;
// nameError = topicError = null;
// Pangea#
}); });
// #Pangea
// commenting out pangea room rules in spaces for now
// if (rulesEditorKey.currentState == null) {
// debugger(when: kDebugMode);
// return;
// }
// commenting out language settings in spaces for now
// if (languageSettingsKey.currentState != null &&
// languageSettingsKey.currentState!.sameLanguages) {
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(L10n.of(context)!.noIdenticalLanguages),
// ),
// );
// return;
// }
// final int? languageLevel =
// languageSettingsKey.currentState!.languageSettings.languageLevel;
// if (languageLevel == null) {
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(content: Text(L10n.of(context)!.languageLevelWarning)),
// );
// return;
// }
// Pangea#
if (nameController.text.isEmpty) { if (nameController.text.isEmpty) {
setState(() { setState(() {
// #Pangea nameError = L10n.of(context)!.pleaseChoose;
// nameError = L10n.of(context)!.pleaseChoose;
final String warning = L10n.of(context)!.emptySpaceNameWarning;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(warning)),
);
// Pangea#
}); });
return; return;
} }
setState(() { setState(() {
loading = true; loading = true;
}); });
// #Pangea
// try {
await showFutureLoadingDialog(
context: context,
future: () async {
try { try {
// Pangea#
final avatar = this.avatar; final avatar = this.avatar;
avatarUrl ??= avatarUrl ??= avatar == null ? null : await client.uploadContent(avatar);
avatar == null ? null : await client.uploadContent(avatar);
final classCode = await SpaceCodeUtil.generateSpaceCode(client);
final spaceId = await client.createRoom(
// #Pangea // #Pangea
final joinCode = await SpaceCodeUtil.generateSpaceCode(client);
// Pangea#
final spaceId = await client.createRoom(
preset: publicGroup preset: publicGroup
? sdk.CreateRoomPreset.publicChat ? sdk.CreateRoomPreset.publicChat
: sdk.CreateRoomPreset.privateChat, : sdk.CreateRoomPreset.privateChat,
// #Pangea
creationContent: {'type': RoomCreationTypes.mSpace}, creationContent: {'type': RoomCreationTypes.mSpace},
visibility: publicGroup ? sdk.Visibility.public : null, visibility: publicGroup ? sdk.Visibility.public : null,
// #Pangea roomAliasName: publicGroup
// roomAliasName: publicGroup ? nameController.text.trim().toLowerCase().replaceAll(' ', '_')
// ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') : null,
// : null,
// roomAliasName: SpaceCodeUtil.generateSpaceCode(),
// Pangea#
name: nameController.text.trim(), name: nameController.text.trim(),
topic: topicController.text.isEmpty ? null : topicController.text, topic: topicController.text.isEmpty ? null : topicController.text,
// #Pangea powerLevelContentOverride: {'events_default': 100},
// powerLevelContentOverride: {'events_default': 100},
powerLevelContentOverride: addToSpaceKey.currentState != null
? await ClassChatPowerLevels.powerLevelOverrideForClassChat(
context,
addToSpaceKey.currentState!.parent,
)
: null,
// Pangea#
initialState: [ initialState: [
// #Pangea // #Pangea
...initialState, ...initialState(joinCode),
// Pangea#
if (avatar != null) if (avatar != null)
sdk.StateEvent( sdk.StateEvent(
type: sdk.EventTypes.RoomAvatar, type: sdk.EventTypes.RoomAvatar,
content: {'url': avatarUrl.toString()}, content: {'url': avatarUrl.toString()},
), ),
sdk.StateEvent(
type: sdk.EventTypes.RoomJoinRules,
content: {
ModelKey.joinRule: sdk.JoinRules.knock
.toString()
.replaceAll('JoinRules.', ''),
ModelKey.accessCode: classCode,
},
),
// Pangea#
], ],
// Pangea#
); );
if (!mounted) return;
// #Pangea // #Pangea
final List<Future<dynamic>> futures = [ Room? room = client.getRoomById(spaceId);
Matrix.of(context).client.waitForRoomInSync(spaceId, join: true),
];
if (addToSpaceKey.currentState != null) {
futures.add(addToSpaceKey.currentState!.addSpaces(spaceId));
}
await Future.wait(futures);
final capacity = addCapacityKey.currentState?.capacity;
final space = client.getRoomById(spaceId);
if (capacity != null && space != null) {
space.updateRoomCapacity(capacity);
}
final Room? room = Matrix.of(context).client.getRoomById(spaceId);
if (room == null) { if (room == null) {
ErrorHandler.logError( await Matrix.of(context).client.waitForRoomInSync(spaceId);
e: 'Failed to get new space by id $spaceId', room = client.getRoomById(spaceId);
);
MatrixState.pangeaController.classController
.setActiveSpaceIdInChatListController(spaceId);
return;
} }
if (room == null) return;
GoogleAnalytics.createClass(room.name, room.classCode); GoogleAnalytics.createClass(room.name, room.classCode);
try { try {
await room.invite(BotName.byEnvironment); await room.invite(BotName.byEnvironment);
@ -239,36 +139,22 @@ class NewSpaceController extends State<NewSpace> {
e: "Failed to invite pangea bot to space ${room.id}", e: "Failed to invite pangea bot to space ${room.id}",
); );
} }
// Pangea#
if (!mounted) return;
// #Pangea
// context.pop<String>(spaceId);
MatrixState.pangeaController.classController MatrixState.pangeaController.classController
.setActiveSpaceIdInChatListController(spaceId); .setActiveSpaceIdInChatListController(spaceId);
// Pangea# // Pangea#
} catch (e, s) { context.pop<String>(spaceId);
// #Pangea } catch (e) {
ErrorHandler.logError(e: e, s: s); setState(() {
rethrow; topicError = e.toLocalizedString(context);
// setState(() { });
// topicError = e.toLocalizedString(context);
// });
// Pangea#
} finally { } finally {
setState(() { setState(() {
loading = false; loading = false;
}); });
} }
},
);
// TODO: Go to spaces // TODO: Go to spaces
} }
@override @override
// #Pangea Widget build(BuildContext context) => NewSpaceView(this);
// Widget build(BuildContext context) => NewSpaceView(this);
Widget build(BuildContext context) {
return NewSpaceView(this);
}
// Pangea#
} }

@ -1,5 +1,3 @@
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart';
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -19,15 +17,6 @@ class NewSpaceView extends StatelessWidget {
appBar: AppBar( appBar: AppBar(
title: Text(L10n.of(context)!.createNewSpace), title: Text(L10n.of(context)!.createNewSpace),
), ),
// #Pangea
floatingActionButton: FloatingActionButton.extended(
onPressed: controller.loading ? null : controller.submitAction,
icon: controller.loading ? null : const Icon(Icons.workspaces_outlined),
label: controller.loading
? const CircularProgressIndicator.adaptive()
: Text(L10n.of(context)!.createSpace),
),
// Pangea#
body: MaxWidthBody( body: MaxWidthBody(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -62,58 +51,38 @@ class NewSpaceView extends StatelessWidget {
decoration: InputDecoration( decoration: InputDecoration(
prefixIcon: const Icon(Icons.people_outlined), prefixIcon: const Icon(Icons.people_outlined),
labelText: L10n.of(context)!.spaceName, labelText: L10n.of(context)!.spaceName,
// #Pangea errorText: controller.nameError,
// errorText: controller.nameError,
// Pangea#
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
// #Pangea SwitchListTile.adaptive(
RoomCapacityButton( contentPadding: const EdgeInsets.symmetric(horizontal: 32),
key: controller.addCapacityKey, title: Text(L10n.of(context)!.spaceIsPublic),
spaceMode: true, value: controller.publicGroup,
), onChanged: controller.setPublicGroup,
AddToSpaceToggles( ),
key: controller.addToSpaceKey, ListTile(
startOpen: true, contentPadding: const EdgeInsets.symmetric(horizontal: 32),
spaceMode: true, trailing: const Padding(
), padding: EdgeInsets.symmetric(horizontal: 16.0),
// SwitchListTile.adaptive( child: Icon(Icons.info_outlined),
// title: Text(L10n.of(context)!.spaceIsPublic), ),
// value: controller.publicGroup, subtitle: Text(L10n.of(context)!.newSpaceDescription),
// onChanged: controller.setPublicGroup, ),
// ), Padding(
// ListTile( padding: const EdgeInsets.all(16.0),
// trailing: const Padding( child: SizedBox(
// padding: EdgeInsets.symmetric(horizontal: 16.0), width: double.infinity,
// child: Icon(Icons.info_outlined), child: ElevatedButton(
// ), onPressed:
// subtitle: Text(L10n.of(context)!.newSpaceDescription), controller.loading ? null : controller.submitAction,
// ), child: controller.loading
// Padding( ? const LinearProgressIndicator()
// padding: const EdgeInsets.all(16.0), : Text(L10n.of(context)!.createNewSpace),
// child: SizedBox( ),
// width: double.infinity, ),
// child: ElevatedButton( ),
// onPressed:
// controller.loading ? null : controller.submitAction,
// child: controller.loading
// ? const LinearProgressIndicator()
// : Row(
// children: [
// Expanded(
// child: Text(
// L10n.of(context)!.createNewSpace,
// ),
// ),
// Icon(Icons.adaptive.arrow_forward_outlined),
// ],
// ),
// ),
// ),
// ),
// Pangea#
], ],
), ),
), ),

@ -1,268 +0,0 @@
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,
),
),
),
),
],
],
);
}
}

@ -0,0 +1,78 @@
import 'package:file_picker/file_picker.dart';
import 'package:file_selector/file_selector.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import 'package:flutter/widgets.dart';
Future<List<XFile>> selectFiles(
BuildContext context, {
String? title,
FileSelectorType type = FileSelectorType.any,
bool allowMultiple = false,
}) async {
if (!PlatformInfos.isLinux) {
final result = await AppLock.of(context).pauseWhile(
FilePicker.platform.pickFiles(
compressionQuality: 0,
allowMultiple: allowMultiple,
type: type.filePickerType,
allowedExtensions: type.extensions,
),
);
return result?.xFiles ?? [];
}
if (allowMultiple) {
return await AppLock.of(context).pauseWhile(
openFiles(
confirmButtonText: title,
acceptedTypeGroups: type.groups,
),
);
}
final file = await AppLock.of(context).pauseWhile(
openFile(
confirmButtonText: title,
acceptedTypeGroups: type.groups,
),
);
if (file == null) return [];
return [file];
}
enum FileSelectorType {
any([], FileType.any, null),
images(
[
XTypeGroup(
label: 'JPG',
extensions: <String>['jpg', 'JPG', 'jpeg', 'JPEG'],
),
XTypeGroup(
label: 'PNGs',
extensions: <String>['png', 'PNG'],
),
XTypeGroup(
label: 'WEBP',
extensions: <String>['WebP', 'WEBP'],
),
],
FileType.image,
null,
),
zip(
[
XTypeGroup(
label: 'ZIP',
extensions: <String>['zip', 'ZIP'],
),
],
FileType.custom,
['zip', 'ZIP'],
);
const FileSelectorType(this.groups, this.filePickerType, this.extensions);
final List<XTypeGroup> groups;
final FileType filePickerType;
final List<String>? extensions;
}

@ -424,6 +424,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.0.6" version: "8.0.6"
file_selector:
dependency: "direct main"
description:
name: file_selector
sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
file_selector_android:
dependency: transitive
description:
name: file_selector_android
sha256: "00aafa9ae05a8663d0b4f17abd2a02316911ca0f46f9b9dacb9578b324d99590"
url: "https://pub.dev"
source: hosted
version: "0.5.1+9"
file_selector_ios:
dependency: transitive
description:
name: file_selector_ios
sha256: "94b98ad950b8d40d96fee8fa88640c2e4bd8afcdd4817993bd04e20310f45420"
url: "https://pub.dev"
source: hosted
version: "0.5.3+1"
file_selector_linux: file_selector_linux:
dependency: transitive dependency: transitive
description: description:
@ -448,6 +472,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.2" version: "2.6.2"
file_selector_web:
dependency: transitive
description:
name: file_selector_web
sha256: c4c0ea4224d97a60a7067eca0c8fd419e708ff830e0c83b11a48faf566cec3e7
url: "https://pub.dev"
source: hosted
version: "0.9.4+2"
file_selector_windows: file_selector_windows:
dependency: transitive dependency: transitive
description: description:
@ -2756,5 +2788,5 @@ packages:
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.4.0 <4.0.0" dart: ">=3.5.0 <4.0.0"
flutter: ">=3.22.0" flutter: ">=3.24.0"

@ -32,6 +32,7 @@ dependencies:
emojis: ^0.9.9 emojis: ^0.9.9
#fcm_shared_isolate: ^0.1.0 #fcm_shared_isolate: ^0.1.0
file_picker: ^8.0.6 file_picker: ^8.0.6
file_selector: ^1.0.3
flutter: flutter:
sdk: flutter sdk: flutter
flutter_app_badger: ^1.5.0 flutter_app_badger: ^1.5.0

Loading…
Cancel
Save