2742 bring back starter chats for top level spaces (#2784)
* feat: added introducton and accouncements chats to new space * chore: make spaceID redirect clearer * chore: remove bot from default power levels
This commit is contained in:
parent
33425f4406
commit
ebf4224cba
18 changed files with 372 additions and 175 deletions
|
|
@ -253,29 +253,39 @@ abstract class AppRoutes {
|
|||
// redirect: loggedOutRedirect,
|
||||
redirect: (context, state) async {
|
||||
final resp = await loggedOutRedirect(context, state);
|
||||
final spaceId = state.uri.queryParameters['spaceId'];
|
||||
if (resp != null) return resp;
|
||||
final isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
|
||||
final roomId = state.pathParameters['roomid'];
|
||||
final room = roomId != null
|
||||
? Matrix.of(context).client.getRoomById(roomId)
|
||||
: null;
|
||||
|
||||
if (room != null &&
|
||||
room.isSpace &&
|
||||
!FluffyThemes.isColumnMode(context) &&
|
||||
(state.fullPath?.endsWith(':roomid') ?? false)) {
|
||||
return '/rooms?spaceId=${room.id}';
|
||||
if (room != null && room.isSpace) {
|
||||
// If a user is on mobile and they end up on the space
|
||||
// page, redirect them and set the activeSpaceId
|
||||
if (!isColumnMode &&
|
||||
(state.fullPath?.endsWith(':roomid') ?? false)) {
|
||||
return '/rooms?spaceId=${room.id}';
|
||||
}
|
||||
}
|
||||
|
||||
if (resp != null ||
|
||||
!state.uri.queryParameters.containsKey('spaceId') ||
|
||||
spaceId == 'clear' ||
|
||||
!FluffyThemes.isColumnMode(context) ||
|
||||
state.path == ':roomid') {
|
||||
return resp;
|
||||
if (state.uri.queryParameters.containsKey('spaceId')) {
|
||||
final spaceId = state.uri.queryParameters['spaceId'];
|
||||
if (spaceId == null || spaceId == 'clear') {
|
||||
// Have to load chat list to clear the spaceId, so don't redirect
|
||||
return null;
|
||||
}
|
||||
|
||||
// If spaceId is not null, and on web, and not on the space page,
|
||||
// redirect to the space page
|
||||
if (isColumnMode &&
|
||||
!(state.fullPath?.endsWith(':roomid') ?? false)) {
|
||||
return '/rooms/$spaceId?spaceId=$spaceId';
|
||||
}
|
||||
}
|
||||
|
||||
return '/rooms/$spaceId?spaceId=${spaceId ?? 'clear'}';
|
||||
return null;
|
||||
},
|
||||
// Pangea#
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
|
|
|
|||
|
|
@ -406,7 +406,9 @@ class ChatView extends StatelessWidget {
|
|||
),
|
||||
// #Pangea
|
||||
ChatViewBackground(controller.choreographer),
|
||||
if (!controller.room.isAbandonedDMRoom)
|
||||
if (!controller.room.isAbandonedDMRoom &&
|
||||
controller.room.canSendDefaultMessages &&
|
||||
controller.room.membership == Membership.join)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
|
|
|
|||
|
|
@ -534,7 +534,9 @@ class ChatListController extends State<ChatList>
|
|||
final String? justInputtedCode =
|
||||
MatrixState.pangeaController.classController.justInputtedCode();
|
||||
final newSpaceCode = space?.classCode(context);
|
||||
if (newSpaceCode == justInputtedCode) return;
|
||||
if (newSpaceCode?.toLowerCase() == justInputtedCode?.toLowerCase()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (space != null) {
|
||||
chatListHandleSpaceTap(
|
||||
|
|
|
|||
|
|
@ -383,15 +383,21 @@ class PublicRoomsHorizontalListState extends State<PublicRoomsHorizontalList> {
|
|||
L10n.of(context).chat,
|
||||
// Pangea#
|
||||
avatar: publicRooms[i].avatarUrl,
|
||||
onPressed: () => showAdaptiveDialog(
|
||||
context: context,
|
||||
builder: (c) => PublicRoomDialog(
|
||||
roomAlias: publicRooms[i].canonicalAlias ??
|
||||
publicRooms[i].roomId,
|
||||
chunk: publicRooms[i],
|
||||
),
|
||||
),
|
||||
// #Pangea
|
||||
onPressed: () => PublicRoomDialog.show(
|
||||
context: context,
|
||||
roomAlias:
|
||||
publicRooms[i].canonicalAlias ?? publicRooms[i].roomId,
|
||||
chunk: publicRooms[i],
|
||||
),
|
||||
// onPressed: () => showAdaptiveDialog(
|
||||
// context: context,
|
||||
// builder: (c) => PublicRoomDialog(
|
||||
// roomAlias: publicRooms[i].canonicalAlias ??
|
||||
// publicRooms[i].roomId,
|
||||
// chunk: publicRooms[i],
|
||||
// ),
|
||||
// ),
|
||||
radius: BorderRadius.circular(
|
||||
AppConfig.borderRadius / 2,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
|||
import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
|
||||
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
|
||||
import 'package:fluffychat/pangea/spaces/widgets/knocking_users_indicator.dart';
|
||||
import 'package:fluffychat/pangea/spaces/widgets/space_view_leaderboard.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
|
|
@ -89,7 +91,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
// and reload the hierarchy when they come through
|
||||
final client = Matrix.of(context).client;
|
||||
_roomSubscription ??= client.onSync.stream
|
||||
.where(hasHierarchyUpdate)
|
||||
.where(_hasHierarchyUpdate)
|
||||
.listen((update) => loadHierarchy(hasUpdate: true));
|
||||
// Pangea#
|
||||
super.initState();
|
||||
|
|
@ -124,6 +126,44 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _joinDefaultChats() async {
|
||||
if (_discoveredChildren == null) return;
|
||||
final found = List<SpaceRoomsChunk>.from(_discoveredChildren!);
|
||||
|
||||
final List<Future> joinFutures = [];
|
||||
for (final chunk in found) {
|
||||
if (chunk.canonicalAlias == null) continue;
|
||||
final alias = chunk.canonicalAlias!;
|
||||
|
||||
final isDefaultChat = (alias.localpart ?? '')
|
||||
.startsWith(SpaceConstants.announcementsChatAlias) ||
|
||||
(alias.localpart ?? '')
|
||||
.startsWith(SpaceConstants.introductionChatAlias);
|
||||
|
||||
if (!isDefaultChat) continue;
|
||||
|
||||
joinFutures.add(
|
||||
Matrix.of(context).client.joinRoom(alias).then((_) {
|
||||
_discoveredChildren?.remove(chunk);
|
||||
}).catchError((e, s) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: {
|
||||
'alias': alias,
|
||||
'spaceId': widget.spaceId,
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (joinFutures.isNotEmpty) {
|
||||
await Future.wait(joinFutures);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> loadHierarchy({hasUpdate = false}) async {
|
||||
final room = Matrix.of(context).client.getRoomById(widget.spaceId);
|
||||
if (room == null) return;
|
||||
|
|
@ -134,6 +174,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
|
||||
try {
|
||||
await _loadHierarchy(activeSpace: room, hasUpdate: hasUpdate);
|
||||
await _joinDefaultChats();
|
||||
} catch (e, s) {
|
||||
Logs().w('Unable to load hierarchy', e, s);
|
||||
if (!mounted) return;
|
||||
|
|
@ -208,12 +249,12 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
|
||||
// finally, set the response to the last response for this space
|
||||
// and set the current next batch token
|
||||
currentHierarchy = filterHierarchyResponse(activeSpace, response.rooms);
|
||||
currentHierarchy = _filterHierarchyResponse(activeSpace, response.rooms);
|
||||
currentNextBatch = response.nextBatch;
|
||||
}
|
||||
|
||||
_discoveredChildren = currentHierarchy;
|
||||
_discoveredChildren?.sort(sortSpaceChildren);
|
||||
_discoveredChildren?.sort(_sortSpaceChildren);
|
||||
_nextBatch = currentNextBatch;
|
||||
}
|
||||
|
||||
|
|
@ -260,17 +301,28 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
final client = Matrix.of(context).client;
|
||||
final space = client.getRoomById(widget.spaceId);
|
||||
|
||||
final joined = await showAdaptiveDialog<bool>(
|
||||
// #Pangea
|
||||
// final joined = await showAdaptiveDialog<bool>(
|
||||
// context: context,
|
||||
// builder: (_) => PublicRoomDialog(
|
||||
// chunk: item,
|
||||
// via: space?.spaceChildren
|
||||
// .firstWhereOrNull(
|
||||
// (child) => child.roomId == item.roomId,
|
||||
// )
|
||||
// ?.via,
|
||||
// ),
|
||||
// );
|
||||
final joined = await PublicRoomDialog.show(
|
||||
context: context,
|
||||
builder: (_) => PublicRoomDialog(
|
||||
chunk: item,
|
||||
via: space?.spaceChildren
|
||||
.firstWhereOrNull(
|
||||
(child) => child.roomId == item.roomId,
|
||||
)
|
||||
?.via,
|
||||
),
|
||||
chunk: item,
|
||||
via: space?.spaceChildren
|
||||
.firstWhereOrNull(
|
||||
(child) => child.roomId == item.roomId,
|
||||
)
|
||||
?.via,
|
||||
);
|
||||
// Pangea#
|
||||
if (mounted && joined == true) {
|
||||
setState(() {
|
||||
// #Pangea
|
||||
|
|
@ -394,7 +446,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
// Pangea#
|
||||
|
||||
// #Pangea
|
||||
bool includeSpaceChild(
|
||||
bool _includeSpaceChild(
|
||||
Room space,
|
||||
SpaceRoomsChunk hierarchyMember,
|
||||
) {
|
||||
|
|
@ -412,7 +464,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
return !isAnalyticsRoom && (isMember || isSuggested);
|
||||
}
|
||||
|
||||
List<SpaceRoomsChunk> filterHierarchyResponse(
|
||||
List<SpaceRoomsChunk> _filterHierarchyResponse(
|
||||
Room space,
|
||||
List<SpaceRoomsChunk> hierarchyResponse,
|
||||
) {
|
||||
|
|
@ -428,7 +480,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
);
|
||||
if (isDuplicate) continue;
|
||||
|
||||
if (includeSpaceChild(space, child)) {
|
||||
if (_includeSpaceChild(space, child)) {
|
||||
filteredChildren.add(child);
|
||||
}
|
||||
}
|
||||
|
|
@ -437,7 +489,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
|
||||
/// Used to filter out sync updates with hierarchy updates for the active
|
||||
/// space so that the view can be auto-reloaded in the room subscription
|
||||
bool hasHierarchyUpdate(SyncUpdate update) {
|
||||
bool _hasHierarchyUpdate(SyncUpdate update) {
|
||||
final joinTimeline = update.rooms?.join?[widget.spaceId]?.timeline;
|
||||
final leaveTimeline = update.rooms?.leave?[widget.spaceId]?.timeline;
|
||||
if (joinTimeline == null && leaveTimeline == null) return false;
|
||||
|
|
@ -452,7 +504,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
return hasJoinUpdate || hasLeaveUpdate;
|
||||
}
|
||||
|
||||
int sortSpaceChildren(
|
||||
int _sortSpaceChildren(
|
||||
SpaceRoomsChunk a,
|
||||
SpaceRoomsChunk b,
|
||||
) {
|
||||
|
|
@ -466,19 +518,6 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<Room>? get joinedRooms {
|
||||
final room = Matrix.of(context).client.getRoomById(widget.spaceId);
|
||||
if (room == null) return null;
|
||||
|
||||
final spaceChildIds =
|
||||
room.spaceChildren.map((c) => c.roomId).whereType<String>().toSet();
|
||||
|
||||
return room.client.rooms
|
||||
.where((room) => spaceChildIds.contains(room.id))
|
||||
.where((room) => !room.isAnalyticsRoom)
|
||||
.toList();
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -11,12 +11,10 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/pages/new_group/new_group_view.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
|
||||
import 'package:fluffychat/pangea/chat/constants/default_power_level.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
|
||||
import 'package:fluffychat/pangea/spaces/utils/space_code.dart';
|
||||
import 'package:fluffychat/pangea/spaces/utils/client_spaces_extension.dart';
|
||||
import 'package:fluffychat/utils/file_selector.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
|
|
@ -197,44 +195,40 @@ class NewGroupController extends State<NewGroup> {
|
|||
Future<void> _createSpace() async {
|
||||
if (!mounted) return;
|
||||
// #Pangea
|
||||
final client = Matrix.of(context).client;
|
||||
final joinCode = await SpaceCodeUtil.generateSpaceCode(client);
|
||||
// Pangea#
|
||||
final spaceId = await Matrix.of(context).client.createRoom(
|
||||
// #Pangea
|
||||
// preset: publicGroup
|
||||
// ? sdk.CreateRoomPreset.publicChat
|
||||
// : sdk.CreateRoomPreset.privateChat,
|
||||
// Pangea#
|
||||
creationContent: {'type': RoomCreationTypes.mSpace},
|
||||
// #Pangea
|
||||
// visibility: publicGroup ? sdk.Visibility.public : null,
|
||||
// final spaceId = await Matrix.of(context).client.createRoom(
|
||||
// preset: publicGroup
|
||||
// ? sdk.CreateRoomPreset.publicChat
|
||||
// : sdk.CreateRoomPreset.privateChat,
|
||||
// creationContent: {'type': RoomCreationTypes.mSpace},
|
||||
// visibility: publicGroup ? sdk.Visibility.public : null,
|
||||
// roomAliasName: publicGroup
|
||||
// ? nameController.text.trim().toLowerCase().replaceAll(' ', '_')
|
||||
// : null,
|
||||
// name: nameController.text.trim(),
|
||||
// powerLevelContentOverride: {'events_default': 100},
|
||||
// initialState: [
|
||||
// if (avatar != null)
|
||||
// sdk.StateEvent(
|
||||
// type: sdk.EventTypes.RoomAvatar,
|
||||
// content: {'url': avatarUrl.toString()},
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// if (!mounted) return;
|
||||
// context.pop<String>(spaceId);
|
||||
final spaceId = await Matrix.of(context).client.createPangeaSpace(
|
||||
name: nameController.text,
|
||||
visibility:
|
||||
groupCanBeFound ? sdk.Visibility.public : sdk.Visibility.private,
|
||||
// roomAliasName: publicGroup
|
||||
// ? nameController.text.trim().toLowerCase().replaceAll(' ', '_')
|
||||
// : null,
|
||||
// Pangea#
|
||||
name: nameController.text.trim(),
|
||||
powerLevelContentOverride: {'events_default': 100},
|
||||
initialState: [
|
||||
// #Pangea
|
||||
..._spaceInitialState(joinCode),
|
||||
// Pangea#
|
||||
if (avatar != null)
|
||||
sdk.StateEvent(
|
||||
type: sdk.EventTypes.RoomAvatar,
|
||||
content: {'url': avatarUrl.toString()},
|
||||
),
|
||||
],
|
||||
joinRules:
|
||||
requiredCodeToJoin ? sdk.JoinRules.knock : sdk.JoinRules.public,
|
||||
avatar: avatar,
|
||||
avatarUrl: avatarUrl,
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
// #Pangea
|
||||
Room? room = client.getRoomById(spaceId);
|
||||
if (room == null) {
|
||||
await Matrix.of(context).client.waitForRoomInSync(spaceId);
|
||||
room = client.getRoomById(spaceId);
|
||||
}
|
||||
|
||||
final room = Matrix.of(context).client.getRoomById(spaceId);
|
||||
if (room == null) return;
|
||||
final spaceCode = room.classCode(context);
|
||||
if (spaceCode != null) {
|
||||
|
|
@ -245,38 +239,8 @@ class NewGroupController extends State<NewGroup> {
|
|||
if (error != null) return;
|
||||
context.go("/rooms?spaceId=$spaceId");
|
||||
// Pangea#
|
||||
context.pop<String>(spaceId);
|
||||
}
|
||||
|
||||
// #Pangea
|
||||
List<StateEvent> _spaceInitialState(String joinCode) {
|
||||
return [
|
||||
StateEvent(
|
||||
type: EventTypes.RoomPowerLevels,
|
||||
stateKey: '',
|
||||
content: {
|
||||
'events': {
|
||||
EventTypes.SpaceChild: 50,
|
||||
},
|
||||
'users_default': 0,
|
||||
'users': {
|
||||
Matrix.of(context).client.userID: SpaceConstants.powerLevelOfAdmin,
|
||||
},
|
||||
},
|
||||
),
|
||||
StateEvent(
|
||||
type: sdk.EventTypes.RoomJoinRules,
|
||||
content: {
|
||||
ModelKey.joinRule: requiredCodeToJoin
|
||||
? sdk.JoinRules.knock.toString().replaceAll('JoinRules.', '')
|
||||
: sdk.JoinRules.public.toString().replaceAll('JoinRules.', ''),
|
||||
ModelKey.accessCode: joinCode,
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
//Pangea#
|
||||
|
||||
void submitAction([_]) async {
|
||||
final client = Matrix.of(context).client;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
|
|
@ -13,7 +14,6 @@ import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'
|
|||
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_icon.dart';
|
||||
import 'package:fluffychat/pangea/user/client_extension.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class MorphAnalyticsListView extends StatelessWidget {
|
||||
|
|
@ -183,7 +183,8 @@ class MorphTagChip extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final unlocked = constructAnalytics.points > 0;
|
||||
final unlocked = constructAnalytics.points > 0 ||
|
||||
Matrix.of(context).client.userID == Environment.supportUserId;
|
||||
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
|
|
@ -216,7 +217,7 @@ class MorphTagChip extends StatelessWidget {
|
|||
SizedBox(
|
||||
width: 28.0,
|
||||
height: 28.0,
|
||||
child: unlocked || Matrix.of(context).client.isSupportAccount
|
||||
child: unlocked
|
||||
? MorphIcon(
|
||||
morphFeature: feature,
|
||||
morphTag: morphTag,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,21 @@
|
|||
Map<String, dynamic> defaultPowerLevels(String userID) => {
|
||||
"defaults": {
|
||||
"ban": 50,
|
||||
"events_default": 0,
|
||||
"invite": 50,
|
||||
"kick": 50,
|
||||
"notifications": {
|
||||
"room": 50,
|
||||
},
|
||||
"redact": 50,
|
||||
"state_default": 50,
|
||||
"users_default": 0,
|
||||
},
|
||||
"events": {
|
||||
"m.room.avatar": 50,
|
||||
"m.room.canonical_alias": 50,
|
||||
"m.room.encryption": 100,
|
||||
"m.room.history_visibility": 100,
|
||||
"m.room.name": 50,
|
||||
"m.room.power_levels": 100,
|
||||
"m.room.server_acl": 100,
|
||||
"m.room.tombstone": 100,
|
||||
},
|
||||
"users": {
|
||||
userID: 100,
|
||||
},
|
||||
};
|
||||
|
||||
Map<String, dynamic> restrictedPowerLevels(String userID) => {
|
||||
"events_default": 50,
|
||||
"events": {
|
||||
"m.room.avatar": 50,
|
||||
"m.room.canonical_alias": 50,
|
||||
|
|
|
|||
|
|
@ -172,11 +172,13 @@ class PangeaController {
|
|||
getAnalytics.dispose();
|
||||
userController.clear();
|
||||
_languageStream?.cancel();
|
||||
_languageStream = null;
|
||||
break;
|
||||
case LoginState.loggedIn:
|
||||
// Initialize analytics data
|
||||
putAnalytics.initialize();
|
||||
getAnalytics.initialize();
|
||||
_setLanguageStream();
|
||||
break;
|
||||
}
|
||||
if (state != LoginState.loggedIn) {
|
||||
|
|
@ -352,9 +354,12 @@ class PangeaController {
|
|||
void _subscribeToStreams() {
|
||||
matrixState.client.onLoginStateChanged.stream
|
||||
.listen(_handleLoginStateChange);
|
||||
_setLanguageStream();
|
||||
}
|
||||
|
||||
// Listen for changes to the user's language settings
|
||||
_languageStream ??= userController.stateStream.listen((update) {
|
||||
void _setLanguageStream() {
|
||||
_languageStream?.cancel();
|
||||
_languageStream = userController.stateStream.listen((update) {
|
||||
if (update is Map<String, dynamic> &&
|
||||
update['prev_target_lang'] != null) {
|
||||
clearCache();
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@ extension ChildrenAndParentsRoomExtension on Room {
|
|||
throw NestedSpaceError();
|
||||
}
|
||||
|
||||
final List<Room> spaceParents =
|
||||
ChildrenAndParentsRoomExtension(child).pangeaSpaceParents;
|
||||
for (final Room parent in spaceParents) {
|
||||
for (final Room parent in pangeaSpaceParents) {
|
||||
try {
|
||||
await parent.removeSpaceChild(roomId);
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -24,12 +24,10 @@ class PublicSpaceCard extends StatelessWidget {
|
|||
final theme = Theme.of(context);
|
||||
|
||||
return PressableButton(
|
||||
onPressed: () => showAdaptiveDialog(
|
||||
onPressed: () => PublicRoomDialog.show(
|
||||
context: context,
|
||||
builder: (c) => PublicRoomDialog(
|
||||
roomAlias: space.canonicalAlias ?? space.roomId,
|
||||
chunk: space,
|
||||
),
|
||||
roomAlias: space.canonicalAlias ?? space.roomId,
|
||||
chunk: space,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(24.0),
|
||||
color: theme.brightness == Brightness.dark
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ class SpaceConstants {
|
|||
static const defaultDominantLanguage = "en";
|
||||
static const defaultTargetLanguage = "es";
|
||||
static const String classCode = 'classcode';
|
||||
static const String introductionChatAlias = 'introductionChat';
|
||||
static const String announcementsChatAlias = 'announcementsChat';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ class ClassController extends BaseController {
|
|||
final spaceID = await showFutureLoadingDialog<String?>(
|
||||
context: context,
|
||||
future: () async {
|
||||
await _classStorage.write(
|
||||
PLocalKey.justInputtedCode,
|
||||
classCode,
|
||||
);
|
||||
|
||||
final knockResponse = await client.httpClient.post(
|
||||
Uri.parse(
|
||||
'${client.homeserver}/_synapse/client/pangea/v1/knock_with_code',
|
||||
|
|
@ -154,10 +159,6 @@ class ClassController extends BaseController {
|
|||
}
|
||||
|
||||
final chosenClassId = foundClasses.first;
|
||||
await _classStorage.write(
|
||||
PLocalKey.justInputtedCode,
|
||||
classCode,
|
||||
);
|
||||
return chosenClassId;
|
||||
},
|
||||
);
|
||||
|
|
|
|||
152
lib/pangea/spaces/utils/client_spaces_extension.dart
Normal file
152
lib/pangea/spaces/utils/client_spaces_extension.dart
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/chat/constants/default_power_level.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
|
||||
import 'package:fluffychat/pangea/spaces/utils/space_code.dart';
|
||||
|
||||
extension SpacesClientExtension on Client {
|
||||
Future<String> createPangeaSpace({
|
||||
required String name,
|
||||
Visibility visibility = Visibility.private,
|
||||
JoinRules joinRules = JoinRules.public,
|
||||
Uint8List? avatar,
|
||||
Uri? avatarUrl,
|
||||
}) async {
|
||||
final joinCode = await SpaceCodeUtil.generateSpaceCode(this);
|
||||
final roomId = await createRoom(
|
||||
creationContent: {'type': RoomCreationTypes.mSpace},
|
||||
visibility: visibility,
|
||||
name: name.trim(),
|
||||
powerLevelContentOverride: {'events_default': 100},
|
||||
initialState: [
|
||||
..._spaceInitialState(
|
||||
joinCode,
|
||||
joinRules: joinRules,
|
||||
),
|
||||
if (avatar != null)
|
||||
StateEvent(
|
||||
type: EventTypes.RoomAvatar,
|
||||
content: {'url': avatarUrl.toString()},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final space = await _waitForRoom(roomId);
|
||||
if (space == null) return roomId;
|
||||
|
||||
await _addDefaultSpaceChats(space: space);
|
||||
return roomId;
|
||||
}
|
||||
|
||||
Future<Room?> _waitForRoom(String roomId) async {
|
||||
final room = getRoomById(roomId);
|
||||
if (room != null) return room;
|
||||
await waitForRoomInSync(roomId, join: true).timeout(
|
||||
const Duration(seconds: 15),
|
||||
onTimeout: () {
|
||||
throw Exception('Timeout fetching room after creation');
|
||||
},
|
||||
);
|
||||
return getRoomById(roomId);
|
||||
}
|
||||
|
||||
Future<void> _addDefaultSpaceChats({
|
||||
required Room space,
|
||||
String introductionsName = "Introductions",
|
||||
String announcementsName = "Announcements",
|
||||
}) async {
|
||||
final introChatFuture = createRoom(
|
||||
preset: CreateRoomPreset.publicChat,
|
||||
visibility: Visibility.private,
|
||||
name: introductionsName,
|
||||
roomAliasName:
|
||||
"${SpaceConstants.introductionChatAlias}_${space.id.localpart}",
|
||||
initialState: [
|
||||
// if (avatar != null)
|
||||
// StateEvent(
|
||||
// type: EventTypes.RoomAvatar,
|
||||
// content: {'url': avatarUrl.toString()},
|
||||
// ),
|
||||
StateEvent(
|
||||
type: EventTypes.RoomPowerLevels,
|
||||
stateKey: '',
|
||||
content: defaultPowerLevels(userID!),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final announcementsChatFuture = createRoom(
|
||||
preset: CreateRoomPreset.publicChat,
|
||||
visibility: Visibility.private,
|
||||
name: announcementsName,
|
||||
roomAliasName:
|
||||
"${SpaceConstants.announcementsChatAlias}_${space.id.localpart}",
|
||||
initialState: [
|
||||
// if (avatar != null)
|
||||
// StateEvent(
|
||||
// type: EventTypes.RoomAvatar,
|
||||
// content: {'url': avatarUrl.toString()},
|
||||
// ),
|
||||
StateEvent(
|
||||
type: EventTypes.RoomPowerLevels,
|
||||
stateKey: '',
|
||||
content: restrictedPowerLevels(userID!),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final List<String> roomIds = await Future.wait([
|
||||
introChatFuture,
|
||||
announcementsChatFuture,
|
||||
]);
|
||||
|
||||
if (roomIds.length != 2) {
|
||||
throw Exception('Failed to create default space chats');
|
||||
}
|
||||
|
||||
final addIntroChatFuture = space.pangeaSetSpaceChild(
|
||||
roomIds[0],
|
||||
);
|
||||
|
||||
final addAnnouncementsChatFuture = space.pangeaSetSpaceChild(
|
||||
roomIds[1],
|
||||
);
|
||||
|
||||
await Future.wait([
|
||||
addIntroChatFuture,
|
||||
addAnnouncementsChatFuture,
|
||||
]);
|
||||
}
|
||||
|
||||
List<StateEvent> _spaceInitialState(
|
||||
String joinCode, {
|
||||
required JoinRules joinRules,
|
||||
}) {
|
||||
return [
|
||||
StateEvent(
|
||||
type: EventTypes.RoomPowerLevels,
|
||||
stateKey: '',
|
||||
content: {
|
||||
'events': {
|
||||
EventTypes.SpaceChild: 50,
|
||||
},
|
||||
'users_default': 0,
|
||||
'users': {
|
||||
userID: SpaceConstants.powerLevelOfAdmin,
|
||||
},
|
||||
},
|
||||
),
|
||||
StateEvent(
|
||||
type: EventTypes.RoomJoinRules,
|
||||
content: {
|
||||
ModelKey.joinRule: joinRules.toString().replaceAll('JoinRules.', ''),
|
||||
ModelKey.accessCode: joinCode,
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
|
||||
extension AccountIdentiferExt on Client {
|
||||
bool get isSupportAccount => userID == Environment.supportUserId;
|
||||
}
|
||||
|
|
@ -163,7 +163,9 @@ abstract class ClientManager {
|
|||
return event.content.tryGet(ModelKey.transcription) == null &&
|
||||
!event.type.startsWith("p.") &&
|
||||
!event.type.startsWith("pangea.") &&
|
||||
event.type != EventTypes.RoomPinnedEvents;
|
||||
event.type != EventTypes.RoomPinnedEvents &&
|
||||
event.type != EventTypes.SpaceChild &&
|
||||
event.type != EventTypes.SpaceParent;
|
||||
},
|
||||
// Pangea#
|
||||
);
|
||||
|
|
|
|||
|
|
@ -181,12 +181,18 @@ class UrlLauncher {
|
|||
}
|
||||
return;
|
||||
} else {
|
||||
await showAdaptiveDialog(
|
||||
// #Pangea
|
||||
// await showAdaptiveDialog(
|
||||
// context: context,
|
||||
// builder: (c) => PublicRoomDialog(
|
||||
// roomAlias: identityParts.primaryIdentifier,
|
||||
// ),
|
||||
// );
|
||||
await PublicRoomDialog.show(
|
||||
context: context,
|
||||
builder: (c) => PublicRoomDialog(
|
||||
roomAlias: identityParts.primaryIdentifier,
|
||||
),
|
||||
roomAlias: identityParts.primaryIdentifier,
|
||||
);
|
||||
// Pangea#
|
||||
}
|
||||
if (roomIdOrAlias.sigil == '!') {
|
||||
if (await showOkCancelAlertDialog(
|
||||
|
|
|
|||
|
|
@ -27,6 +27,31 @@ class PublicRoomDialog extends StatefulWidget {
|
|||
|
||||
const PublicRoomDialog({super.key, this.roomAlias, this.chunk, this.via});
|
||||
// #Pangea
|
||||
static Future<bool?> show({
|
||||
required BuildContext context,
|
||||
String? roomAlias,
|
||||
PublicRoomsChunk? chunk,
|
||||
List<String>? via,
|
||||
}) async {
|
||||
final room = MatrixState.pangeaController.matrixState.client
|
||||
.getRoomById(chunk!.roomId);
|
||||
|
||||
if (room != null && room.membership == Membership.join) {
|
||||
context.go("/rooms?spaceId=${room.id}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return showAdaptiveDialog(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
builder: (context) => PublicRoomDialog(
|
||||
roomAlias: roomAlias,
|
||||
chunk: chunk,
|
||||
via: via,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
State<PublicRoomDialog> createState() => PublicRoomDialogState();
|
||||
}
|
||||
|
|
@ -38,20 +63,6 @@ class PublicRoomDialogState extends State<PublicRoomDialog> {
|
|||
|
||||
final TextEditingController _codeController = TextEditingController();
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
if (chunk != null) {
|
||||
final room = MatrixState.pangeaController.matrixState.client
|
||||
.getRoomById(chunk!.roomId);
|
||||
|
||||
if (room != null && room.membership == Membership.join) {
|
||||
context.go("/rooms?spaceId=${room.id}");
|
||||
Navigator.of(context).maybePop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_codeController.dispose();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue