feat: add join space onboarding step (#2771)
This commit is contained in:
parent
757ffae1bb
commit
8ae997e642
10 changed files with 224 additions and 28 deletions
|
|
@ -4922,5 +4922,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"leaderboard": "Leaderboard"
|
||||
"leaderboard": "Leaderboard",
|
||||
"welcomeUser": "Welcome {user}",
|
||||
"@welcomeUser": {
|
||||
"placeholders": {
|
||||
"user": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"joinSpaceOnboardingDesc": "Do you have an invite code or link to a learning community?",
|
||||
"skipForNow": "Skip for now"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import 'package:fluffychat/pangea/layouts/bottom_nav_layout.dart';
|
|||
import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart';
|
||||
import 'package:fluffychat/pangea/login/pages/login_or_signup_view.dart';
|
||||
import 'package:fluffychat/pangea/login/pages/signup.dart';
|
||||
import 'package:fluffychat/pangea/login/pages/space_code_onboarding.dart';
|
||||
import 'package:fluffychat/pangea/login/pages/user_settings.dart';
|
||||
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
|
||||
import 'package:fluffychat/pangea/spaces/utils/join_with_alias.dart';
|
||||
|
|
@ -173,6 +174,19 @@ abstract class AppRoutes {
|
|||
const UserSettingsPage(),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'join_space',
|
||||
pageBuilder: (context, state) {
|
||||
return defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
const SpaceCodeOnboarding(),
|
||||
);
|
||||
},
|
||||
redirect: loggedOutRedirect,
|
||||
),
|
||||
],
|
||||
),
|
||||
ShellRoute(
|
||||
pageBuilder: chatListShellRouteBuilder,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import 'package:fluffychat/pages/chat_list/chat_list_view.dart';
|
|||
import 'package:fluffychat/pangea/chat_list/utils/app_version_util.dart';
|
||||
import 'package:fluffychat/pangea/chat_list/utils/chat_list_handle_space_tap.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/local.key.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';
|
||||
|
|
@ -43,6 +42,7 @@ import '../../widgets/matrix.dart';
|
|||
import 'package:fluffychat/utils/tor_stub.dart'
|
||||
if (dart.library.html) 'package:tor_detector_web/tor_detector_web.dart';
|
||||
|
||||
|
||||
enum PopupMenuAction {
|
||||
settings,
|
||||
invite,
|
||||
|
|
@ -533,9 +533,7 @@ class ChatListController extends State<ChatList>
|
|||
|
||||
// #Pangea
|
||||
final String? justInputtedCode =
|
||||
MatrixState.pangeaController.classController.chatBox.read(
|
||||
PLocalKey.justInputtedCode,
|
||||
);
|
||||
MatrixState.pangeaController.classController.justInputtedCode();
|
||||
final newSpaceCode = space?.classCode(context);
|
||||
if (newSpaceCode == justInputtedCode) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import 'package:matrix/matrix.dart';
|
|||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/local.key.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
|
@ -50,9 +49,8 @@ void chatListHandleSpaceTap(
|
|||
(element) =>
|
||||
element.isSpace && element.membership == Membership.join,
|
||||
);
|
||||
final justInputtedCode = MatrixState
|
||||
.pangeaController.classController.chatBox
|
||||
.read(PLocalKey.justInputtedCode);
|
||||
final justInputtedCode =
|
||||
MatrixState.pangeaController.classController.justInputtedCode();
|
||||
if (rooms.any((s) => s.spaceChildren.any((c) => c.roomId == space.id))) {
|
||||
autoJoin(space);
|
||||
} else if (justInputtedCode != null &&
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ import 'package:flutter/material.dart';
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/widgets/mxc_image.dart';
|
||||
|
||||
class PangeaLoginScaffold extends StatelessWidget {
|
||||
final String mainAssetPath;
|
||||
final Uint8List? mainAssetBytes;
|
||||
final Uri? mainAssetUrl;
|
||||
final List<Widget> children;
|
||||
final bool showAppName;
|
||||
final AppBar? customAppBar;
|
||||
|
|
@ -16,6 +18,7 @@ class PangeaLoginScaffold extends StatelessWidget {
|
|||
required this.children,
|
||||
this.mainAssetPath = "assets/pangea/PangeaChat_Glow_Logo.png",
|
||||
this.mainAssetBytes,
|
||||
this.mainAssetUrl,
|
||||
this.showAppName = true,
|
||||
this.customAppBar,
|
||||
super.key,
|
||||
|
|
@ -58,10 +61,22 @@ class PangeaLoginScaffold extends StatelessWidget {
|
|||
mainAssetBytes!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Image.asset(
|
||||
mainAssetPath,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
: mainAssetUrl != null
|
||||
? mainAssetUrl!.toString().startsWith("mxc")
|
||||
? MxcImage(
|
||||
uri: mainAssetUrl,
|
||||
fit: BoxFit.cover,
|
||||
width: isColumnMode ? 175 : 125,
|
||||
height: isColumnMode ? 175 : 125,
|
||||
)
|
||||
: Image.network(
|
||||
mainAssetUrl.toString(),
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Image.asset(
|
||||
mainAssetPath,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (showAppName)
|
||||
|
|
|
|||
76
lib/pangea/login/pages/space_code_onboarding.dart
Normal file
76
lib/pangea/login/pages/space_code_onboarding.dart
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/login/pages/space_code_onboarding_view.dart';
|
||||
import 'package:fluffychat/pangea/spaces/constants/space_constants.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class SpaceCodeOnboarding extends StatefulWidget {
|
||||
const SpaceCodeOnboarding({super.key});
|
||||
|
||||
@override
|
||||
State<SpaceCodeOnboarding> createState() => SpaceCodeOnboardingState();
|
||||
}
|
||||
|
||||
class SpaceCodeOnboardingState extends State<SpaceCodeOnboarding> {
|
||||
Profile? profile;
|
||||
Client get client => Matrix.of(context).client;
|
||||
|
||||
final TextEditingController codeController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_setProfile();
|
||||
codeController.addListener(() {
|
||||
if (mounted) setState(() {});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
codeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _setProfile() async {
|
||||
try {
|
||||
profile = await client.getProfileFromUserId(
|
||||
client.userID!,
|
||||
);
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: {
|
||||
'userId': client.userID,
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> submitCode() async {
|
||||
String code = codeController.text.trim();
|
||||
if (code.isEmpty) return;
|
||||
|
||||
try {
|
||||
final link = Uri.parse(Uri.parse(code).fragment);
|
||||
if (link.queryParameters.containsKey(SpaceConstants.classCode)) {
|
||||
code = link.queryParameters[SpaceConstants.classCode]!;
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("Text input is not a URL: $e");
|
||||
}
|
||||
|
||||
await MatrixState.pangeaController.classController
|
||||
.joinClasswithCode(context, code);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
SpaceCodeOnboardingView(controller: this);
|
||||
}
|
||||
68
lib/pangea/login/pages/space_code_onboarding_view.dart
Normal file
68
lib/pangea/login/pages/space_code_onboarding_view.dart
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/login/pages/pangea_login_scaffold.dart';
|
||||
import 'package:fluffychat/pangea/login/pages/space_code_onboarding.dart';
|
||||
import 'package:fluffychat/pangea/login/widgets/full_width_button.dart';
|
||||
import 'package:fluffychat/pangea/user/utils/p_logout.dart';
|
||||
|
||||
class SpaceCodeOnboardingView extends StatelessWidget {
|
||||
final SpaceCodeOnboardingState controller;
|
||||
const SpaceCodeOnboardingView({
|
||||
super.key,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PangeaLoginScaffold(
|
||||
customAppBar: AppBar(
|
||||
leading: BackButton(
|
||||
onPressed: () => pLogoutAction(
|
||||
context,
|
||||
bypassWarning: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
showAppName: false,
|
||||
mainAssetUrl: controller.profile?.avatarUrl,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).welcomeUser(
|
||||
controller.profile?.displayName ??
|
||||
controller.client.userID?.localpart ??
|
||||
"",
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
L10n.of(context).joinSpaceOnboardingDesc,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
FullWidthTextField(
|
||||
hintText: L10n.of(context).enterCodeToJoin,
|
||||
controller: controller.codeController,
|
||||
onSubmitted: (_) => controller.submitCode,
|
||||
),
|
||||
FullWidthButton(
|
||||
title: L10n.of(context).join,
|
||||
onPressed: controller.submitCode,
|
||||
enabled: controller.codeController.text.isNotEmpty,
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
TextButton(
|
||||
child: Text(L10n.of(context).skipForNow),
|
||||
onPressed: () => context.go("/rooms"),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -207,7 +207,11 @@ class UserSettingsState extends State<UserSettingsPage> {
|
|||
throw TimeoutException(L10n.of(context).oopsSomethingWentWrong);
|
||||
},
|
||||
);
|
||||
context.go('/rooms');
|
||||
context.go(
|
||||
_pangeaController.classController.cachedClassCode == null
|
||||
? '/user_age/join_space'
|
||||
: '/rooms',
|
||||
);
|
||||
} catch (err) {
|
||||
if (err is MatrixException) {
|
||||
profileCreationError = err.errorMessage;
|
||||
|
|
|
|||
|
|
@ -23,22 +23,35 @@ import '../../common/controllers/base_controller.dart';
|
|||
|
||||
class ClassController extends BaseController {
|
||||
late PangeaController _pangeaController;
|
||||
|
||||
// Storage Initialization
|
||||
final GetStorage chatBox = GetStorage("chat_list_storage");
|
||||
final GetStorage linkBox = GetStorage("link_storage");
|
||||
static final GetStorage _classStorage = GetStorage('class_storage');
|
||||
|
||||
ClassController(PangeaController pangeaController) : super() {
|
||||
_pangeaController = pangeaController;
|
||||
}
|
||||
|
||||
Future<void> joinCachedSpaceCode(BuildContext context) async {
|
||||
final String? classCode = linkBox.read(
|
||||
Future<void> cacheSpaceCode(String code) async {
|
||||
if (code.isEmpty) return;
|
||||
await _classStorage.write(
|
||||
PLocalKey.cachedClassCodeToJoin,
|
||||
code,
|
||||
);
|
||||
}
|
||||
|
||||
final String? alias = _classStorage.read(PLocalKey.cachedAliasToJoin);
|
||||
String? justInputtedCode() {
|
||||
return _classStorage.read(PLocalKey.justInputtedCode);
|
||||
}
|
||||
|
||||
String? get cachedClassCode {
|
||||
return _classStorage.read(PLocalKey.cachedClassCodeToJoin);
|
||||
}
|
||||
|
||||
String? get cachedAlias {
|
||||
return _classStorage.read(PLocalKey.cachedAliasToJoin);
|
||||
}
|
||||
|
||||
Future<void> joinCachedSpaceCode(BuildContext context) async {
|
||||
final String? classCode = cachedClassCode;
|
||||
final String? alias = cachedAlias;
|
||||
|
||||
if (classCode != null) {
|
||||
await joinClasswithCode(
|
||||
|
|
@ -46,7 +59,7 @@ class ClassController extends BaseController {
|
|||
classCode,
|
||||
);
|
||||
|
||||
await linkBox.remove(
|
||||
await _classStorage.remove(
|
||||
PLocalKey.cachedClassCodeToJoin,
|
||||
);
|
||||
} else if (alias != null) {
|
||||
|
|
@ -141,7 +154,7 @@ class ClassController extends BaseController {
|
|||
}
|
||||
|
||||
final chosenClassId = foundClasses.first;
|
||||
await chatBox.write(
|
||||
await _classStorage.write(
|
||||
PLocalKey.justInputtedCode,
|
||||
classCode,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/constants/local.key.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
//if on home with classcode in url and not logged in, then save it soemhow and after llogin, join class automatically
|
||||
|
|
@ -32,10 +31,11 @@ class _JoinClassWithLinkState extends State<JoinClassWithLink> {
|
|||
);
|
||||
return;
|
||||
}
|
||||
await MatrixState.pangeaController.classController.linkBox.write(
|
||||
PLocalKey.cachedClassCodeToJoin,
|
||||
widget.classCode,
|
||||
);
|
||||
|
||||
if (widget.classCode != null) {
|
||||
await MatrixState.pangeaController.classController
|
||||
.cacheSpaceCode(widget.classCode!);
|
||||
}
|
||||
context.go("/home");
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue