934 enrolling users automatically in several spaces (#975)
* allow users to set visibility of rooms in add chat or subspace dialog and in room details * only allow room admins to change visibility
This commit is contained in:
parent
81d48236c4
commit
af1561b49f
5 changed files with 309 additions and 48 deletions
|
|
@ -13,6 +13,7 @@ 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:image_picker/image_picker.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
enum AliasActions { copy, delete, setCanonical }
|
||||
|
|
@ -205,6 +206,20 @@ class ChatDetailsController extends State<ChatDetails> {
|
|||
void hoverEditNameIcon(bool hovering) =>
|
||||
setState(() => showEditNameIcon = !showEditNameIcon);
|
||||
|
||||
Future<void> setVisibility(matrix.Visibility visibility) async {
|
||||
if (roomId == null) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
await Matrix.of(context).client.setRoomVisibilityOnDirectory(
|
||||
roomId!,
|
||||
visibility: visibility,
|
||||
);
|
||||
},
|
||||
);
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_det
|
|||
import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_invitation_buttons.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/widgets/chat/visibility_toggle.dart';
|
||||
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
|
||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
|
|
@ -340,6 +341,14 @@ class ChatDetailsView extends StatelessWidget {
|
|||
'/rooms/${room.id}/details/permissions',
|
||||
),
|
||||
),
|
||||
// #Pangea
|
||||
if (room.isRoomAdmin)
|
||||
VisibilityToggle(
|
||||
room: room,
|
||||
setVisibility: controller.setVisibility,
|
||||
iconColor: iconColor,
|
||||
),
|
||||
// Pangea#
|
||||
Divider(color: theme.dividerColor),
|
||||
// #Pangea
|
||||
if (room.canInvite &&
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
|
|||
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
||||
import 'package:fluffychat/pangea/constants/pangea_room_types.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/add_room_dialog.dart';
|
||||
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/utils/stream_extension.dart';
|
||||
|
|
@ -331,43 +332,51 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
);
|
||||
if (roomType == null) return;
|
||||
|
||||
final names = await showTextInputDialog(
|
||||
// #Pangea
|
||||
final RoomResponse? response = await showDialog<RoomResponse>(
|
||||
context: context,
|
||||
title: roomType == AddRoomType.subspace
|
||||
? L10n.of(context)!.createNewSpace
|
||||
// #Pangea
|
||||
// : L10n.of(context)!.createGroup,
|
||||
: L10n.of(context)!.createChat,
|
||||
// Pangea#
|
||||
textFields: [
|
||||
DialogTextField(
|
||||
hintText: roomType == AddRoomType.subspace
|
||||
? L10n.of(context)!.spaceName
|
||||
// #Pangea
|
||||
// : L10n.of(context)!.groupName,
|
||||
: L10n.of(context)!.chatName,
|
||||
// Pangea#
|
||||
minLines: 1,
|
||||
maxLines: 1,
|
||||
maxLength: 64,
|
||||
validator: (text) {
|
||||
if (text == null || text.isEmpty) {
|
||||
return L10n.of(context)!.pleaseChoose;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
DialogTextField(
|
||||
hintText: L10n.of(context)!.chatDescription,
|
||||
minLines: 4,
|
||||
maxLines: 8,
|
||||
maxLength: 255,
|
||||
),
|
||||
],
|
||||
okLabel: L10n.of(context)!.create,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
builder: (context) {
|
||||
return AddRoomDialog(
|
||||
roomType: roomType,
|
||||
);
|
||||
},
|
||||
);
|
||||
if (names == null) return;
|
||||
if (response == null) return;
|
||||
|
||||
// final names = await showTextInputDialog(
|
||||
// context: context,
|
||||
// title: roomType == AddRoomType.subspace
|
||||
// ? L10n.of(context)!.createNewSpace
|
||||
// : L10n.of(context)!.createGroup,
|
||||
// : L10n.of(context)!.createChat,
|
||||
// textFields: [
|
||||
// DialogTextField(
|
||||
// hintText: roomType == AddRoomType.subspace
|
||||
// ? L10n.of(context)!.spaceName
|
||||
// L10n.of(context)!.groupName,
|
||||
// : L10n.of(context)!.chatName,
|
||||
// minLines: 1,
|
||||
// maxLines: 1,
|
||||
// maxLength: 64,
|
||||
// validator: (text) {
|
||||
// if (text == null || text.isEmpty) {
|
||||
// return L10n.of(context)!.pleaseChoose;
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// ),
|
||||
// DialogTextField(
|
||||
// hintText: L10n.of(context)!.chatDescription,
|
||||
// minLines: 4,
|
||||
// maxLines: 8,
|
||||
// maxLength: 255,
|
||||
// ),
|
||||
// ],
|
||||
// okLabel: L10n.of(context)!.create,
|
||||
// cancelLabel: L10n.of(context)!.cancel,
|
||||
// );
|
||||
// if (names == null) return;
|
||||
// Pangea#
|
||||
final client = Matrix.of(context).client;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
|
|
@ -378,33 +387,46 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
|
||||
if (roomType == AddRoomType.subspace) {
|
||||
roomId = await client.createSpace(
|
||||
name: names.first,
|
||||
topic: names.last.isEmpty ? null : names.last,
|
||||
visibility: activeSpace.joinRules == JoinRules.public
|
||||
? sdk.Visibility.public
|
||||
: sdk.Visibility.private,
|
||||
// #Pangea
|
||||
// name: names.first,
|
||||
// topic: names.last.isEmpty ? null : names.last,
|
||||
// visibility: activeSpace.joinRules == JoinRules.public
|
||||
// ? sdk.Visibility.public
|
||||
// : sdk.Visibility.private,
|
||||
name: response.roomName,
|
||||
topic: response.roomDescription,
|
||||
visibility: response.visibility,
|
||||
// Pangea#
|
||||
);
|
||||
} else {
|
||||
roomId = await client.createGroupChat(
|
||||
groupName: names.first,
|
||||
// #Pangea
|
||||
// groupName: names.first,
|
||||
// preset: activeSpace.joinRules == JoinRules.public
|
||||
// ? CreateRoomPreset.publicChat
|
||||
// : CreateRoomPreset.privateChat,
|
||||
// visibility: activeSpace.joinRules == JoinRules.public
|
||||
// ? sdk.Visibility.public
|
||||
// : sdk.Visibility.private,
|
||||
// initialState: names.length > 1 && names.last.isNotEmpty
|
||||
// ? [
|
||||
// StateEvent(
|
||||
// type: EventTypes.RoomTopic,
|
||||
// content: {'topic': names.last},
|
||||
// ),
|
||||
// ]
|
||||
// : null,
|
||||
groupName: response.roomName,
|
||||
preset: CreateRoomPreset.publicChat,
|
||||
// Pangea#
|
||||
visibility: activeSpace.joinRules == JoinRules.public
|
||||
? sdk.Visibility.public
|
||||
: sdk.Visibility.private,
|
||||
initialState: names.length > 1 && names.last.isNotEmpty
|
||||
visibility: response.visibility,
|
||||
initialState: response.roomDescription.isNotEmpty
|
||||
? [
|
||||
StateEvent(
|
||||
type: EventTypes.RoomTopic,
|
||||
content: {'topic': names.last},
|
||||
content: {'topic': response.roomDescription},
|
||||
),
|
||||
]
|
||||
: null,
|
||||
// #Pangea
|
||||
enableEncryption: false,
|
||||
// Pangea#
|
||||
);
|
||||
|
|
|
|||
156
lib/pangea/widgets/chat/add_room_dialog.dart
Normal file
156
lib/pangea/widgets/chat/add_room_dialog.dart
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
import 'package:fluffychat/pages/chat_list/space_view.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/visibility_toggle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
|
||||
class AddRoomDialog extends StatefulWidget {
|
||||
final AddRoomType? roomType;
|
||||
|
||||
const AddRoomDialog({
|
||||
required this.roomType,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
AddRoomDialogState createState() => AddRoomDialogState();
|
||||
}
|
||||
|
||||
class AddRoomDialogState extends State<AddRoomDialog> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final TextEditingController _roomNameController = TextEditingController();
|
||||
final TextEditingController _roomDescriptionController =
|
||||
TextEditingController();
|
||||
|
||||
matrix.Visibility visibility = matrix.Visibility.public;
|
||||
|
||||
Future<void> setVisibility(matrix.Visibility newVisibility) async {
|
||||
setState(() => visibility = newVisibility);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_roomNameController.dispose();
|
||||
_roomDescriptionController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 400,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
widget.roomType == AddRoomType.subspace
|
||||
? L10n.of(context)!.createNewSpace
|
||||
: L10n.of(context)!.createChat,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _roomNameController,
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.roomType == AddRoomType.subspace
|
||||
? L10n.of(context)!.spaceName
|
||||
: L10n.of(context)!.chatName,
|
||||
),
|
||||
minLines: 1,
|
||||
maxLines: 1,
|
||||
maxLength: 64,
|
||||
validator: (text) {
|
||||
if (text == null || text.isEmpty) {
|
||||
return L10n.of(context)!.pleaseChoose;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: _roomDescriptionController,
|
||||
decoration: InputDecoration(
|
||||
hintText: L10n.of(context)!.chatDescription,
|
||||
),
|
||||
minLines: 4,
|
||||
maxLines: 8,
|
||||
maxLength: 255,
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
VisibilityToggle(
|
||||
setVisibility: setVisibility,
|
||||
spaceMode: widget.roomType == AddRoomType.subspace,
|
||||
visibility: visibility,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(null);
|
||||
},
|
||||
child: Text(L10n.of(context)!.cancel),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final isValid = _formKey.currentState!.validate();
|
||||
if (!isValid) return;
|
||||
|
||||
Navigator.of(context).pop(
|
||||
RoomResponse(
|
||||
roomName: _roomNameController.text,
|
||||
roomDescription: _roomDescriptionController.text,
|
||||
visibility: visibility,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(L10n.of(context)!.confirm),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RoomResponse {
|
||||
final String roomName;
|
||||
final String roomDescription;
|
||||
final matrix.Visibility visibility;
|
||||
|
||||
RoomResponse({
|
||||
required this.roomName,
|
||||
required this.roomDescription,
|
||||
required this.visibility,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'roomName': roomName,
|
||||
'roomDescripion': roomDescription,
|
||||
'visibility': visibility,
|
||||
};
|
||||
}
|
||||
}
|
||||
59
lib/pangea/widgets/chat/visibility_toggle.dart
Normal file
59
lib/pangea/widgets/chat/visibility_toggle.dart
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
class VisibilityToggle extends StatelessWidget {
|
||||
final Room? room;
|
||||
final Color? iconColor;
|
||||
final Future<void> Function(matrix.Visibility) setVisibility;
|
||||
final bool spaceMode;
|
||||
final matrix.Visibility visibility;
|
||||
|
||||
const VisibilityToggle({
|
||||
required this.setVisibility,
|
||||
this.room,
|
||||
this.iconColor,
|
||||
this.spaceMode = false,
|
||||
this.visibility = matrix.Visibility.private,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: room != null
|
||||
? Matrix.of(context).client.getRoomVisibilityOnDirectory(room!.id)
|
||||
: null,
|
||||
builder: (context, snapshot) {
|
||||
return SwitchListTile.adaptive(
|
||||
activeColor: AppConfig.activeToggleColor,
|
||||
title: Text(
|
||||
room?.isSpace ?? spaceMode
|
||||
? L10n.of(context)!.spaceIsPublic
|
||||
: L10n.of(context)!.groupIsPublic,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
secondary: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
foregroundColor: iconColor,
|
||||
child: const Icon(Icons.public_outlined),
|
||||
),
|
||||
value: room != null
|
||||
? snapshot.hasData
|
||||
? snapshot.data == matrix.Visibility.public
|
||||
: false
|
||||
: visibility == matrix.Visibility.public,
|
||||
onChanged: (value) => setVisibility(
|
||||
value ? matrix.Visibility.public : matrix.Visibility.private,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue