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-7214: feat(primary name) #1927

Merged
merged 17 commits into from
Dec 3, 2024
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
feat(primary name)
- refresh primary name when sync
- add refresh name event on bloc
- update ario sdk readme repo
thiagocarvalhodev committed Dec 3, 2024
commit 36a7ed16212b2130e761411ee1a00aaeb283715a
11 changes: 9 additions & 2 deletions lib/arns/domain/arns_repository.dart
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ abstract class ARNSRepository {
Future<void> saveAllFilesWithAssignedNames();
Future<List<ArnsRecord>> getActiveARNSRecordsForFile(String fileId);
Future<void> waitForARNSRecordsToUpdate();
Future<String> getPrimaryName(String address);
Future<String> getPrimaryName(String address, {bool update = false});

factory ARNSRepository({
required ArioSDK sdk,
@@ -88,6 +88,7 @@ class _ARNSRepository implements ARNSRepository {
}

final Map<String, Map<String, ARNSUndername>> _cachedUndernames = {};
String? _cachedPrimaryName;

@override
Future<void> setUndernamesToFile({
@@ -373,13 +374,19 @@ class _ARNSRepository implements ARNSRepository {
}

@override
Future<String> getPrimaryName(String address) async {
Future<String> getPrimaryName(String address, {bool update = false}) async {
logger.d('Getting primary name for address: $address');

if (!update && _cachedPrimaryName != null) {
return _cachedPrimaryName!;
}

final primaryName = await _sdk.getPrimaryName(address);

logger.d('Primary name: $primaryName');

_cachedPrimaryName = primaryName;

return primaryName;
}
}
3 changes: 3 additions & 0 deletions lib/components/app_top_bar.dart
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import 'package:ardrive/pages/drive_detail/components/hover_widget.dart';
import 'package:ardrive/search/search_modal.dart';
import 'package:ardrive/search/search_text_field.dart';
import 'package:ardrive/sync/domain/cubit/sync_cubit.dart';
import 'package:ardrive/user/name/presentation/bloc/profile_name_bloc.dart';
import 'package:ardrive/utils/app_localizations_wrapper.dart';
import 'package:ardrive/utils/plausible_event_tracker/plausible_custom_event_properties.dart';
import 'package:ardrive/utils/plausible_event_tracker/plausible_event_tracker.dart';
@@ -124,6 +125,7 @@ class SyncButton extends StatelessWidget {
ArDriveDropdownItem(
onClick: () {
context.read<SyncCubit>().startSync(deepSync: false);
context.read<ProfileNameBloc>().add(RefreshProfileName());
PlausibleEventTracker.trackResync(type: ResyncType.resync);
},
content: ArDriveDropdownItemTile(
@@ -136,6 +138,7 @@ class SyncButton extends StatelessWidget {
ArDriveDropdownItem(
onClick: () {
context.read<SyncCubit>().startSync(deepSync: true);
context.read<ProfileNameBloc>().add(RefreshProfileName());
PlausibleEventTracker.trackResync(type: ResyncType.deepResync);
},
content: ArDriveDropdownItemTile(
15 changes: 14 additions & 1 deletion lib/components/profile_card.dart
Original file line number Diff line number Diff line change
@@ -554,12 +554,25 @@ class _ProfileCardState extends State<ProfileCard> {
final primaryName = state is ProfileNameLoaded
? state.primaryName
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this won't truncate primary names to max 20 and add ... ? Or is it handled elsewhere?

: truncateString(walletAddress, offsetStart: 2, offsetEnd: 2);
double maxWidth = 100;

if (state is ProfileNameLoaded) {
maxWidth = primaryName.length.toDouble() * 10;

if (maxWidth < 100) {
maxWidth = 100;
}

if (maxWidth > 180) {
maxWidth = 180;
}
}

return ArDriveButtonNew(
text: primaryName,
typography: typography,
variant: ButtonVariant.outline,
maxWidth: 100,
maxWidth: maxWidth,
onPressed: () {
setState(() {
_showProfileCard = !_showProfileCard;
2 changes: 0 additions & 2 deletions lib/pages/app_router_delegate.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:ardrive/app_shell.dart';
import 'package:ardrive/arns/domain/arns_repository.dart';
import 'package:ardrive/authentication/ardrive_auth.dart';
import 'package:ardrive/authentication/login/views/login_page.dart';
import 'package:ardrive/blocs/activity/activity_cubit.dart';
@@ -300,7 +299,6 @@ class AppRouterDelegate extends RouterDelegate<AppRoutePath>
promptToSnapshotBloc:
context.read<PromptToSnapshotBloc>(),
tabVisibility: TabVisibilitySingleton(),
arnsRepository: context.read<ARNSRepository>(),
),
),
BlocProvider(
9 changes: 0 additions & 9 deletions lib/sync/domain/cubit/sync_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:math';

import 'package:ardrive/arns/domain/arns_repository.dart';
import 'package:ardrive/blocs/activity/activity_cubit.dart';
import 'package:ardrive/blocs/blocs.dart';
import 'package:ardrive/blocs/prompt_to_snapshot/prompt_to_snapshot_bloc.dart';
@@ -35,7 +34,6 @@ class SyncCubit extends Cubit<SyncState> {
final TabVisibilitySingleton _tabVisibility;
final ConfigService _configService;
final SyncRepository _syncRepository;
final ARNSRepository _arnsRepository;

StreamSubscription? _restartOnFocusStreamSubscription;
StreamSubscription? _restartArConnectOnFocusStreamSubscription;
@@ -55,14 +53,12 @@ class SyncCubit extends Cubit<SyncState> {
required ConfigService configService,
required ActivityTracker activityTracker,
required SyncRepository syncRepository,
required ARNSRepository arnsRepository,
}) : _profileCubit = profileCubit,
_activityCubit = activityCubit,
_promptToSnapshotBloc = promptToSnapshotBloc,
_configService = configService,
_tabVisibility = tabVisibility,
_syncRepository = syncRepository,
_arnsRepository = arnsRepository,
super(SyncIdle()) {
// Sync the user's drives on start and periodically.
createSyncStream();
@@ -252,11 +248,6 @@ class SyncCubit extends Cubit<SyncState> {

if (profile is ProfileLoggedIn) {
_profileCubit.refreshBalance();
_arnsRepository.getPrimaryName(profile.user.walletAddress).then((name) {
logger.d('Primary name: $name');
}).catchError((e) {
logger.e('Error getting primary name. It won\'t affect the sync.', e);
});
}

logger.i('Transaction statuses updated');
74 changes: 52 additions & 22 deletions lib/user/name/presentation/bloc/profile_name_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:ardrive/arns/domain/arns_repository.dart';
import 'package:ardrive/authentication/ardrive_auth.dart';
import 'package:ardrive/utils/logger.dart';
import 'package:ario_sdk/ario_sdk.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

@@ -13,33 +14,62 @@ class ProfileNameBloc extends Bloc<ProfileNameEvent, ProfileNameState> {

ProfileNameBloc(this._arnsRepository, this._auth)
: super(ProfileNameInitial(_auth.currentUser.walletAddress)) {
on<ProfileNameEvent>((event, emit) async {
try {
logger.d(
'Loading primary name for address: ${_auth.currentUser.walletAddress}');

// loads primary name for the wallet
emit(ProfileNameLoading(_auth.currentUser.walletAddress));
on<LoadProfileName>((event, emit) async {
await _loadProfileName(
walletAddress: _auth.currentUser.walletAddress,
refresh: false,
emit: emit,
);
});
on<RefreshProfileName>((event, emit) async {
await _loadProfileName(
walletAddress: _auth.currentUser.walletAddress,
refresh: true,
emit: emit,
);
});
}

final primaryName = await _arnsRepository.getPrimaryName(
_auth.currentUser.walletAddress,
);
Future<void> _loadProfileName({
required String walletAddress,
required bool refresh,
required Emitter<ProfileNameState> emit,
}) async {
try {
/// if we are not refreshing, we emit a loading state
if (!refresh) {
emit(ProfileNameLoading(walletAddress));
}

logger.d('Primary Name Loaded: $primaryName');
final primaryName =
await _arnsRepository.getPrimaryName(walletAddress, update: refresh);

// we only show the first 7 characters of the primary name
// if the primary name is longer than 7 characters
final truncatedPrimaryName =
primaryName.length > 7 ? primaryName.substring(0, 7) : primaryName;
final truncatedPrimaryName = _truncatePrimaryName(primaryName);

emit(ProfileNameLoaded(
truncatedPrimaryName, _auth.currentUser.walletAddress));
} catch (e) {
emit(
ProfileNameLoaded(truncatedPrimaryName, walletAddress),
);
} catch (e) {
if (e is PrimaryNameNotFoundException) {
logger.d('Primary name not found for address: $walletAddress');
} else {
logger.e('Error getting primary name.', e);
emit(ProfileNameLoadedWithWalletAddress(
_auth.currentUser.walletAddress,
));
}
});

emit(
ProfileNameLoadedWithWalletAddress(
walletAddress,
),
);
}
}

/// Truncates the primary name to 20 characters
String _truncatePrimaryName(String primaryName) {
kunstmusik marked this conversation as resolved.
Show resolved Hide resolved
if (primaryName.length > 20) {
return primaryName.substring(0, 20);
}

return primaryName;
}
}
2 changes: 2 additions & 0 deletions lib/user/name/presentation/bloc/profile_name_event.dart
Original file line number Diff line number Diff line change
@@ -7,4 +7,6 @@ sealed class ProfileNameEvent extends Equatable {
List<Object> get props => [];
}

final class RefreshProfileName extends ProfileNameEvent {}

final class LoadProfileName extends ProfileNameEvent {}
10 changes: 8 additions & 2 deletions packages/ardrive_ui/lib/src/components/button.dart
Original file line number Diff line number Diff line change
@@ -367,8 +367,14 @@ class _ArDriveButtonNewState extends State<ArDriveButtonNew> {
final text = Text(widget.text,
textAlign: TextAlign.center,
style: widget.fontStyle ??
typography.paragraphLarge(
color: foregroundColor, fontWeight: ArFontWeight.semiBold));
typography
.paragraphLarge(
color: foregroundColor,
fontWeight: ArFontWeight.semiBold,
)
.copyWith(
overflow: TextOverflow.ellipsis,
));

final buttonH = widget.maxHeight ?? buttonDefaultHeight;

14 changes: 14 additions & 0 deletions packages/ario_sdk/README.md
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ This SDK facilitates interaction with the Ario network by providing Dart APIs fo
- [Creating an Instance](#creating-an-instance)
- [Fetching Gateways](#fetching-gateways)
- [Fetching IO Token Balance](#fetching-io-token-balance)
- [Fetching Primary Name](#fetching-primary-name)
- [Models](#models)
- [Platform Support](#platform-support)

@@ -72,6 +73,19 @@ Future<void> fetchIOTokens(String address) async {
}
```

### Fetching Primary Name

Fetch the primary name for a specific wallet address:

```dart
Future<void> fetchPrimaryName(String address) async {
final primaryName = await arioSDK.getPrimaryName(address);
print('Primary Name: $primaryName');
}
```

Throws a [PrimaryNameNotFoundException] if the primary name is not found.

## Models

The SDK include the Gateway model that represent the data structures used by the Ario network:
1 change: 1 addition & 0 deletions packages/ario_sdk/lib/ario_sdk.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library ario_sdk;

export 'src/ario_sdk.dart';
export 'src/exceptions.dart';
export 'src/factory.dart';
export 'src/models/models.dart';
export 'src/utils/utils.dart';
3 changes: 3 additions & 0 deletions packages/ario_sdk/lib/src/ario_sdk.dart
Original file line number Diff line number Diff line change
@@ -28,5 +28,8 @@ abstract class ArioSDK {
String undername = '@',
});

/// Get the primary name for the given address
///
/// Throws [PrimaryNameNotFoundException] if the primary name is not found
Future<String> getPrimaryName(String address);
}
4 changes: 4 additions & 0 deletions packages/ario_sdk/lib/src/exceptions.dart
Original file line number Diff line number Diff line change
@@ -16,3 +16,7 @@ class GetIOTokensException extends ARIOException {
class GetGatewaysException extends ARIOException {
GetGatewaysException(super.message);
}

class PrimaryNameNotFoundException extends ARIOException {
PrimaryNameNotFoundException(super.message);
}
4 changes: 4 additions & 0 deletions packages/ario_sdk/lib/src/implementations/ario_sdk_web.dart
Original file line number Diff line number Diff line change
@@ -102,6 +102,10 @@ class ArioSDKWeb implements ArioSDK {
Future<String> getPrimaryName(String address) async {
final primaryName = await _getPrimaryNameImpl(address);

if (primaryName.contains('Primary name data not found')) {
throw PrimaryNameNotFoundException(primaryName);
}

return primaryName;
}
}
1 change: 0 additions & 1 deletion packages/ario_sdk/web/src/index.js
Original file line number Diff line number Diff line change
@@ -162,6 +162,5 @@ async function getProcesses(address) {
async function getPrimaryName(address) {
console.log('Fetching primary name for address:', address);
const result = await io.getPrimaryName({ address: address });
console.log('Primary name:', result);
return JSON.stringify(result);
}