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-5746: Release ArDrive v2.36.0 #1640

Merged
merged 19 commits into from
Feb 27, 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
3 changes: 3 additions & 0 deletions android/fastlane/metadata/android/en-US/changelogs/111.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Updates user interface to include new Creative Commons license options: CC0, CC-BY-NC, CC-BY-NC-ND, CC-BY-NC-SA, CC-BY-ND, and CC-BY-SA.
- Fixes issue with moving files in private drives
- Fixes issue displaying long content in the activity section of the details panel
1 change: 0 additions & 1 deletion lib/blocs/fs_entry_info/fs_entry_info_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ class FsEntryInfoCubit extends Cubit<FsEntryInfoState> {
licenseDefinitionTxId: '',
name: 'Pending',
shortName: 'Pending',
version: '',
),
);
}
Expand Down
313 changes: 190 additions & 123 deletions lib/blocs/fs_entry_license/fs_entry_license_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,63 @@ part 'fs_entry_license_state.dart';

class FsEntryLicenseBloc
extends Bloc<FsEntryLicenseEvent, FsEntryLicenseState> {
FsEntryLicenseBloc({
required this.driveId,
required this.selectedItems,
required ArweaveService arweave,
required TurboUploadService turboUploadService,
required DriveDao driveDao,
required ProfileCubit profileCubit,
required ArDriveCrypto crypto,
required LicenseService licenseService,
Platform platform = const LocalPlatform(),
}) : _arweave = arweave,
_turboUploadService = turboUploadService,
_driveDao = driveDao,
_profileCubit = profileCubit,
_crypto = crypto,
_licenseService = licenseService,
super(const FsEntryLicenseLoadInProgress()) {
if (selectedItems.isEmpty) {
addError(Exception('selectedItems cannot be empty'));
}

on<FsEntryLicenseEvent>(_onEvent, transformer: restartable());
}

final String driveId;
final List<ArDriveDataTableItem> selectedItems;

final selectForm = FormGroup({
'licenseType': FormControl<LicenseMeta>(
// We initialize with UDL license by default
LicenseMeta _selectedLicenseMeta = udlLicenseMeta;
LicenseMeta get selectedLicenseMeta => _selectedLicenseMeta;

List<FileEntry>? filesToLicense;
LicenseParams? licenseParams;

final ArweaveService _arweave;
final TurboUploadService _turboUploadService;
final DriveDao _driveDao;
final ProfileCubit _profileCubit;
final ArDriveCrypto _crypto;
final LicenseService _licenseService;

final List<String> errorLog = [];

/// Form getters
FormGroup get selectForm => _selectForm;
FormGroup get udlForm => _udlForm;
FormGroup get ccForm => _ccForm;

// Forms
final _selectForm = FormGroup({
'licenseType': FormControl<LicenseCategory>(
validators: [Validators.required],
value: udlLicenseMeta,
value: LicenseCategory.udl,
),
});
LicenseMeta get selectFormLicenseMeta =>
selectForm.control('licenseType').value;

final udlForm = FormGroup({
final _udlForm = FormGroup({
'licenseFeeAmount': FormControl<String>(
validators: [
Validators.composeOR([
Expand All @@ -59,139 +103,141 @@ class FsEntryLicenseBloc
),
});

List<FileEntry>? filesToLicense;
LicenseParams? licenseParams;

final ArweaveService _arweave;
final TurboUploadService _turboUploadService;
final DriveDao _driveDao;
final ProfileCubit _profileCubit;
final ArDriveCrypto _crypto;
final LicenseService _licenseService;

final List<String> errorLog = [];
final _ccForm = FormGroup({
'ccAttributionField': FormControl<LicenseMeta>(
validators: [Validators.required],
value: cc0LicenseMeta,
),
});

FsEntryLicenseBloc({
required this.driveId,
required this.selectedItems,
required ArweaveService arweave,
required TurboUploadService turboUploadService,
required DriveDao driveDao,
required ProfileCubit profileCubit,
required ArDriveCrypto crypto,
required LicenseService licenseService,
Platform platform = const LocalPlatform(),
}) : _arweave = arweave,
_turboUploadService = turboUploadService,
_driveDao = driveDao,
_profileCubit = profileCubit,
_crypto = crypto,
_licenseService = licenseService,
super(const FsEntryLicenseLoadInProgress()) {
if (selectedItems.isEmpty) {
addError(Exception('selectedItems cannot be empty'));
Future<void> _onEvent(
FsEntryLicenseEvent event,
Emitter<FsEntryLicenseState> emit,
) async {
if (event is FsEntryLicenseInitial) {
await _handleInitial(event, emit);
} else if (event is FsEntryLicenseSelect) {
await _handleSelect(event, emit);
} else if (event is FsEntryLicenseConfigurationSubmit) {
await _handleConfigurationSubmit(event, emit);
} else if (event is FsEntryLicenseReviewConfirm) {
await _handleReviewConfirm(event, emit);
} else if (event is FsEntryLicenseReviewBack) {
_handleReviewBack(event, emit);
} else if (event is FsEntryLicenseConfigurationBack) {
_handleConfigurationBack(event, emit);
} else if (event is FsEntryLicenseSuccessClose) {
_handleSuccessClose(event, emit);
} else if (event is FsEntryLicenseFailureTryAgain) {
_handleFailureTryAgain(event, emit);
} else {
addError('Unsupported event: ${event.runtimeType}');
}
}

final profile = _profileCubit.state as ProfileLoggedIn;

on<FsEntryLicenseEvent>(
(event, emit) async {
if (await _profileCubit.logoutIfWalletMismatch()) {
emit(const FsEntryLicenseWalletMismatch());
return;
}
Future<void> _handleInitial(
FsEntryLicenseInitial event,
Emitter<FsEntryLicenseState> emit,
) async {
filesToLicense = await _enumerateFiles(items: selectedItems, emit: emit);
if (filesToLicense!.isEmpty) {
emit(const FsEntryLicenseNoFiles());
} else {
emit(const FsEntryLicenseSelecting());
}
}

if (event is FsEntryLicenseInitial) {
filesToLicense =
await enumerateFiles(items: selectedItems, emit: emit);
if (filesToLicense!.isEmpty) {
emit(const FsEntryLicenseNoFiles());
} else {
emit(const FsEntryLicenseSelecting());
}
}
Future<void> _handleSelect(
FsEntryLicenseSelect event,
Emitter<FsEntryLicenseState> emit,
) async {
final licenseType = selectForm.control('licenseType').value;

switch (licenseType) {
case LicenseCategory.udl:
_selectedLicenseMeta = udlLicenseMetaV2;
break;
case LicenseCategory.cc:
_selectedLicenseMeta = ccByLicenseMetaV2;
break;
}

if (event is FsEntryLicenseSelect) {
if (selectFormLicenseMeta.hasParams) {
emit(const FsEntryLicenseConfiguring());
} else {
licenseParams = null;
emit(const FsEntryLicenseReviewing());
}
}
emit(const FsEntryLicenseConfiguring());
}

if (event is FsEntryLicenseConfigurationBack) {
emit(const FsEntryLicenseSelecting());
}
Future<void> _handleConfigurationSubmit(
FsEntryLicenseConfigurationSubmit event,
Emitter<FsEntryLicenseState> emit,
) async {
final licenseCategory = selectForm.control('licenseType').value;

if (event is FsEntryLicenseConfigurationSubmit) {
if (selectFormLicenseMeta.licenseType == LicenseType.udl) {
licenseParams = await udlFormToLicenseParams(udlForm);
} else {
addError(
'Unsupported license configuration: ${selectFormLicenseMeta.licenseType}');
}
emit(const FsEntryLicenseReviewing());
}
if (licenseCategory == LicenseCategory.cc) {
_selectedLicenseMeta = ccForm.control('ccAttributionField').value;
}

if (event is FsEntryLicenseReviewBack) {
if (selectFormLicenseMeta.hasParams) {
licenseParams = null;
emit(const FsEntryLicenseConfiguring());
} else {
emit(const FsEntryLicenseSelecting());
}
}
if (_selectedLicenseMeta.licenseType == LicenseType.udlV2) {
licenseParams = await _udlFormToLicenseParams(udlForm);
} else {
addError(
'Unsupported license configuration: ${_selectedLicenseMeta.licenseType}');
}

if (event is FsEntryLicenseReviewConfirm) {
emit(const FsEntryLicenseLoadInProgress());
try {
await licenseEntities(
profile: profile,
licenseMeta: selectFormLicenseMeta,
licenseParams: licenseParams,
);
emit(const FsEntryLicenseSuccess());
} catch (_, trace) {
addError('Error licensing entities', trace);
emit(const FsEntryLicenseFailure());
}
}
emit(const FsEntryLicenseReviewing());
}

if (event is FsEntryLicenseSuccessClose) {
emit(const FsEntryLicenseComplete());
}
Future<void> _handleReviewConfirm(
FsEntryLicenseReviewConfirm event,
Emitter<FsEntryLicenseState> emit,
) async {
emit(const FsEntryLicenseLoadInProgress());
try {
final profile = _profileCubit.state as ProfileLoggedIn;
await _licenseEntities(
profile: profile,
licenseMeta: _selectedLicenseMeta,
licenseParams: licenseParams,
);
emit(const FsEntryLicenseSuccess());
} catch (_, trace) {
addError('Error licensing entities', trace);
emit(const FsEntryLicenseFailure());
}
}

if (event is FsEntryLicenseFailureTryAgain) {
emit(const FsEntryLicenseReviewing());
}
},
transformer: restartable(),
);
void _handleReviewBack(
FsEntryLicenseReviewBack event,
Emitter<FsEntryLicenseState> emit,
) {
if (_selectedLicenseMeta.hasParams) {
licenseParams = null;
emit(const FsEntryLicenseConfiguring());
} else {
emit(const FsEntryLicenseSelecting());
}
}

Future<UdlLicenseParams> udlFormToLicenseParams(FormGroup udlForm) async {
final String? licenseFeeAmountString =
udlForm.control('licenseFeeAmount').value;
final double? licenseFeeAmount = licenseFeeAmountString == null
? null
: double.tryParse(licenseFeeAmountString);
void _handleConfigurationBack(
FsEntryLicenseConfigurationBack event,
Emitter<FsEntryLicenseState> emit,
) {
emit(const FsEntryLicenseSelecting());
}

final UdlCurrency licenseFeeCurrency =
udlForm.control('licenseFeeCurrency').value;
final UdlCommercialUse commercialUse =
udlForm.control('commercialUse').value;
final UdlDerivation derivations = udlForm.control('derivations').value;
void _handleSuccessClose(
FsEntryLicenseSuccessClose event,
Emitter<FsEntryLicenseState> emit,
) {
emit(const FsEntryLicenseComplete());
}

return UdlLicenseParams(
licenseFeeAmount: licenseFeeAmount,
licenseFeeCurrency: licenseFeeCurrency,
commercialUse: commercialUse,
derivations: derivations,
);
void _handleFailureTryAgain(
FsEntryLicenseFailureTryAgain event,
Emitter<FsEntryLicenseState> emit,
) {
emit(const FsEntryLicenseReviewing());
}

Future<List<FileEntry>> enumerateFiles({
Future<List<FileEntry>> _enumerateFiles({
required List<ArDriveDataTableItem> items,
required Emitter<FsEntryLicenseState> emit,
}) async {
Expand Down Expand Up @@ -231,7 +277,7 @@ class FsEntryLicenseBloc
return files.where((file) => file.pinnedDataOwnerAddress == null).toList();
}

Future<void> licenseEntities({
Future<void> _licenseEntities({
required ProfileLoggedIn profile,
required LicenseMeta licenseMeta,
LicenseParams? licenseParams,
Expand Down Expand Up @@ -323,6 +369,27 @@ class FsEntryLicenseBloc
}
}

Future<UdlLicenseParams> _udlFormToLicenseParams(FormGroup udlForm) async {
final String? licenseFeeAmountString =
udlForm.control('licenseFeeAmount').value;
final double? licenseFeeAmount = licenseFeeAmountString == null
? null
: double.tryParse(licenseFeeAmountString);

final UdlCurrency licenseFeeCurrency =
udlForm.control('licenseFeeCurrency').value;
final UdlCommercialUse commercialUse =
udlForm.control('commercialUse').value;
final UdlDerivation derivations = udlForm.control('derivations').value;

return UdlLicenseParams(
licenseFeeAmount: licenseFeeAmount,
licenseFeeCurrency: licenseFeeCurrency,
commercialUse: commercialUse,
derivations: derivations,
);
}

@override
void onError(Object error, StackTrace stackTrace) {
errorLog.add(error.toString());
Expand Down
Loading
Loading