Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PE-7123: Auto Manifest Update Default to Last Name #1919

Merged
merged 7 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions lib/arns/domain/arns_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ abstract class ARNSRepository {
Future<void> saveAllFilesWithAssignedNames();
Future<List<ArnsRecord>> getActiveARNSRecordsForFile(String fileId);
Future<void> waitForARNSRecordsToUpdate();
Future<sdk.ARNSUndername> getUndernameByDomainAndName(
String domain, String name);
Future<PrimaryNameDetails> getPrimaryName(String address,
{bool update = false});

Expand Down Expand Up @@ -375,6 +377,26 @@ class _ARNSRepository implements ARNSRepository {
await _getARNSUndernamesCompleter!.future;
}

@override
Future<sdk.ARNSUndername> getUndernameByDomainAndName(
String domain, String name) async {
if (_cachedUndernames.isEmpty) {
await waitForARNSRecordsToUpdate();
}

if (_cachedUndernames[domain] == null) {
throw Exception('Domain not cached');
}

final undername = _cachedUndernames[domain]![name];

if (undername == null) {
throw Exception('Undername not cached');
}

return undername;
}

@override
Future<PrimaryNameDetails> getPrimaryName(String address,
{bool update = false}) async {
Expand Down
34 changes: 34 additions & 0 deletions lib/core/upload/view/blocs/upload_manifest_options_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'package:ardrive/arns/domain/arns_repository.dart';
import 'package:ardrive/arns/utils/parse_assigned_names_from_string.dart';
import 'package:ardrive/authentication/ardrive_auth.dart';
import 'package:ardrive/models/models.dart';
import 'package:ardrive/utils/logger.dart';
import 'package:ario_sdk/ario_sdk.dart';
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

Expand Down Expand Up @@ -57,6 +60,37 @@ class UploadManifestOptionsBloc
on<LoadAnts>((event, emit) async {
final walletAddress = await arDriveAuth.getWalletAddress();
_ants = await arnsRepository.getAntRecordsForWallet(walletAddress!);

for (var file in manifestFiles) {
if (file.manifest.assignedNames != null &&
file.manifest.assignedNames!.isNotEmpty) {
final assignedNames =
parseAssignedNamesFromString(file.manifest.assignedNames!);
final assignedName = assignedNames!.first;

final (domain, undername) = splitArNSRecordName(assignedName);

/// For now, we only support adding one name
final antRecord = _ants!.firstWhereOrNull((e) => e.domain == domain);

if (antRecord != null) {
try {
final existingUndername = await arnsRepository
.getUndernameByDomainAndName(domain, undername ?? '@');

add(SelectManifest(manifest: file.manifest));
add(LinkManifestToUndername(
manifest: file.manifest,
antRecord: antRecord,
undername: existingUndername,
));
} catch (e) {
logger.e('Error getting undername.', e);
}
}
}
}

emit(_createReadyState());
});

Expand Down
123 changes: 62 additions & 61 deletions lib/core/upload/view/manifest_options/manifest_options.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:ardrive/components/components.dart';
import 'package:ardrive/core/upload/view/blocs/upload_manifest_options_bloc.dart';
import 'package:ardrive/utils/logger.dart';
import 'package:ardrive_ui/ardrive_ui.dart';
import 'package:ario_sdk/ario_sdk.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -31,6 +32,8 @@ class ManifestOptions extends StatelessWidget {
final file = manifestFiles.elementAt(index).manifest;
final isSelected = selectedManifestIds.contains(file.id);

logger.d('Is selected: $isSelected');

return _ManifestOptionTile(
manifestSelection: manifestFiles.elementAt(index),
isSelected: isSelected,
Expand Down Expand Up @@ -91,72 +94,68 @@ class __ManifestOptionTileState extends State<_ManifestOptionTile> {
widget.manifestSelection.undername != null);
final hasSelectedAnt = widget.manifestSelection.antRecord != null;

return AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
color: colorTokens.containerL2,
borderRadius: BorderRadius.circular(5),
),
curve: Curves.easeInOut,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
height: isExpanded
? 168
: showingName
? 70
: 50,
child: GestureDetector(
onTap: () {},
return SingleChildScrollView(
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
color: colorTokens.containerL2,
borderRadius: BorderRadius.circular(5),
),
curve: Curves.easeInOut,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
height: isExpanded
? 168
: showingName
? 70
: 50,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
ArDriveCheckBox(
key: ValueKey(widget.isSelected),
checked: widget.isSelected,
onChange: (value) {
if (value) {
context
.read<UploadManifestOptionsBloc>()
.add(SelectManifest(manifest: file));
} else {
context
.read<UploadManifestOptionsBloc>()
.add(DeselectManifest(manifest: file));
}
},
),
const SizedBox(width: 16),
Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
flex: 2,
child: Row(
children: [
ArDriveIcons.manifest(
size: 16,
color: file.isHidden ? hiddenColor : null),
const SizedBox(width: 8),
Text(
file.name,
style: typography.paragraphNormal(
color: file.isHidden ? hiddenColor : null,
),
),
if (file.isHidden) ...[
const SizedBox(width: 8),
Text('(hidden)',
style: typography.paragraphNormal(
color: hiddenColor,
))
]
],
),
),
Flexible(
flex: 1,
child: ArDriveCheckBox(
checked: widget.isSelected,
onChange: (value) {
if (value) {
context
.read<UploadManifestOptionsBloc>()
.add(SelectManifest(manifest: file));
} else {
context
.read<UploadManifestOptionsBloc>()
.add(DeselectManifest(manifest: file));
}
},
ArDriveIcons.manifest(
size: 16,
color: file.isHidden ? hiddenColor : null),
const SizedBox(width: 8),
Expanded(
child: Text(
file.name,
style: typography.paragraphNormal(
color: file.isHidden ? hiddenColor : null,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
if (file.isHidden) ...[
const SizedBox(width: 8),
Text('(hidden)',
style: typography.paragraphNormal(
color: hiddenColor,
))
]
],
),
),
Expand All @@ -168,16 +167,16 @@ class __ManifestOptionTileState extends State<_ManifestOptionTile> {
text: !state.arnsNamesLoaded
? 'Loading Names...'
: hasSelectedAnt
? 'Change ArNS'
: 'Add ArNS',
? 'Change ArNS Name'
: 'Add ArNS Name',
typography: typography,
isDisabled: isExpanded ||
!widget.isSelected ||
!state.arnsNamesLoaded ||
(state.arnsNamesLoaded && state.ants!.isEmpty),
fontStyle: typography.paragraphSmall(),
variant: ButtonVariant.primary,
maxWidth: state.arnsNamesLoaded ? 100 : 120,
maxWidth: state.arnsNamesLoaded ? 140 : 160,
maxHeight: 30,
onPressed: () {
context
Expand All @@ -186,7 +185,6 @@ class __ManifestOptionTileState extends State<_ManifestOptionTile> {
},
),
)
// TODO: Add back when we have the right UI for it
],
),
if (showingName) ...[
Expand All @@ -197,7 +195,7 @@ class __ManifestOptionTileState extends State<_ManifestOptionTile> {
size: 16,
color: colorTokens.textHigh,
),
const SizedBox(width: 8),
const SizedBox(width: 18),
Flexible(
child: Text(
getLiteralArNSName(widget.manifestSelection.antRecord!,
Expand All @@ -216,8 +214,11 @@ class __ManifestOptionTileState extends State<_ManifestOptionTile> {
const SizedBox(height: 8),
Expanded(
flex: 1,
child: AntSelector(
manifestSelection: widget.manifestSelection,
child: Padding(
padding: const EdgeInsets.only(left: 34),
child: AntSelector(
manifestSelection: widget.manifestSelection,
),
),
),
],
Expand Down
10 changes: 10 additions & 0 deletions packages/ario_sdk/lib/src/utils/get_literal_arns_record_name.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ String getLiteralARNSRecordName(ARNSUndername undername) {
return '${undername.name}_${undername.domain}';
}

/// Splits an ARNS record name into its literal name and domain.
/// If the name is not in the format [name]_[domain], it returns [name] and null.
(String, String?) splitArNSRecordName(String name) {
if (name.contains('_')) {
return (name.split('_').first, name.split('_').last);
}

return (name, null);
}
//
Loading