Skip to content

Commit

Permalink
feat: quick node for thumbnail uploading
Browse files Browse the repository at this point in the history
  • Loading branch information
AhsanRns committed May 15, 2024
1 parent f20be2f commit 407981c
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 0 deletions.
2 changes: 2 additions & 0 deletions evently/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release

lib/env.dart
131 changes: 131 additions & 0 deletions evently/lib/services/third_party_services/quick_node.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import 'dart:async';

import 'package:dio/dio.dart';
import 'package:evently/env.dart';
import 'package:injectable/injectable.dart';

typedef OnUploadProgressCallback = void Function(UploadProgress uploadProgress);

class UploadProgress {
int totalSize;
int sendSize;
double uploadedProgressData;

UploadProgress({
required this.totalSize,
required this.sendSize,
required this.uploadedProgressData,
});
}

abstract class QuickNode {
/// Upload a new object to IPFS and pins it for permanent storage on the network.
/// [UploadIPFSInput] as an input
/// [UploadIPFSOutput] as an output
Future<void> uploadNewObjectToIPFS({required UploadIPFSInput uploadIPFSInput, required OnUploadProgressCallback onUploadProgressCallback});

/// these are the list of extension required
static List<String> listOfQuickNodeAllowedExtension() => ['jpg', 'png', 'heif', 'jpeg', 'gif'];

/// this method is used to get the content type while making request input to quick node
static String getContentType(String fileExtension) {
final dict = {
///* images
"jpg": "image/jpg",
"png": "image/png",
'heif': "image/heif",
'jpeg': "image/jpeg",
'gif': "image/gif",
};
return dict[fileExtension]!;
}
}

@LazySingleton(as: QuickNode)
class QuickNodeImpl extends QuickNode {
QuickNodeImpl({required this.httpClient});

final Dio httpClient;

@override
Future<void> uploadNewObjectToIPFS({required UploadIPFSInput uploadIPFSInput, required OnUploadProgressCallback onUploadProgressCallback}) async {
try {
httpClient.options.headers['x-api-key'] = xApiKey;

final response = await httpClient.post(
'https://api.quicknode.com/ipfs/rest/v1/s3/put-object',
data: FormData.fromMap({
'Body': await MultipartFile.fromFile(uploadIPFSInput.filePath),
'Key': uploadIPFSInput.fileName,
'ContentType': uploadIPFSInput.contentType,
}),
onSendProgress: (uploaded, total) {
final double uploadedPercentage = uploaded / total;
onUploadProgressCallback(
UploadProgress(totalSize: total, sendSize: uploaded, uploadedProgressData: uploadedPercentage),
);
},
);

final uploadIPFSOutput = UploadIPFSOutput.fromJson(response.data as Map<String, dynamic>);

// return //StorageResponseModel.fromQuickNode(uploadIPFSOutput: uploadIPFSOutput);
} catch (e) {
throw Exception('Failed to upload file: $e');
}
}
}

class UploadIPFSInput {
final String fileName;
final String filePath;
final String contentType;

UploadIPFSInput({
required this.fileName,
required this.filePath,
required this.contentType,
});
}

class UploadIPFSOutput {
final String? requestId;
final String? status;
final String? created;
final Pin? pin;
final Info? info;
final List<String>? delegates;

UploadIPFSOutput({this.requestId, this.status, this.created, this.pin, this.info, this.delegates});

factory UploadIPFSOutput.fromJson(Map<String, dynamic> json) {
return UploadIPFSOutput(
requestId: json['requestid'] as String?,
status: json['status'] as String?,
created: json['created'] as String?,
pin: Pin.fromJson(json['pin'] as Map<String, dynamic>),
info: Info.fromJson(json['info'] as Map<String, dynamic>),
delegates: [],
);
}
}

class Pin {
String? cid;
String? name;

Pin({this.cid, this.name});

factory Pin.fromJson(Map<String, dynamic> json) => Pin(
cid: json['cid'] as String?,
name: json['name'] as String?,
);
}

class Info {
final String? size;

Info({this.size});

factory Info.fromJson(Map<String, dynamic> json) => Info(size: json['size'] as String?);
}
4 changes: 4 additions & 0 deletions evently/lib/utils/di/register_modules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Injectable is a convenient code generator for get_it.
// All you have to do now is annotate your injectable classes with @injectable and let the generator do the work.
// This class is use to generate code to register objects on app start
import 'package:dio/dio.dart';
import 'package:file_picker/file_picker.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:injectable/injectable.dart';
Expand All @@ -14,4 +15,7 @@ abstract class RegisterModule {

@LazySingleton()
FilePicker get filePicker => FilePicker.platform;

@LazySingleton()
Dio get dio => Dio();
}
8 changes: 8 additions & 0 deletions evently/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.3"
dio:
dependency: "direct main"
description:
name: dio
sha256: "11e40df547d418cc0c4900a9318b26304e665da6fa4755399a9ff9efd09034b5"
url: "https://pub.dev"
source: hosted
version: "5.4.3+1"
dotted_border:
dependency: "direct main"
description:
Expand Down
1 change: 1 addition & 0 deletions evently/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ dependencies:
pylons_sdk:
path: ../dart_sdk
shared_preferences: ^2.2.3
dio: ^5.4.3+1

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit 407981c

Please sign in to comment.