TF-3985 Navigate Paywall url when click Increase your space button

This commit is contained in:
dab246
2025-09-09 15:33:50 +07:00
committed by Dat H. Pham
parent c3ee166c00
commit f373cd3d37
22 changed files with 463 additions and 5 deletions
@@ -0,0 +1,5 @@
import 'package:tmail_ui_user/features/paywall/domain/model/paywall_url_pattern.dart';
abstract class PaywallDatasource {
Future<PaywallUrlPattern> getPaywallUrl(String baseUrl);
}
@@ -0,0 +1,18 @@
import 'package:tmail_ui_user/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart';
import 'package:tmail_ui_user/features/paywall/data/datasource/paywall_datasource.dart';
import 'package:tmail_ui_user/features/paywall/domain/model/paywall_url_pattern.dart';
import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart';
class PaywallDatasourceImpl extends PaywallDatasource {
final LinagoraEcosystemApi _linagoraEcosystemApi;
final ExceptionThrower _exceptionThrower;
PaywallDatasourceImpl(this._linagoraEcosystemApi, this._exceptionThrower);
@override
Future<PaywallUrlPattern> getPaywallUrl(String baseUrl) {
return Future.sync(() async {
return await _linagoraEcosystemApi.getPaywallUrl(baseUrl);
}).catchError(_exceptionThrower.throwException);
}
}
@@ -0,0 +1,14 @@
import 'package:tmail_ui_user/features/paywall/data/datasource/paywall_datasource.dart';
import 'package:tmail_ui_user/features/paywall/domain/model/paywall_url_pattern.dart';
import 'package:tmail_ui_user/features/paywall/domain/repository/paywall_repository.dart';
class PaywallRepositoryImpl extends PaywallRepository {
final PaywallDatasource _paywallDatasource;
PaywallRepositoryImpl(this._paywallDatasource);
@override
Future<PaywallUrlPattern> getPaywallUrl(String baseUrl) {
return _paywallDatasource.getPaywallUrl(baseUrl);
}
}
@@ -0,0 +1,40 @@
import 'package:core/utils/mail/domain.dart';
import 'package:core/utils/mail/mail_address.dart';
import 'package:equatable/equatable.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/paywall/presentation/paywall_utils.dart';
class PaywallUrlPattern with EquatableMixin {
final String pattern;
PaywallUrlPattern(this.pattern);
String getQualifiedUrl({required String ownerEmail, String? domainName}) {
final mailAddress = _getMailAddress(ownerEmail: ownerEmail);
return PaywallUtils.buildPaywallUrlFromTemplate(
template: pattern,
localPart: mailAddress?.localPart,
domainName: mailAddress?.domain.domainName,
);
}
MailAddress? _getMailAddress({required String ownerEmail}) {
try {
return MailAddress.validateAddress(ownerEmail);
} catch (e) {
if (GetUtils.isEmail(ownerEmail)) {
final listPart = ownerEmail.split('@');
if (listPart.length == 2) {
return MailAddress(
localPart: listPart.first,
domain: Domain.of((listPart.last)),
);
}
}
return null;
}
}
@override
List<Object> get props => [pattern];
}
@@ -0,0 +1,5 @@
import 'package:tmail_ui_user/features/paywall/domain/model/paywall_url_pattern.dart';
abstract class PaywallRepository {
Future<PaywallUrlPattern> getPaywallUrl(String baseUrl);
}
@@ -0,0 +1,18 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/paywall/domain/model/paywall_url_pattern.dart';
class GettingPaywallUrl extends LoadingState {}
class GetPaywallUrlSuccess extends UIState {
final PaywallUrlPattern paywallUrlPattern;
GetPaywallUrlSuccess(this.paywallUrlPattern);
@override
List<Object> get props => [paywallUrlPattern];
}
class GetPaywallUrlFailure extends FeatureFailure {
GetPaywallUrlFailure(dynamic exception) : super(exception: exception);
}
@@ -0,0 +1,21 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:tmail_ui_user/features/paywall/domain/repository/paywall_repository.dart';
import 'package:tmail_ui_user/features/paywall/domain/state/get_paywall_url_state.dart';
class GetPaywallUrlInteractor {
final PaywallRepository _paywallRepository;
GetPaywallUrlInteractor(this._paywallRepository);
Stream<Either<Failure, Success>> execute(String baseUrl) async* {
try {
yield Right(GettingPaywallUrl());
final paywallUrl = await _paywallRepository.getPaywallUrl(baseUrl);
yield Right(GetPaywallUrlSuccess(paywallUrl));
} catch (e) {
yield Left(GetPaywallUrlFailure(e));
}
}
}
@@ -0,0 +1,41 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/interactors_bindings.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/data/network/linagora_ecosystem_api.dart';
import 'package:tmail_ui_user/features/paywall/data/datasource/paywall_datasource.dart';
import 'package:tmail_ui_user/features/paywall/data/datasource_impl/paywall_datasource_impl.dart';
import 'package:tmail_ui_user/features/paywall/data/repository/paywall_repository_impl.dart';
import 'package:tmail_ui_user/features/paywall/domain/repository/paywall_repository.dart';
import 'package:tmail_ui_user/features/paywall/domain/usecases/get_paywall_url_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
class PaywallBindings extends InteractorsBindings {
@override
void bindingsDataSource() {
Get.lazyPut<PaywallDatasource>(() => Get.find<PaywallDatasourceImpl>());
}
@override
void bindingsDataSourceImpl() {
Get.lazyPut(
() => PaywallDatasourceImpl(
Get.find<LinagoraEcosystemApi>(),
Get.find<RemoteExceptionThrower>(),
),
);
}
@override
void bindingsInteractor() {
Get.lazyPut(() => GetPaywallUrlInteractor(Get.find<PaywallRepository>()));
}
@override
void bindingsRepository() {
Get.lazyPut<PaywallRepository>(() => Get.find<PaywallRepositoryImpl>());
}
@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => PaywallRepositoryImpl(Get.find<PaywallDatasource>()));
}
}
@@ -0,0 +1,29 @@
class PaywallUtils {
const PaywallUtils._();
/// Builds a paywall URL from a template.
///
/// - Supports both raw placeholders (`{localPart}`, `{domainName}`)
/// and URL-encoded placeholders (`%7BlocalPart%7D`, `%7BdomainName%7D`).
/// - If [localPart] or [domainName] is not provided, the placeholder
/// is removed.
static String buildPaywallUrlFromTemplate({
required String template,
String? localPart,
String? domainName,
}) {
final replacements = {
'{localPart}': localPart ?? '',
'{domainName}': domainName ?? '',
Uri.encodeComponent('{localPart}'): localPart ?? '',
Uri.encodeComponent('{domainName}'): domainName ?? '',
};
var result = template;
replacements.forEach((placeholder, value) {
result = result.replaceAll(placeholder, value);
});
return result;
}
}