mirror of
https://github.com/immich-app/immich.git
synced 2024-12-28 22:51:59 +00:00
fix(web): emit updated date when pressing enter (#9640)
wip uploading format wip first working version
This commit is contained in:
parent
a3489d604b
commit
4907916345
4 changed files with 138 additions and 103 deletions
BIN
mobile/android/kls_database.db
Normal file
BIN
mobile/android/kls_database.db
Normal file
Binary file not shown.
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:background_downloader/background_downloader.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
@ -33,6 +34,7 @@ final backupServiceProvider = Provider(
|
|||
|
||||
class BackupService {
|
||||
final httpClient = http.Client();
|
||||
final _fileDownloader = FileDownloader();
|
||||
final ApiService _apiService;
|
||||
final Isar _db;
|
||||
final Logger _log = Logger("BackupService");
|
||||
|
@ -242,121 +244,146 @@ class BackupService {
|
|||
)
|
||||
: assetList.toList();
|
||||
|
||||
final tasks = <UploadTask>[];
|
||||
for (var entity in assetsToUpload) {
|
||||
File? file;
|
||||
File? livePhotoFile;
|
||||
final isAvailableLocally =
|
||||
await entity.isLocallyAvailable(isOrigin: true);
|
||||
|
||||
try {
|
||||
final isAvailableLocally =
|
||||
await entity.isLocallyAvailable(isOrigin: true);
|
||||
|
||||
// Handle getting files from iCloud
|
||||
if (!isAvailableLocally && Platform.isIOS) {
|
||||
// Skip iCloud assets if the user has disabled this feature
|
||||
if (isIgnoreIcloudAssets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
setCurrentUploadAssetCb(
|
||||
CurrentUploadAsset(
|
||||
id: entity.id,
|
||||
fileCreatedAt: entity.createDateTime.year == 1970
|
||||
? entity.modifiedDateTime
|
||||
: entity.createDateTime,
|
||||
fileName: await entity.titleAsync,
|
||||
fileType: _getAssetType(entity.type),
|
||||
iCloudAsset: true,
|
||||
),
|
||||
);
|
||||
|
||||
file = await entity.loadFile(progressHandler: pmProgressHandler);
|
||||
livePhotoFile = await entity.loadFile(
|
||||
withSubtype: true,
|
||||
progressHandler: pmProgressHandler,
|
||||
);
|
||||
} else {
|
||||
if (entity.type == AssetType.video) {
|
||||
file = await entity.originFile;
|
||||
} else {
|
||||
file = await entity.originFile.timeout(const Duration(seconds: 5));
|
||||
if (entity.isLivePhoto) {
|
||||
livePhotoFile = await entity.originFileWithSubtype
|
||||
.timeout(const Duration(seconds: 5));
|
||||
}
|
||||
}
|
||||
// Handle getting files from iCloud
|
||||
if (!isAvailableLocally && Platform.isIOS) {
|
||||
// Skip iCloud assets if the user has disabled this feature
|
||||
if (isIgnoreIcloudAssets) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
String originalFileName = await entity.titleAsync;
|
||||
var fileStream = file.openRead();
|
||||
var assetRawUploadData = http.MultipartFile(
|
||||
"assetData",
|
||||
fileStream,
|
||||
file.lengthSync(),
|
||||
filename: originalFileName,
|
||||
);
|
||||
setCurrentUploadAssetCb(
|
||||
CurrentUploadAsset(
|
||||
id: entity.id,
|
||||
fileCreatedAt: entity.createDateTime.year == 1970
|
||||
? entity.modifiedDateTime
|
||||
: entity.createDateTime,
|
||||
fileName: await entity.titleAsync,
|
||||
fileType: _getAssetType(entity.type),
|
||||
iCloudAsset: true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
var req = MultipartRequest(
|
||||
'POST',
|
||||
Uri.parse('$savedEndpoint/asset/upload'),
|
||||
onProgress: ((bytes, totalBytes) =>
|
||||
uploadProgressCb(bytes, totalBytes)),
|
||||
);
|
||||
req.headers["x-immich-user-token"] = Store.get(StoreKey.accessToken);
|
||||
req.headers["Transfer-Encoding"] = "chunked";
|
||||
final files = [];
|
||||
// TODO: This is silly to have to load the file just to access the path
|
||||
// But there doesn't seem to be any other way to do it
|
||||
final fileName = (await entity.originFile)?.path;
|
||||
files.add(fileName);
|
||||
|
||||
req.fields['deviceAssetId'] = entity.id;
|
||||
req.fields['deviceId'] = deviceId;
|
||||
req.fields['fileCreatedAt'] =
|
||||
entity.createDateTime.toUtc().toIso8601String();
|
||||
req.fields['fileModifiedAt'] =
|
||||
entity.modifiedDateTime.toUtc().toIso8601String();
|
||||
req.fields['isFavorite'] = entity.isFavorite.toString();
|
||||
req.fields['duration'] = entity.videoDuration.toString();
|
||||
if (entity.isLivePhoto) {
|
||||
final livePhotoFileName = (await entity.originFileWithSubtype)?.path;
|
||||
if (livePhotoFileName != null) {
|
||||
files.add(livePhotoFileName);
|
||||
}
|
||||
}
|
||||
|
||||
req.files.add(assetRawUploadData);
|
||||
final url = '$savedEndpoint/asset/upload';
|
||||
final headers = {
|
||||
'x-immich-user-token': Store.get(StoreKey.accessToken),
|
||||
'Transfer-Encoding': 'chunked',
|
||||
};
|
||||
|
||||
var fileSize = file.lengthSync();
|
||||
final fields = {
|
||||
'deviceAssetId': entity.id,
|
||||
'deviceId': deviceId,
|
||||
'fileCreatedAt': entity.createDateTime.toUtc().toIso8601String(),
|
||||
'fileModifiedAt': entity.modifiedDateTime.toUtc().toIso8601String(),
|
||||
'isFavorite': entity.isFavorite.toString(),
|
||||
'duration': entity.videoDuration.toString(),
|
||||
};
|
||||
|
||||
if (entity.isLivePhoto) {
|
||||
if (livePhotoFile != null) {
|
||||
final livePhotoTitle = p.setExtension(
|
||||
originalFileName,
|
||||
p.extension(livePhotoFile.path),
|
||||
);
|
||||
final fileStream = livePhotoFile.openRead();
|
||||
final livePhotoRawUploadData = http.MultipartFile(
|
||||
"livePhotoData",
|
||||
fileStream,
|
||||
livePhotoFile.lengthSync(),
|
||||
filename: livePhotoTitle,
|
||||
);
|
||||
req.files.add(livePhotoRawUploadData);
|
||||
fileSize += livePhotoFile.lengthSync();
|
||||
} else {
|
||||
_log.warning(
|
||||
"Failed to obtain motion part of the livePhoto - $originalFileName",
|
||||
);
|
||||
}
|
||||
}
|
||||
if (files.length == 1) {
|
||||
final String file = files.first;
|
||||
final split = file.split('/');
|
||||
final name = split.last;
|
||||
final directory = split.take(split.length - 1).join('/');
|
||||
|
||||
setCurrentUploadAssetCb(
|
||||
CurrentUploadAsset(
|
||||
id: entity.id,
|
||||
fileCreatedAt: entity.createDateTime.year == 1970
|
||||
? entity.modifiedDateTime
|
||||
: entity.createDateTime,
|
||||
fileName: originalFileName,
|
||||
fileType: _getAssetType(entity.type),
|
||||
fileSize: fileSize,
|
||||
iCloudAsset: false,
|
||||
),
|
||||
);
|
||||
final task = UploadTask(
|
||||
url: url,
|
||||
group: 'backup',
|
||||
fileField: 'assetData',
|
||||
taskId: entity.id,
|
||||
fields: fields,
|
||||
headers: headers,
|
||||
updates: Updates.statusAndProgress,
|
||||
retries: 0,
|
||||
httpRequestMethod: 'POST',
|
||||
displayName: 'Immich',
|
||||
filename: name,
|
||||
directory: directory,
|
||||
baseDirectory: BaseDirectory.root,
|
||||
);
|
||||
tasks.add(task);
|
||||
} else {
|
||||
final task = MultiUploadTask(
|
||||
url: url,
|
||||
files: files,
|
||||
headers: headers,
|
||||
fields: fields,
|
||||
updates: Updates.statusAndProgress,
|
||||
group: 'backup',
|
||||
taskId: entity.id,
|
||||
retries: 0,
|
||||
displayName: 'Immich',
|
||||
httpRequestMethod: 'POST',
|
||||
baseDirectory: BaseDirectory.root,
|
||||
);
|
||||
|
||||
var response =
|
||||
await httpClient.send(req, cancellationToken: cancelToken);
|
||||
print('created task $task for files $files');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
tasks.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
final permission = await _fileDownloader.permissions
|
||||
.status(PermissionType.androidSharedStorage);
|
||||
print('has permission $permission');
|
||||
|
||||
if (tasks.length == 1) {
|
||||
final result = await _fileDownloader.upload(
|
||||
tasks.first,
|
||||
onProgress: (percent) => print('${percent * 100} done'),
|
||||
onStatus: (status) => print('status $status'),
|
||||
onElapsedTime: (t) => print('time is $t'),
|
||||
elapsedTimeInterval: const Duration(seconds: 1),
|
||||
);
|
||||
|
||||
print('$result is done with ${result.status}');
|
||||
print('result ${result.responseBody}');
|
||||
print('result ${result.responseHeaders}');
|
||||
} else {
|
||||
final result = await _fileDownloader.uploadBatch(
|
||||
tasks,
|
||||
batchProgressCallback: (succeeded, failed) =>
|
||||
print('$succeeded succeeded, $failed failed'),
|
||||
taskStatusCallback: (status) => print('status $status'),
|
||||
taskProgressCallback: (update) => print('update $update'),
|
||||
onElapsedTime: (t) => print('time is $t'),
|
||||
elapsedTimeInterval: const Duration(seconds: 1),
|
||||
);
|
||||
|
||||
print(
|
||||
'$result is done with ${result.succeeded.length} succeeded and ${result.failed.length} failed',
|
||||
);
|
||||
|
||||
for (final task in result.succeeded) {
|
||||
final r = result.results[task];
|
||||
print('successful task $task with result $r');
|
||||
}
|
||||
|
||||
for (final task in result.failed) {
|
||||
final r = result.results[task];
|
||||
print('failed task $task with result $r');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (result.status == 200) {
|
||||
// asset is a duplicate (already exists on the server)
|
||||
duplicatedAssetIds.add(entity.id);
|
||||
uploadSuccessCb(entity.id, deviceId, true);
|
||||
|
@ -409,6 +436,7 @@ class BackupService {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (duplicatedAssetIds.isNotEmpty) {
|
||||
await _saveDuplicatedAssetIds(duplicatedAssetIds);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ dependencies:
|
|||
octo_image: ^2.0.0
|
||||
thumbhash: 0.1.0+1
|
||||
async: ^2.11.0
|
||||
background_downloader: ^8.0.0
|
||||
|
||||
openapi:
|
||||
path: openapi
|
||||
|
@ -82,6 +83,7 @@ dependency_overrides:
|
|||
#f url: https://github.com/Zverik/flutter-geolocator.git
|
||||
#f ref: floss
|
||||
#f path: geolocator_android
|
||||
http: ^1.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -17,4 +17,9 @@
|
|||
{value}
|
||||
on:input={(e) => (updatedValue = e.currentTarget.value)}
|
||||
on:blur={() => (value = updatedValue)}
|
||||
on:keydown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
value = updatedValue;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
Loading…
Reference in a new issue