Skip to content

Commit

Permalink
Merge pull request #1733 from ardriveapp/dev
Browse files Browse the repository at this point in the history
PE-6085: Release ArDrive App v2.43.0
  • Loading branch information
thiagocarvalhodev authored May 2, 2024
2 parents 0c1d15c + b3a441e commit d804d3b
Show file tree
Hide file tree
Showing 18 changed files with 714 additions and 351 deletions.
1 change: 1 addition & 0 deletions android/fastlane/metadata/android/en-US/changelogs/125.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- New Feature: Search (for quickly locating files and navigating through folders and drives)
2 changes: 1 addition & 1 deletion assets/config/prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"enablePins": true,
"useNewUploader": true,
"enableMetamaskLogin": true,
"enableSearch": false
"enableSearch": true
}
15 changes: 7 additions & 8 deletions lib/blocs/drive_detail/drive_detail_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ class DriveDetailCubit extends Cubit<DriveDetailState> {
pathSegments: pathSegments,
driveIsEmpty: folderContents.files.isEmpty &&
folderContents.subfolders.isEmpty,

),
);
} else {
Expand Down Expand Up @@ -307,11 +306,7 @@ class DriveDetailCubit extends Cubit<DriveDetailState> {
var state = this.state as DriveDetailLoadSuccess;

if (state.currentDrive.isPublic && item is FileDataTableItem) {
final fileWithRevisions = _driveDao.latestFileRevisionByFileId(
driveId: driveId,
fileId: item.id,
);
final dataTxId = (await fileWithRevisions.getSingle()).dataTxId;
final dataTxId = item.dataTxId;
state = state.copyWith(
selectedFilePreviewUrl:
'${_configService.config.defaultArweaveGatewayUrl}/$dataTxId');
Expand All @@ -326,10 +321,14 @@ class DriveDetailCubit extends Cubit<DriveDetailState> {
state.currentFolderContents.indexOf(item) ~/ state.rowsPerPage;
}

emit(state.copyWith(
emit(
state.copyWith(
selectedItem: item,
showSelectedItemDetails: true,
selectedPage: selectedPage));
selectedPage: selectedPage,
forceRebuildKey: selectedPage != null ? UniqueKey() : null,
),
);
}

ArDriveDataTableItem? _selectedItem;
Expand Down
1 change: 1 addition & 0 deletions lib/blocs/drive_detail/drive_detail_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class DriveDetailLoadSuccess extends DriveDetailState {
multiselect,
forceRebuildKey,
selectedItem,
selectedPage,
];
SelectedItem? maybeSelectedItem() =>
selectedItems.isNotEmpty ? selectedItems.first : null;
Expand Down
35 changes: 20 additions & 15 deletions lib/components/app_top_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:ardrive/gift/reedem_button.dart';
import 'package:ardrive/pages/drive_detail/components/dropdown_item.dart';
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/services/config/config.dart';
import 'package:ardrive/sync/domain/cubit/sync_cubit.dart';
import 'package:ardrive/utils/app_localizations_wrapper.dart';
Expand All @@ -21,6 +22,7 @@ class AppTopBar extends StatelessWidget {
Widget build(BuildContext context) {
final enableSearch = context.read<ConfigService>().config.enableSearch;
final colorTokens = ArDriveTheme.of(context).themeData.colorTokens;
final controller = TextEditingController();

return SizedBox(
height: 110,
Expand All @@ -32,25 +34,28 @@ class AppTopBar extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (enableSearch) ...[
Flexible(
child: ArDriveTextFieldNew(
hintText: 'Search',
suffixIcon: const Icon(Icons.search),
onFieldSubmitted: (s) {
showArDriveDialog(
context,
content: FileSearchModal(
initialQuery: s,
driveDetailCubit: context.read<DriveDetailCubit>(),
),
// blur effect
barrierColor: colorTokens.containerL1.withOpacity(0.8),
);
},
Expanded(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: SearchTextField(
controller: controller,
onFieldSubmitted: (query) {
showArDriveDialog(
context,
content: FileSearchModal(
initialQuery: query,
driveDetailCubit: context.read<DriveDetailCubit>(),
controller: controller,
),
barrierColor: colorTokens.containerL1.withOpacity(0.8),
);
},
),
),
),
const SizedBox(width: 24),
],
const Spacer(),
const SyncButton(),
const SizedBox(width: 24),
const RedeemButton(),
Expand Down
93 changes: 46 additions & 47 deletions lib/models/daos/drive_dao/drive_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:ardrive/core/crypto/crypto.dart';
import 'package:ardrive/entities/entities.dart';
import 'package:ardrive/models/license.dart';
import 'package:ardrive/models/models.dart';
import 'package:ardrive/search/search_result.dart';
import 'package:ardrive_utils/ardrive_utils.dart';
import 'package:arweave/arweave.dart';
import 'package:cryptography/cryptography.dart';
Expand Down Expand Up @@ -430,65 +431,75 @@ class DriveDao extends DatabaseAccessor<Database> with _$DriveDaoMixin {
});
}

Future<List<SearchResult>> searchFiles(String name) async {
final resultFiles = await (select(fileRevisions)
..where((tbl) => tbl.name.like('%$name%')))
.get();
final resultFolders = await (select(folderRevisions)
..where((tbl) => tbl.name.like('%$name%')))
Future<List<SearchResult>> search({
required String query,
required SearchQueryType type,
}) async {
final resultFiles = await (select(fileEntries)
..where((tbl) => tbl.name.like('%$query%')))
.get();
final resultDrives = await (select(driveRevisions)
..where((tbl) => tbl.name.like('%$name%')))
final resultFolders = await (select(folderEntries)
..where((tbl) => tbl.name.like('%$query%')))
.get();
final resultDrives =
await (select(drives)..where((tbl) => tbl.name.like('%$query%'))).get();

resultFolders.removeWhere((element) => element.parentFolderId == null);

final List<SearchResult> results = [];
final fileResults = await Future.wait(
resultFiles.map(
(file) async {
final folder = await folderById(
driveId: file.driveId,
folderId: file.parentFolderId,
).getSingle();

final drive = await driveById(driveId: file.driveId).getSingle();
FolderEntry? folder;

return SearchResult<FileRevision>(
if (file.parentFolderId != drive.rootFolderId) {
folder = await folderById(
driveId: file.driveId,
folderId: file.parentFolderId,
).getSingle();
}

return SearchResult<FileEntry>(
result: file,
folder: folder,
parentFolder: folder,
drive: drive,
);
},
),
);

final folderResults = await Future.wait(resultFolders.map((folder) async {
FolderEntry? parentFolder;

if (folder.parentFolderId != null) {
final parentFolderEntry = await folderById(
driveId: folder.driveId,
folderId: folder.parentFolderId!,
).getSingle();
parentFolder = parentFolderEntry;
}

final drive = await driveById(driveId: folder.driveId).getSingle();
final folderResults = await Future.wait(
resultFolders.map(
(folder) async {
FolderEntry? parentFolder;
final drive = await driveById(driveId: folder.driveId).getSingle();

if (folder.parentFolderId != null &&
folder.parentFolderId! != drive.rootFolderId) {
final parentFolderEntry = await folderById(
driveId: folder.driveId,
folderId: folder.parentFolderId!,
).getSingle();
parentFolder = parentFolderEntry;
}

return SearchResult<FolderRevision>(
result: folder,
folder: parentFolder,
drive: drive,
);
}));
return SearchResult<FolderEntry>(
result: folder,
parentFolder: parentFolder,
drive: drive,
);
},
),
);

final driveResults = await Future.wait(resultDrives.map((drive) async {
return SearchResult<DriveRevision>(
return SearchResult<Drive>(
result: drive,
drive: await driveById(driveId: drive.driveId).getSingle(),
drive: await driveById(driveId: drive.id).getSingle(),
);
}));

results.addAll(driveResults);
results.addAll(folderResults);
results.addAll(fileResults);
Expand Down Expand Up @@ -641,15 +652,3 @@ class DriveDao extends DatabaseAccessor<Database> with _$DriveDaoMixin {
});
}
}

class SearchResult<T> {
final T result;
final FolderEntry? folder;
final Drive drive;

SearchResult({
required this.result,
this.folder,
required this.drive,
});
}
27 changes: 26 additions & 1 deletion lib/pages/drive_detail/components/drive_detail_data_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ Widget _buildDataListContent(
!context.watch<ActivityTracker>().isMultiSelectEnabled,
rowsPerPageText: appLocalizationsOf(context).rowsPerPage,
maxItemsPerPage: 100,

pageItemsDivisorFactor: 25,
onSelectedRows: (boxes) {
final bloc = context.read<DriveDetailCubit>();
Expand Down Expand Up @@ -408,6 +407,32 @@ class DriveDataTableItemMapper {
);
}

static FileDataTableItem fromFileEntryForSearchModal(
FileEntry fileEntry,
) {
return FileDataTableItem(
isOwner: true,
lastModifiedDate: fileEntry.lastModifiedDate,
name: fileEntry.name,
size: fileEntry.size,
lastUpdated: fileEntry.lastUpdated,
dateCreated: fileEntry.dateCreated,
contentType: fileEntry.dataContentType ?? '',
fileStatusFromTransactions: null,
fileId: fileEntry.id,
driveId: fileEntry.driveId,
parentFolderId: fileEntry.parentFolderId,
dataTxId: fileEntry.dataTxId,
bundledIn: fileEntry.bundledIn,
licenseTxId: fileEntry.licenseTxId,
metadataTx: null,
dataTx: null,
index: 0,
pinnedDataOwnerAddress: fileEntry.pinnedDataOwnerAddress,
isHidden: fileEntry.isHidden,
);
}

static FolderDataTableItem fromFolderEntry(
FolderEntry folderEntry,
int index,
Expand Down
31 changes: 31 additions & 0 deletions lib/search/domain/bloc/search_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:ardrive/search/domain/repository/search_repository.dart';
import 'package:ardrive/search/search_result.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

part 'search_event.dart';
part 'search_state.dart';

class SearchBloc extends Bloc<SearchEvent, SearchState> {
final SearchRepository _searchRepository;

SearchBloc(
this._searchRepository,
) : super(SearchInitial()) {
on<SearchEvent>((event, emit) async {
if (event is SearchQueryChanged) {
if (event.query.isEmpty) {
emit(SearchQueryEmpty());
} else {
final results = await _searchRepository.search(event.query);

if (results.isEmpty) {
emit(SearchEmpty());
} else {
emit(SearchSuccess(results));
}
}
}
});
}
}
17 changes: 17 additions & 0 deletions lib/search/domain/bloc/search_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
part of 'search_bloc.dart';

sealed class SearchEvent extends Equatable {
const SearchEvent();

@override
List<Object> get props => [];
}

class SearchQueryChanged extends SearchEvent {
final String query;

const SearchQueryChanged(this.query);

@override
List<Object> get props => [query];
}
23 changes: 23 additions & 0 deletions lib/search/domain/bloc/search_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
part of 'search_bloc.dart';

sealed class SearchState extends Equatable {
const SearchState();

@override
List<Object> get props => [];
}

final class SearchInitial extends SearchState {}

final class SearchEmpty extends SearchState {}

final class SearchQueryEmpty extends SearchState {}

final class SearchSuccess extends SearchState {
final List<SearchResult> results;

const SearchSuccess(this.results);

@override
List<Object> get props => [results];
}
21 changes: 21 additions & 0 deletions lib/search/domain/repository/search_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:ardrive/models/daos/drive_dao/drive_dao.dart';
import 'package:ardrive/search/search_result.dart';

abstract class SearchRepository {
Future<List<SearchResult>> search(String query);
}

class ArDriveSearchRepository implements SearchRepository {
final DriveDao _driveDao;

ArDriveSearchRepository(this._driveDao);

@override
Future<List<SearchResult>> search(String query) async {
if (query.isEmpty) return Future.value([]);

String sanitizedQuery = query.toLowerCase();

return _driveDao.search(query: sanitizedQuery, type: SearchQueryType.name);
}
}
Loading

0 comments on commit d804d3b

Please sign in to comment.