Skip to content

Commit

Permalink
TW-1367: Handle go to the register public site automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
nqhhdev authored and hoangdat committed Mar 26, 2024
1 parent 9d04194 commit 1c97392
Show file tree
Hide file tree
Showing 15 changed files with 318 additions and 221 deletions.
6 changes: 0 additions & 6 deletions lib/config/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ abstract class AppConfig {

static String homeserver = 'https://example.com/';

static const String postLoginRedirectUrlPathParams =
'post_login_redirect_url';

static const String postRegisteredRedirectUrlPathParams =
'post_registered_redirect_url';

static String? platform;

static double toolbarHeight(BuildContext context) =>
Expand Down
70 changes: 65 additions & 5 deletions lib/pages/auto_homeserver_picker/auto_homeserver_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,18 @@ class AutoHomeserverPickerController extends State<AutoHomeserverPicker>
with ConnectPageMixin {
static const Duration autoHomeserverPickerTimeout = Duration(seconds: 30);

static const _saasPlatform = 'saas';

final showButtonRetryNotifier = ValueNotifier<bool>(false);

MatrixState get matrix => Matrix.of(context);

void _autoCheckHomeserver() async {
bool get _isSaasPlatform =>
AppConfig.platform != null &&
AppConfig.platform!.isNotEmpty &&
AppConfig.platform == _saasPlatform;

void _autoConnectHomeserver() async {
try {
matrix.loginHomeserverSummary = await matrix
.getLoginClient()
Expand Down Expand Up @@ -93,18 +100,71 @@ class AutoHomeserverPickerController extends State<AutoHomeserverPicker>

void retryCheckHomeserver() {
showButtonRetryNotifier.toggle();
_autoCheckHomeserver();
if (_isSaasPlatform) {
_autoConnectSaas();
} else {
_autoConnectHomeserver();
}
}

@override
void initState() {
void _autoConnectSaas() async {
matrix.loginHomeserverSummary =
await matrix.getLoginClient().checkHomeserver(
Uri.parse(AppConfig.twakeWorkplaceHomeserver),
);
Map<String, dynamic>? rawLoginTypes;
await Matrix.of(context)
.getLoginClient()
.request(
RequestType.GET,
'/client/r0/login',
)
.then((loginTypes) => rawLoginTypes = loginTypes)
.timeout(
autoHomeserverPickerTimeout,
onTimeout: () {
throw CheckHomeserverTimeoutException();
},
);
final identitiesProvider = identityProviders(rawLoginTypes: rawLoginTypes);
if (identitiesProvider?.length == 1) {
registerPublicPlatformAction(
context: context,
id: identitiesProvider!.single.id!,
saasRegistrationErrorCallback: (object) {
Logs().e(
"AutoHomeserverPickerController: _saasAutoRegistration: Error - $object",
);
},
saasRegistrationTimeoutCallback: () {
Logs().e(
"AutoHomeserverPickerController: _saasAutoRegistration: Timeout",
);
},
);
}
}

void _setupAutoHomeserverPicker() {
if (widget.loggedOut == null) {
_autoCheckHomeserver();
Logs().d(
"AutoHomeserverPickerController: _initializeAutoHomeserverPicker: PlatForm ${AppConfig.platform}",
);
if (_isSaasPlatform) {
_autoConnectSaas();
} else {
_autoConnectHomeserver();
}
} else {
if (widget.loggedOut == true) {
showButtonRetryNotifier.toggle();
}
}
}

@override
void initState() {
_setupAutoHomeserverPicker();
super.initState();
}

Expand Down
7 changes: 4 additions & 3 deletions lib/pages/chat_list/chat_list_body_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class ChatListBodyView extends StatelessWidget {
.paddingTextStartNewChatMessage,
child: Text(
L10n.of(context)!.startNewChatMessage,
style: Theme.of(context).textTheme.bodyMedium,
style:
Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
),
Expand Down Expand Up @@ -152,8 +153,8 @@ class ChatListBodyView extends StatelessWidget {
controller.filteredRoomsForPin.length,
),
isExpanded: isExpanded,
onTap:
controller.expandRoomsForPinNotifier.toggle,
onTap: controller
.expandRoomsForPinNotifier.toggle,
),
if (isExpanded) child!,
],
Expand Down
7 changes: 4 additions & 3 deletions lib/pages/chat_list/chat_list_header.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import 'package:fluffychat/pages/chat_list/chat_list.dart';
import 'package:fluffychat/pages/chat_list/chat_list_header_style.dart';
import 'package:fluffychat/widgets/twake_components/twake_header.dart';
import 'package:flutter/material.dart';

class ChatListHeader extends StatelessWidget {
final ChatListController controller;
final VoidCallback onClearSelection;
final VoidCallback? onOpenSearchPage;

const ChatListHeader({
Key? key,
required this.controller,
required this.onClearSelection,
this.onOpenSearchPage,
}) : super(key: key);

@override
Expand All @@ -18,7 +19,7 @@ class ChatListHeader extends StatelessWidget {
children: [
TwakeHeader(
controller: controller,
onClearSelection: onClearSelection,
onClearSelection: controller.onClickClearSelection,
),
Container(
height: ChatListHeaderStyle.searchBarContainerHeight,
Expand Down
7 changes: 1 addition & 6 deletions lib/pages/chat_list/chat_list_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,7 @@ class ChatListView extends StatelessWidget {
preferredSize: ChatListViewStyle.preferredSizeAppBar(context),
child: ChatListHeader(
onOpenSearchPage: onOpenSearchPage,
selectModeNotifier: controller.selectModeNotifier,
conversationSelectionNotifier:
controller.conversationSelectionNotifier,
currentProfileNotifier: controller.currentProfileNotifier,
onClickClearSelection: controller.onClickClearSelection,
onClickAvatar: controller.onClickAvatar,
controller: controller,
),
),
bottomNavigationBar: ValueListenableBuilder(
Expand Down
63 changes: 63 additions & 0 deletions lib/pages/connect/connect_page_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
import 'package:matrix/matrix.dart';
import 'package:universal_html/html.dart' as html;

typedef OnSAASRegistrationTimeoutCallback = void Function();
typedef OnSAASRegistrationErrorCallback = void Function(Object?);

mixin ConnectPageMixin {
static const saasRegistrationTimeout = Duration(seconds: 120);

static const windowNameValue = '_self';

bool supportsFlow({
Expand Down Expand Up @@ -53,6 +58,15 @@ mixin ConnectPageMixin {
return '$ssoRedirectUri?redirectUrl=$redirectUrlEncode';
}

String generatePublicPlatformAuthenticationUrl({
required BuildContext context,
required String id,
required String redirectUrl,
}) {
final redirectUrlEncode = Uri.encodeQueryComponent(redirectUrl);
return '${AppConfig.registrationUrl}?post_registered_redirect_url=$redirectUrlEncode';
}

String? _getLogoutUrl(
BuildContext context, {
required String redirectUrl,
Expand Down Expand Up @@ -150,6 +164,36 @@ mixin ConnectPageMixin {
}
}

Future<void> registerPublicPlatformAction({
required BuildContext context,
required String id,
OnSAASRegistrationTimeoutCallback? saasRegistrationTimeoutCallback,
OnSAASRegistrationErrorCallback? saasRegistrationErrorCallback,
}) async {
final redirectUrl = _generateRedirectUrl(
Matrix.of(context).client.homeserver.toString(),
);
final url = generatePublicPlatformAuthenticationUrl(
context: context,
id: id,
redirectUrl: redirectUrl,
);
final urlScheme = _getRedirectUrlScheme(redirectUrl);
final uri = await FlutterWebAuth2.authenticate(
url: url,
callbackUrlScheme: urlScheme,
options: const FlutterWebAuth2Options(
intentFlags: ephemeralIntentFlags,
windowName: windowNameValue,
),
);
Logs().d("ConnectPageMixin:_redirectRegistrationUrl: URI - $uri");
handleTokenFromRegistrationSite(
matrix: Matrix.of(context),
uri: uri,
);
}

String _generatePostLogoutRedirectUrl() {
if (kIsWeb) {
if (AppConfig.issueId != null && AppConfig.issueId!.isNotEmpty) {
Expand Down Expand Up @@ -190,4 +234,23 @@ mixin ConnectPageMixin {
}
return list;
}

void handleTokenFromRegistrationSite({
required MatrixState matrix,
required String uri,
}) async {
final token = Uri.parse(uri).queryParameters['loginToken'];
Logs().d(
"ConnectPageMixin: handleTokenFromRegistrationSite: token: $token",
);
if (token == null || token.isEmpty == true) return;
matrix.loginType = LoginType.mLoginToken;
await TwakeDialog.showFutureLoadingDialogFullScreen(
future: () => matrix.getLoginClient().login(
LoginType.mLoginToken,
token: token,
initialDeviceDisplayName: PlatformInfos.clientName,
),
);
}
}
4 changes: 0 additions & 4 deletions lib/pages/twake_welcome/twake_id_view_style.dart

This file was deleted.

27 changes: 7 additions & 20 deletions lib/pages/twake_welcome/twake_welcome.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'package:fluffychat/config/app_config.dart';
import 'package:equatable/equatable.dart';
import 'package:fluffychat/pages/connect/connect_page_mixin.dart';
import 'package:fluffychat/pages/twake_welcome/twake_welcome_view.dart';
import 'package:fluffychat/utils/dialog/twake_dialog.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
Expand All @@ -29,13 +28,14 @@ class TwakeWelcomeArg extends Equatable {

class TwakeWelcome extends StatefulWidget {
final TwakeWelcomeArg? arg;

const TwakeWelcome({super.key, this.arg});

@override
State<TwakeWelcome> createState() => TwakeWelcomeController();
}

class TwakeWelcomeController extends State<TwakeWelcome> {
class TwakeWelcomeController extends State<TwakeWelcome> with ConnectPageMixin {
void goToHomeserverPicker() {
if (widget.arg?.isAddAnotherAccount == true) {
context.push('/rooms/addhomeserver');
Expand Down Expand Up @@ -63,20 +63,6 @@ class TwakeWelcomeController extends State<TwakeWelcome> {
_redirectRegistrationUrl(loginUrl);
}

void _handleTokenFromRegistrationSite(String uri) async {
final token = Uri.parse(uri).queryParameters['loginToken'];
Logs().d("TwakeIdController: _handleLoginToken: token: $token");
if (token?.isEmpty ?? false) return;
Matrix.of(context).loginType = LoginType.mLoginToken;
await TwakeDialog.showFutureLoadingDialogFullScreen(
future: () => Matrix.of(context).getLoginClient().login(
LoginType.mLoginToken,
token: token,
initialDeviceDisplayName: PlatformInfos.clientName,
),
);
}

void _redirectRegistrationUrl(String url) async {
matrix.loginHomeserverSummary =
await matrix.getLoginClient().checkHomeserver(
Expand All @@ -90,12 +76,13 @@ class TwakeWelcomeController extends State<TwakeWelcome> {
),
);
Logs().d("TwakeIdController:_redirectRegistrationUrl: URI - $uri");
_handleTokenFromRegistrationSite(uri);
handleTokenFromRegistrationSite(matrix: matrix, uri: uri);
}

void onClickCreateTwakeId() {
Logs()
.d("TwakeIdController::onClickCreateTwakeId: Signup Url - $signupUrl");
Logs().d(
"TwakeIdController::onClickCreateTwakeId: Signup Url - $signupUrl",
);
_redirectRegistrationUrl(signupUrl);
}

Expand Down
7 changes: 4 additions & 3 deletions lib/pages/twake_welcome/twake_welcome_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:fluffychat/pages/twake_welcome/twake_id_view_style.dart';
import 'package:fluffychat/pages/twake_welcome/twake_welcome.dart';
import 'package:fluffychat/pages/twake_welcome/twake_welcome_view_style.dart';
import 'package:fluffychat/resource/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
Expand All @@ -24,10 +24,11 @@ class TwakeWelcomeView extends StatelessWidget {
description: L10n.of(context)!.descriptionTwakeId,
onUseCompanyServerOnTap: controller.goToHomeserverPicker,
onSignInOnTap: controller.onClickSignIn,
onCreateTwakeIdOnTap: controller.onClickCreateTwakeId,
logo: SvgPicture.asset(
ImagePaths.logoTwakeWelcome,
width: TwakeIdViewStyle.logoWidth,
height: TwakeIdViewStyle.logoHeight,
width: TwakeWelcomeViewStyle.logoWidth,
height: TwakeWelcomeViewStyle.logoHeight,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class AppAdaptiveScaffoldBodyController extends State<AppAdaptiveScaffoldBody> {
'AppAdaptiveScaffoldBodyController::_onLogoutMultipleAccountSuccess():newWidget - ${widget.args}',
);
if (oldWidget.args != widget.args && widget.args is LogoutBodyArgs) {
activeNavigationBar.value = AdaptiveDestinationEnum.rooms;
activeNavigationBarNotifier.value = AdaptiveDestinationEnum.rooms;
pageController.jumpToPage(AdaptiveDestinationEnum.rooms.index);
}
}
Expand Down
Loading

0 comments on commit 1c97392

Please sign in to comment.