1137 room visibility changes (#1139)
* only show visbility toggles for parent spaces. update copy and toggle icon. * when a space is added to another space, reset its join rules / visibility to defaults * before adding space to space, give visibility warning
This commit is contained in:
parent
e40dc33c0c
commit
09c88b6e28
10 changed files with 141 additions and 132 deletions
|
|
@ -4519,5 +4519,8 @@
|
|||
"notificationsOn": "Notifications on",
|
||||
"notificationsOff": "Notifications off",
|
||||
"spaceCanBeFoundViaSearch": "Space can be found via search",
|
||||
"chatCanBeFoundViaSearch": "Chat can be found via search"
|
||||
"chatCanBeFoundViaSearch": "Chat can be found via search",
|
||||
"requireCodeToJoin": "Require code to join",
|
||||
"canFindInSearch": "Can find in search",
|
||||
"addSubspaceWarning": "Once you add this, it will not appear in public search results, and it will be visible to all members of the parent space."
|
||||
}
|
||||
|
|
@ -924,6 +924,15 @@ class ChatListController extends State<ChatList>
|
|||
.toList(),
|
||||
);
|
||||
if (space == null) return;
|
||||
// #Pangea
|
||||
if (room.isSpace) {
|
||||
final resp = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context)!.addSubspaceWarning,
|
||||
);
|
||||
if (resp == OkCancelResult.cancel) return;
|
||||
}
|
||||
// Pangea#
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
// #Pangea
|
||||
|
|
@ -949,10 +958,10 @@ class ChatListController extends State<ChatList>
|
|||
}
|
||||
|
||||
// #Pangea
|
||||
// Remove a room from a space. Often, the user will have permission to set
|
||||
// the SpaceChild event for the parent space, but not the SpaceParent event.
|
||||
// This would cause a permissions error, but the child will still be removed
|
||||
// via the SpaceChild event. If that's the case, silence the error.
|
||||
/// Remove a room from a space. Often, the user will have permission to set
|
||||
/// the SpaceChild event for the parent space, but not the SpaceParent event.
|
||||
/// This would cause a permissions error, but the child will still be removed
|
||||
/// via the SpaceChild event. If that's the case, silence the error.
|
||||
Future<void> removeSpaceChild(Room space, String roomId) async {
|
||||
try {
|
||||
await space.removeSpaceChild(roomId);
|
||||
|
|
|
|||
|
|
@ -70,34 +70,34 @@ class NewGroupView extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SwitchListTile.adaptive(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
secondary: const Icon(Icons.public_outlined),
|
||||
title: Text(L10n.of(context)!.groupIsPublic),
|
||||
value: controller.publicGroup,
|
||||
onChanged: controller.loading ? null : controller.setPublicGroup,
|
||||
),
|
||||
AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
child: controller.publicGroup
|
||||
? SwitchListTile.adaptive(
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 32),
|
||||
secondary: const Icon(Icons.search_outlined),
|
||||
// #Pangea
|
||||
// title: Text(L10n.of(context)!.groupCanBeFoundViaSearch),
|
||||
title: Text(L10n.of(context)!.chatCanBeFoundViaSearch),
|
||||
// Pangea#
|
||||
value: controller.groupCanBeFound,
|
||||
onChanged: controller.loading
|
||||
? null
|
||||
: controller.setGroupCanBeFound,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
// #Pangea
|
||||
// SwitchListTile.adaptive(
|
||||
// contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
// secondary: const Icon(Icons.public_outlined),
|
||||
// title: Text(L10n.of(context)!.groupIsPublic),
|
||||
// value: controller.publicGroup,
|
||||
// onChanged: controller.loading ? null : controller.setPublicGroup,
|
||||
// ),
|
||||
// AnimatedSize(
|
||||
// duration: FluffyThemes.animationDuration,
|
||||
// child: controller.publicGroup
|
||||
// ? SwitchListTile.adaptive(
|
||||
// contentPadding:
|
||||
// const EdgeInsets.symmetric(horizontal: 32),
|
||||
// secondary: const Icon(Icons.search_outlined),
|
||||
// // #Pangea
|
||||
// // title: Text(L10n.of(context)!.groupCanBeFoundViaSearch),
|
||||
// title: Text(L10n.of(context)!.chatCanBeFoundViaSearch),
|
||||
// // Pangea#
|
||||
// value: controller.groupCanBeFound,
|
||||
// onChanged: controller.loading
|
||||
// ? null
|
||||
// : controller.setGroupCanBeFound,
|
||||
// )
|
||||
// : const SizedBox.shrink(),
|
||||
// ),
|
||||
// SwitchListTile.adaptive(
|
||||
// contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
// secondary: Icon(
|
||||
// Icons.lock_outlined,
|
||||
// color: theme.colorScheme.onSurface,
|
||||
|
|
|
|||
|
|
@ -27,10 +27,13 @@ class NewSpace extends StatefulWidget {
|
|||
class NewSpaceController extends State<NewSpace> {
|
||||
TextEditingController nameController = TextEditingController();
|
||||
TextEditingController topicController = TextEditingController();
|
||||
bool publicGroup = false;
|
||||
|
||||
// #Pangea
|
||||
bool spaceCanBeFound = true;
|
||||
// bool publicGroup = false;
|
||||
bool requiredCodeToJoin = false;
|
||||
bool spaceCanBeFound = false;
|
||||
// Pangea#
|
||||
|
||||
bool loading = false;
|
||||
String? nameError;
|
||||
String? topicError;
|
||||
|
|
@ -55,10 +58,13 @@ class NewSpaceController extends State<NewSpace> {
|
|||
void setSpaceCanBeFound(bool b) => setState(() => spaceCanBeFound = b);
|
||||
// Pangea#
|
||||
|
||||
void setPublicGroup(bool b) => setState(() => publicGroup = b);
|
||||
// #Pangea
|
||||
// void setPublicGroup(bool b) => setState(() => publicGroup = b);
|
||||
void setRequireCode(bool b) => setState(() => requiredCodeToJoin = b);
|
||||
// Pangea#
|
||||
|
||||
// #Pangea
|
||||
List<StateEvent> initialState(String joinCode, bool publicGroup) {
|
||||
List<StateEvent> initialState(String joinCode) {
|
||||
return [
|
||||
StateEvent(
|
||||
type: EventTypes.RoomPowerLevels,
|
||||
|
|
@ -77,9 +83,9 @@ class NewSpaceController extends State<NewSpace> {
|
|||
StateEvent(
|
||||
type: sdk.EventTypes.RoomJoinRules,
|
||||
content: {
|
||||
ModelKey.joinRule: publicGroup
|
||||
? sdk.JoinRules.public.toString().replaceAll('JoinRules.', '')
|
||||
: sdk.JoinRules.invite.toString().replaceAll('JoinRules.', ''),
|
||||
ModelKey.joinRule: requiredCodeToJoin
|
||||
? sdk.JoinRules.knock.toString().replaceAll('JoinRules.', '')
|
||||
: sdk.JoinRules.public.toString().replaceAll('JoinRules.', ''),
|
||||
ModelKey.accessCode: joinCode,
|
||||
},
|
||||
),
|
||||
|
|
@ -109,24 +115,25 @@ class NewSpaceController extends State<NewSpace> {
|
|||
// Pangea#
|
||||
|
||||
final spaceId = await client.createRoom(
|
||||
preset: publicGroup
|
||||
? sdk.CreateRoomPreset.publicChat
|
||||
: sdk.CreateRoomPreset.privateChat,
|
||||
// #Pangea
|
||||
visibility: publicGroup && spaceCanBeFound
|
||||
? sdk.Visibility.public
|
||||
: sdk.Visibility.private,
|
||||
// preset: publicGroup
|
||||
// ? sdk.CreateRoomPreset.publicChat
|
||||
// : sdk.CreateRoomPreset.privateChat,
|
||||
visibility:
|
||||
spaceCanBeFound ? sdk.Visibility.public : sdk.Visibility.private,
|
||||
// Pangea#
|
||||
creationContent: {'type': RoomCreationTypes.mSpace},
|
||||
roomAliasName: publicGroup
|
||||
? nameController.text.trim().toLowerCase().replaceAll(' ', '_')
|
||||
: null,
|
||||
// #Pangea
|
||||
// roomAliasName: publicGroup
|
||||
// ? nameController.text.trim().toLowerCase().replaceAll(' ', '_')
|
||||
// : null,
|
||||
// Pangea#
|
||||
name: nameController.text.trim(),
|
||||
topic: topicController.text.isEmpty ? null : topicController.text,
|
||||
powerLevelContentOverride: {'events_default': 100},
|
||||
initialState: [
|
||||
// #Pangea
|
||||
...initialState(joinCode, publicGroup),
|
||||
...initialState(joinCode),
|
||||
// Pangea#
|
||||
if (avatar != null)
|
||||
sdk.StateEvent(
|
||||
|
|
|
|||
|
|
@ -58,18 +58,20 @@ class NewSpaceView extends StatelessWidget {
|
|||
const SizedBox(height: 16),
|
||||
SwitchListTile.adaptive(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
title: Text(L10n.of(context)!.spaceIsPublic),
|
||||
value: controller.publicGroup,
|
||||
onChanged: controller.setPublicGroup,
|
||||
// #Pangea
|
||||
// title: Text(L10n.of(context)!.spaceIsPublic),
|
||||
title: Text(L10n.of(context)!.requireCodeToJoin),
|
||||
// Pangea#
|
||||
value: controller.requiredCodeToJoin,
|
||||
onChanged: controller.setRequireCode,
|
||||
),
|
||||
// #Pangea
|
||||
if (controller.publicGroup)
|
||||
SwitchListTile.adaptive(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
title: Text(L10n.of(context)!.spaceCanBeFoundViaSearch),
|
||||
value: controller.spaceCanBeFound,
|
||||
onChanged: controller.setSpaceCanBeFound,
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
title: Text(L10n.of(context)!.canFindInSearch),
|
||||
value: controller.spaceCanBeFound,
|
||||
onChanged: controller.setSpaceCanBeFound,
|
||||
),
|
||||
// Pangea#
|
||||
ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
// import markdown.dart
|
||||
import 'package:html_unescape/html_unescape.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:matrix/src/utils/markdown.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
|
|
|||
|
|
@ -109,25 +109,35 @@ extension ChildrenAndParentsRoomExtension on Room {
|
|||
}
|
||||
|
||||
/// Wrapper around call to setSpaceChild with added functionality
|
||||
/// to prevent adding one room to multiple spaces
|
||||
/// to prevent adding one room to multiple spaces, and resets the
|
||||
/// subspace's JoinRules and Visibility to defaults.
|
||||
Future<void> _pangeaSetSpaceChild(
|
||||
String roomId, {
|
||||
bool? suggested,
|
||||
}) async {
|
||||
final Room? child = client.getRoomById(roomId);
|
||||
if (child != null) {
|
||||
final List<Room> spaceParents = child.pangeaSpaceParents;
|
||||
for (final Room parent in spaceParents) {
|
||||
try {
|
||||
await parent.removeSpaceChild(roomId);
|
||||
} catch (e) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
m: 'Failed to remove child from parent',
|
||||
);
|
||||
}
|
||||
if (child == null) return;
|
||||
final List<Room> spaceParents = child.pangeaSpaceParents;
|
||||
for (final Room parent in spaceParents) {
|
||||
try {
|
||||
await parent.removeSpaceChild(roomId);
|
||||
} catch (e) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
m: 'Failed to remove child from parent',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await setSpaceChild(roomId, suggested: suggested);
|
||||
await child.setJoinRules(JoinRules.public);
|
||||
await child.client.setRoomVisibilityOnDirectory(
|
||||
roomId,
|
||||
visibility: matrix.Visibility.private,
|
||||
);
|
||||
} catch (err, stack) {
|
||||
ErrorHandler.logError(e: err, s: stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -313,14 +313,18 @@ class PangeaChatDetailsView extends StatelessWidget {
|
|||
),
|
||||
if (isGroupChat && room.isRoomAdmin)
|
||||
Divider(color: theme.dividerColor, height: 1),
|
||||
if (room.isRoomAdmin)
|
||||
if (room.isRoomAdmin &&
|
||||
room.isSpace &&
|
||||
room.spaceParents.isEmpty)
|
||||
VisibilityToggle(
|
||||
room: room,
|
||||
setVisibility: controller.setVisibility,
|
||||
setJoinRules: controller.setJoinRules,
|
||||
iconColor: iconColor,
|
||||
),
|
||||
if (room.isRoomAdmin)
|
||||
if (room.isRoomAdmin &&
|
||||
room.isSpace &&
|
||||
room.spaceParents.isEmpty)
|
||||
Divider(color: theme.dividerColor, height: 1),
|
||||
RoomCapacityButton(
|
||||
room: room,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
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;
|
||||
|
|
@ -23,17 +22,6 @@ class AddRoomDialogState extends State<AddRoomDialog> {
|
|||
final TextEditingController _roomDescriptionController =
|
||||
TextEditingController();
|
||||
|
||||
matrix.Visibility visibility = matrix.Visibility.public;
|
||||
JoinRules joinRules = JoinRules.public;
|
||||
|
||||
Future<void> _setJoinRules(JoinRules newJoinRules) async {
|
||||
setState(() => joinRules = newJoinRules);
|
||||
}
|
||||
|
||||
Future<void> _setVisibility(matrix.Visibility newVisibility) async {
|
||||
setState(() => visibility = newVisibility);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_roomNameController.dispose();
|
||||
|
|
@ -98,13 +86,6 @@ class AddRoomDialogState extends State<AddRoomDialog> {
|
|||
],
|
||||
),
|
||||
),
|
||||
VisibilityToggle(
|
||||
setJoinRules: _setJoinRules,
|
||||
setVisibility: _setVisibility,
|
||||
spaceMode: widget.roomType == AddRoomType.subspace,
|
||||
visibility: visibility,
|
||||
joinRules: joinRules,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
|
|
@ -121,13 +102,12 @@ class AddRoomDialogState extends State<AddRoomDialog> {
|
|||
onPressed: () async {
|
||||
final isValid = _formKey.currentState!.validate();
|
||||
if (!isValid) return;
|
||||
|
||||
Navigator.of(context).pop(
|
||||
RoomResponse(
|
||||
roomName: _roomNameController.text,
|
||||
roomDescription: _roomDescriptionController.text,
|
||||
joinRules: joinRules,
|
||||
visibility: visibility,
|
||||
joinRules: JoinRules.public,
|
||||
visibility: matrix.Visibility.private,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class VisibilityToggle extends StatelessWidget {
|
|||
this.iconColor,
|
||||
this.spaceMode = false,
|
||||
this.visibility = matrix.Visibility.private,
|
||||
this.joinRules = JoinRules.invite,
|
||||
this.joinRules = JoinRules.knock,
|
||||
this.showSearchToggle = true,
|
||||
super.key,
|
||||
});
|
||||
|
|
@ -40,9 +40,7 @@ class VisibilityToggle extends StatelessWidget {
|
|||
SwitchListTile.adaptive(
|
||||
activeColor: AppConfig.activeToggleColor,
|
||||
title: Text(
|
||||
room?.isSpace ?? spaceMode
|
||||
? L10n.of(context)!.spaceIsPublic
|
||||
: L10n.of(context)!.groupIsPublic,
|
||||
L10n.of(context)!.requireCodeToJoin,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
|
@ -51,45 +49,40 @@ class VisibilityToggle extends StatelessWidget {
|
|||
secondary: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
foregroundColor: iconColor,
|
||||
child: const Icon(Icons.public_outlined),
|
||||
child: const Icon(Icons.key_outlined),
|
||||
),
|
||||
value: _isPublic,
|
||||
value: !_isPublic,
|
||||
onChanged: (value) =>
|
||||
setJoinRules(value ? JoinRules.public : JoinRules.invite),
|
||||
setJoinRules(value ? JoinRules.knock : JoinRules.public),
|
||||
),
|
||||
if (_isPublic && showSearchToggle)
|
||||
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)!.spaceCanBeFoundViaSearch
|
||||
: L10n.of(context)!.chatCanBeFoundViaSearch,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
FutureBuilder(
|
||||
future: room != null
|
||||
? Matrix.of(context).client.getRoomVisibilityOnDirectory(room!.id)
|
||||
: null,
|
||||
builder: (context, snapshot) {
|
||||
return SwitchListTile.adaptive(
|
||||
activeColor: AppConfig.activeToggleColor,
|
||||
title: Text(
|
||||
L10n.of(context)!.canFindInSearch,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
secondary: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
foregroundColor: iconColor,
|
||||
child: const Icon(Icons.search_outlined),
|
||||
),
|
||||
value: room != null
|
||||
? snapshot.data == matrix.Visibility.public
|
||||
: visibility == matrix.Visibility.public,
|
||||
onChanged: (value) => setVisibility(
|
||||
value ? matrix.Visibility.public : matrix.Visibility.private,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
secondary: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
foregroundColor: iconColor,
|
||||
child: const Icon(Icons.search_outlined),
|
||||
),
|
||||
value: room != null
|
||||
? snapshot.data == matrix.Visibility.public
|
||||
: visibility == matrix.Visibility.public,
|
||||
onChanged: (value) => setVisibility(
|
||||
value ? matrix.Visibility.public : matrix.Visibility.private,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue