Skip to content

Commit

Permalink
[deep link] Make path a class to add isExclude and queryParam (flutte…
Browse files Browse the repository at this point in the history
…r#8307)

* add isExcluded

add isExcluded

1

add aasa path

1

add key

Add tests

* test

* resolve comments

* resolve comments

* resolve comments

* resolve comments

* lint
  • Loading branch information
hannah-hyj authored Sep 13, 2024
1 parent 2b3bed9 commit 6d6bb3b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ class DeepLinksController extends DisposableController
if (path == null) {
continue;
}
final previousRecord = linkDatasByPath[path];
final previousRecord = linkDatasByPath[path.path];

linkDatasByPath[path] = LinkData(
linkDatasByPath[path.path] = LinkData(
domain: linkData.domain,
path: linkData.path,
scheme: linkData.scheme.union(previousRecord?.scheme ?? {}),
Expand Down Expand Up @@ -207,7 +207,8 @@ class DeepLinksController extends DisposableController
},
associatedPath: [
...previousRecord?.associatedPath ?? [],
if (linkData.path != null) linkData.path!,
if (linkData.path != null && !linkData.path!.isExcluded)
linkData.path!.path,
],
domainErrors: linkData.domainErrors,
hasAndroidAssetLinksFile: linkData.hasAndroidAssetLinksFile,
Expand Down Expand Up @@ -401,7 +402,7 @@ class DeepLinksController extends DisposableController
if (domainPathToLinkData[domainAndPath] == null) {
domainPathToLinkData[domainAndPath] = LinkData(
domain: appLink.host,
path: appLink.path,
path: Path(path: appLink.path),
pathErrors:
_getPathErrorsFromIntentFilterChecks(appLink.intentFilterChecks),
os: {PlatformOS.android},
Expand Down Expand Up @@ -510,7 +511,7 @@ class DeepLinksController extends DisposableController
Map<String, List<DomainError>> iosDomainErrors =
<String, List<DomainError>>{};

late final Map<String, List<String>> iosDomainPaths;
late final Map<String, List<Path>> iosDomainPaths;
try {
final androidResult = await deepLinksService.validateAndroidDomain(
domains: domains,
Expand Down Expand Up @@ -552,7 +553,7 @@ class DeepLinksController extends DisposableController
false);

if (linkdata.os.contains(PlatformOS.ios)) {
final iosPaths = iosDomainPaths[linkdata.domain] ?? <String>[];
final iosPaths = iosDomainPaths[linkdata.domain] ?? <Path>[];

// If no path is provided, we will still show the domain just with domain errors.
if (iosPaths.isEmpty) {
Expand Down Expand Up @@ -593,7 +594,7 @@ class DeepLinksController extends DisposableController

Future<List<LinkData>> _validatePath(List<LinkData> linkdatas) async {
for (final linkData in linkdatas) {
final path = linkData.path;
final path = linkData.path?.path;
if (path == null) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,26 @@ class ValidatedLinkDatas {
final List<LinkData> byPath;
}

/// Represents a path in a deep link.
class Path {
Path({
required this.path,
this.queryParams = const {},
this.isExcluded = false,
});

final String path;

// TODO(hangyujin): display queryParams in path table.
final Map<String, String> queryParams;

/// A Boolean value that indicates whether to stop pattern matching and prevent the universal
/// link from opening if the URL matches the associated pattern.
///
/// The default is false.
final bool isExcluded;
}

/// Contains all data relevant to a deep link.
class LinkData with SearchableDataMixin {
LinkData({
Expand All @@ -259,7 +279,7 @@ class LinkData with SearchableDataMixin {
this.hasIosAasaFile = true,
});

final String? path;
final Path? path;
final String? domain;
final Set<PlatformOS> os;
final Set<String> scheme;
Expand All @@ -274,17 +294,17 @@ class LinkData with SearchableDataMixin {
@override
bool matchesSearchToken(RegExp regExpSearch) {
return (domain?.caseInsensitiveContains(regExpSearch) ?? false) ||
(path?.caseInsensitiveContains(regExpSearch) ?? false);
(path?.path.caseInsensitiveContains(regExpSearch) ?? false);
}

@override
String toString() => 'LinkData($domain $path $os)';

String get safePath => path ?? '';
String get safePath => path?.path ?? '';
String get safeDomain => domain ?? '';

LinkData copyWith({
String? path,
Path? path,
List<DomainError>? domainErrors,
bool? hasAndroidAssetLinksFile,
bool? hasIosAasaFile,
Expand Down Expand Up @@ -501,7 +521,8 @@ class PathColumn extends ColumnData<LinkData>
return _ErrorAwareText(
isError: dataObject.pathErrors.isNotEmpty,
controller: controller,
text: dataObject.safePath,
text:
'${(dataObject.path?.isExcluded ?? false) ? 'NOT ' : ''}${getValue(dataObject)}',
link: dataObject,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ const _iosValidationResultsKey = 'validationResults';
const _aasaAppPathsKey = 'aasaAppPaths';
const _aasaPathsKey = 'aasaPaths';
const _pathKey = 'path';
const _isExcludedKey = 'isExcluded';
const _queryParamsKey = 'queryParams';
const _keyKey = 'key';
const _valueKey = 'value';

const iosCheckNameToDomainError = <String, DomainError>{
'EXISTENCE': IosDomainError.existence,
Expand All @@ -75,7 +79,7 @@ class ValidateIosDomainResult {
ValidateIosDomainResult(this.errorCode, this.domainErrors, this.paths);
final String errorCode;
final Map<String, List<DomainError>> domainErrors;
final Map<String, List<String>> paths;
final Map<String, List<Path>> paths;
}

class GenerateAssetLinksResult {
Expand Down Expand Up @@ -158,7 +162,7 @@ class DeepLinksService {
required List<String> domains,
}) async {
final domainErrors = <String, List<DomainError>>{};
final paths = <String, List<String>>{};
final paths = <String, List<Path>>{};
// TODO(hangyujin): Add error code to the result.
const errorCode = '';

Expand Down Expand Up @@ -205,9 +209,20 @@ class DeepLinksService {
?.cast<Map<String, Object?>>();
if (aasaPaths != null) {
for (final aasaPath in aasaPaths) {
paths
.putIfAbsent(domainName, () => <String>[])
.add(aasaPath[_pathKey] as String);
final rawQueryParams = (aasaPath[_queryParamsKey] as List?)
?.cast<Map<String, Object?>>();
final queryParams = <String, String>{
for (final item in rawQueryParams ?? <Map>[])
item[_keyKey] as String: item[_valueKey] as String,
};
paths.putIfAbsent(domainName, () => <Path>[]).add(
Path(
path: aasaPath[_pathKey] as String,
queryParams: queryParams,
isExcluded:
aasaPath[_isExcludedKey] as bool? ?? false,
),
);
}
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ void main() {
expect(find.text('/path2'), findsOneWidget);
expect(find.text('/path3'), findsOneWidget);
expect(find.text('/ios-path1'), findsOneWidget);
expect(find.text('/ios-path2'), findsOneWidget);
expect(find.text('NOT /ios-path2'), findsOneWidget);

// Only show links with path error.
deepLinksController.updateDisplayOptions(
Expand All @@ -587,7 +587,7 @@ void main() {
expect(find.text('/path2'), findsOneWidget);
expect(find.text('/path3'), findsNothing);
expect(find.text('/ios-path1'), findsNothing);
expect(find.text('/ios-path2'), findsNothing);
expect(find.text('NOT /ios-path2'), findsNothing);

// Only show links with no issue.
deepLinksController.updateDisplayOptions(
Expand All @@ -603,7 +603,7 @@ void main() {
expect(find.text('/path2'), findsNothing);
expect(find.text('/path3'), findsOneWidget);
expect(find.text('/ios-path1'), findsOneWidget);
expect(find.text('/ios-path2'), findsOneWidget);
expect(find.text('NOT /ios-path2'), findsOneWidget);
},
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ const iosValidationResponseWithNoError = '''
},
{
"path": "/ios-path2",
"isExcluded": true,
"queryParams": [
{
"key": "dplnk",
Expand Down Expand Up @@ -230,6 +231,7 @@ const iosValidationResponseWithError = '''
},
{
"path": "/ios-path2",
"isExcluded": true,
"queryParams": [
{
"key": "dplnk",
Expand Down

0 comments on commit 6d6bb3b

Please sign in to comment.