Solian/lib/providers/content/attachment.dart

180 lines
4.8 KiB
Dart
Raw Normal View History

2024-05-22 15:18:01 +00:00
import 'dart:convert';
2024-06-29 12:25:29 +00:00
import 'dart:typed_data';
2024-05-22 15:18:01 +00:00
import 'package:get/get.dart';
import 'package:path/path.dart';
import 'package:solian/models/attachment.dart';
import 'package:solian/models/pagination.dart';
2024-05-22 15:18:01 +00:00
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
import 'package:dio/dio.dart' as dio;
2024-05-22 15:18:01 +00:00
class AttachmentProvider extends GetConnect {
2024-06-29 12:25:29 +00:00
static Map<String, String> mimetypeOverrides = {
'mov': 'video/quicktime',
'mp4': 'video/mp4'
};
2024-06-01 13:39:28 +00:00
2024-05-22 15:18:01 +00:00
@override
void onInit() {
httpClient.baseUrl = ServiceFinder.buildUrl('files', null);
2024-05-22 15:18:01 +00:00
}
final Map<int, Attachment> _cachedResponses = {};
2024-05-27 15:07:01 +00:00
Future<List<Attachment?>> listMetadata(
List<int> id, {
noCache = false,
}) async {
if (id.isEmpty) return List.empty();
List<Attachment?> result = List.filled(id.length, null);
List<int> pendingQuery = List.empty(growable: true);
if (!noCache) {
for (var idx = 0; idx < id.length; idx++) {
if (_cachedResponses.containsKey(id[idx])) {
result[idx] = _cachedResponses[id[idx]];
} else {
pendingQuery.add(id[idx]);
}
}
}
final resp = await get(
'/attachments?take=${pendingQuery.length}&id=${pendingQuery.join(',')}',
);
if (resp.statusCode != 200) return result;
final rawOut = PaginationResult.fromJson(resp.body);
if (rawOut.data == null) return result;
final List<Attachment> out =
rawOut.data!.map((x) => Attachment.fromJson(x)).toList();
for (final item in out) {
if (item.destination != 0 && item.isAnalyzed) {
_cachedResponses[item.id] = item;
}
}
for (var i = 0; i < out.length; i++) {
for (var j = 0; j < id.length; j++) {
if (out[i].id == id[j]) {
result[j] = out[i];
}
}
}
return result;
}
Future<Attachment?> getMetadata(int id, {noCache = false}) async {
2024-06-01 13:39:28 +00:00
if (!noCache && _cachedResponses.containsKey(id)) {
return _cachedResponses[id]!;
}
final resp = await get('/attachments/$id/meta');
if (resp.statusCode == 200) {
final result = Attachment.fromJson(resp.body);
if (result.destination != 0 && result.isAnalyzed) {
_cachedResponses[id] = result;
}
return result;
}
2024-06-01 13:39:28 +00:00
return null;
2024-06-01 13:39:28 +00:00
}
2024-05-22 15:18:01 +00:00
Future<Attachment> createAttachment(
2024-08-01 14:13:08 +00:00
Uint8List data, String path, String usage, Map<String, dynamic>? metadata,
{Function(double)? onProgress}) async {
2024-05-22 15:18:01 +00:00
final AuthProvider auth = Get.find();
2024-07-24 17:18:47 +00:00
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
2024-05-22 15:18:01 +00:00
2024-08-04 13:12:35 +00:00
await auth.ensureCredentials();
final filePayload =
dio.MultipartFile.fromBytes(data, filename: basename(path));
2024-06-29 12:25:29 +00:00
final fileAlt = basename(path).contains('.')
? basename(path).substring(0, basename(path).lastIndexOf('.'))
: basename(path);
final fileExt = basename(path)
.substring(basename(path).lastIndexOf('.') + 1)
2024-05-27 15:07:01 +00:00
.toLowerCase();
// Override for some files cannot be detected mimetype by server-side
String? mimetypeOverride;
if (mimetypeOverrides.keys.contains(fileExt)) {
mimetypeOverride = mimetypeOverrides[fileExt];
}
final payload = dio.FormData.fromMap({
2024-06-03 15:36:46 +00:00
'alt': fileAlt,
'file': filePayload,
'usage': usage,
if (mimetypeOverride != null) 'mimetype': mimetypeOverride,
'metadata': jsonEncode(metadata),
2024-06-03 15:36:46 +00:00
});
final resp = await dio.Dio(
dio.BaseOptions(
baseUrl: ServiceFinder.buildUrl('files', null),
headers: {'Authorization': 'Bearer ${auth.credentials!.accessToken}'},
),
).post(
2024-08-01 14:13:08 +00:00
'/attachments',
data: payload,
onSendProgress: (count, total) {
if (onProgress != null) onProgress(count / total);
2024-08-01 14:13:08 +00:00
},
);
2024-05-27 15:07:01 +00:00
if (resp.statusCode != 200) {
throw Exception(resp.data);
2024-05-22 15:18:01 +00:00
}
return Attachment.fromJson(resp.data);
2024-05-22 15:18:01 +00:00
}
Future<Response> updateAttachment(
int id,
String alt,
String usage, {
bool isMature = false,
}) async {
final AuthProvider auth = Get.find();
2024-07-24 17:18:47 +00:00
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
2024-05-22 15:18:01 +00:00
final client = auth.configureClient('files');
2024-05-22 15:18:01 +00:00
var resp = await client.put('/attachments/$id', {
2024-05-22 15:18:01 +00:00
'alt': alt,
'usage': usage,
'is_mature': isMature,
});
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
2024-05-27 15:07:01 +00:00
return resp;
2024-05-22 15:18:01 +00:00
}
Future<Response> deleteAttachment(int id) async {
final AuthProvider auth = Get.find();
2024-07-24 17:18:47 +00:00
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
2024-05-22 15:18:01 +00:00
final client = auth.configureClient('files');
2024-05-22 15:18:01 +00:00
var resp = await client.delete('/attachments/$id');
2024-05-22 15:18:01 +00:00
if (resp.statusCode != 200) {
throw Exception(resp.bodyString);
}
return resp;
}
2024-06-01 13:39:28 +00:00
void clearCache({int? id}) {
if (id != null) {
_cachedResponses.remove(id);
} else {
_cachedResponses.clear();
}
}
2024-05-22 15:18:01 +00:00
}