mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
wip: add platform channels
This commit is contained in:
parent
f1dcfbc594
commit
37b15869d5
@ -1,5 +1,15 @@
|
||||
package com.alextran.immich
|
||||
|
||||
import ImmichHostService
|
||||
import com.alextran.immich.platform.ImmichHostServiceImpl
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
|
||||
class MainActivity: FlutterActivity()
|
||||
class MainActivity: FlutterActivity() {
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
// Register piegon handler
|
||||
ImmichHostService.setUp(flutterEngine.dartExecutor.binaryMessenger, ImmichHostServiceImpl())
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
package com.alextran.immich.platform
|
||||
|
||||
import ImmichHostService
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.FileInputStream
|
||||
import java.security.MessageDigest
|
||||
|
||||
class ImmichHostServiceImpl: ImmichHostService {
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
override fun digestFiles(paths: List<String>, callback: (Result<List<ByteArray?>?>) -> Unit) {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
val buf = ByteArray(Companion.BUFFER_SIZE)
|
||||
val digest: MessageDigest = MessageDigest.getInstance("SHA-1")
|
||||
val hashes = arrayOfNulls<ByteArray>(paths.size)
|
||||
for (i in paths.indices) {
|
||||
val path = paths[i]
|
||||
var len = 0
|
||||
try {
|
||||
val file = FileInputStream(path)
|
||||
file.use { assetFile ->
|
||||
while (true) {
|
||||
len = assetFile.read(buf)
|
||||
if (len != Companion.BUFFER_SIZE) break
|
||||
digest.update(buf)
|
||||
}
|
||||
}
|
||||
digest.update(buf, 0, len)
|
||||
hashes[i] = digest.digest()
|
||||
} catch (e: Exception) {
|
||||
// skip this file
|
||||
Log.w(TAG, "Failed to hash file ${paths[i]}: $e")
|
||||
}
|
||||
}
|
||||
callback(Result.success(hashes.asList()))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BUFFER_SIZE = 2 * 1024 * 1024;
|
||||
private const val TAG = "ImmichHostServiceImpl"
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '12.0'
|
||||
platform :ios, '13.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
@ -83,6 +83,6 @@ SPEC CHECKSUMS:
|
||||
sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b
|
||||
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
|
||||
|
||||
PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d
|
||||
PODFILE CHECKSUM: 47bc0bc2c8210ec5b4886fa2f4d1046a536e3e17
|
||||
|
||||
COCOAPODS: 1.15.2
|
||||
|
@ -15,6 +15,8 @@
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
B2FE78A32C9633490065752A /* Messages.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2FE78A02C9633490065752A /* Messages.g.swift */; };
|
||||
B2FE78A42C9633490065752A /* MessagesImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2FE78A12C9633490065752A /* MessagesImpl.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -60,6 +62,8 @@
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
B0875BFC00218C7E86E76B26 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
B2FE78A02C9633490065752A /* Messages.g.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Messages.g.swift; sourceTree = "<group>"; };
|
||||
B2FE78A12C9633490065752A /* MessagesImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagesImpl.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -81,7 +85,6 @@
|
||||
5743DC0B43F97DC290E40819 /* Pods-Runner.release.xcconfig */,
|
||||
B0875BFC00218C7E86E76B26 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@ -136,6 +139,7 @@
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B2FE78A22C9633490065752A /* Platform */,
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
@ -148,6 +152,15 @@
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B2FE78A22C9633490065752A /* Platform */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B2FE78A02C9633490065752A /* Messages.g.swift */,
|
||||
B2FE78A12C9633490065752A /* MessagesImpl.swift */,
|
||||
);
|
||||
path = Platform;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -197,7 +210,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1510;
|
||||
LastUpgradeCheck = 1540;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
@ -336,8 +349,10 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B2FE78A32C9633490065752A /* Messages.g.swift in Sources */,
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
B2FE78A42C9633490065752A /* MessagesImpl.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -395,6 +410,7 @@
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
@ -425,12 +441,12 @@
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
baseConfigurationReference = B0875BFC00218C7E86E76B26 /* Pods-Runner.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
DEVELOPMENT_TEAM = 7AM53GU2W3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "immich-v2";
|
||||
@ -498,6 +514,7 @@
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB31CF90195004384FC /* Generated.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
@ -520,6 +537,7 @@
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
@ -577,6 +595,7 @@
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
@ -609,12 +628,12 @@
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
baseConfigurationReference = 2DB7C9F14E5C41B0C29A9694 /* Pods-Runner.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
DEVELOPMENT_TEAM = 7AM53GU2W3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "immich-v2";
|
||||
@ -636,12 +655,12 @@
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
baseConfigurationReference = 5743DC0B43F97DC290E40819 /* Pods-Runner.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
DEVELOPMENT_TEAM = 7AM53GU2W3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "immich-v2";
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
LastUpgradeVersion = "1540"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -8,6 +8,11 @@ import Flutter
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
|
||||
// Register piegon handler
|
||||
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
|
||||
ImmichHostServiceSetup.setUp(binaryMessenger: controller.binaryMessenger, api: ImmichHostServiceImpl())
|
||||
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
|
39
mobile-v2/ios/Runner/Platform/MessagesImpl.swift
Normal file
39
mobile-v2/ios/Runner/Platform/MessagesImpl.swift
Normal file
@ -0,0 +1,39 @@
|
||||
import CryptoKit
|
||||
|
||||
class ImmichHostServiceImpl: ImmichHostService {
|
||||
func digestFiles(paths: [String], completion: @escaping (Result<[FlutterStandardTypedData?]?, Error>) -> Void) {
|
||||
let bufsize = 2 * 1024 * 1024
|
||||
// Private error to throw if file cannot be read
|
||||
enum DigestError: String, LocalizedError {
|
||||
case NoFileHandle = "Cannot Open File Handle"
|
||||
|
||||
public var errorDescription: String? { self.rawValue }
|
||||
}
|
||||
|
||||
// Compute hash in background thread
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
var hashes: [FlutterStandardTypedData?] = Array(repeating: nil, count: paths.count)
|
||||
for i in (0 ..< paths.count) {
|
||||
do {
|
||||
guard let file = FileHandle(forReadingAtPath: paths[i]) else { throw DigestError.NoFileHandle }
|
||||
var hasher = Insecure.SHA1.init();
|
||||
while autoreleasepool(invoking: {
|
||||
let chunk = file.readData(ofLength: bufsize)
|
||||
guard !chunk.isEmpty else { return false } // EOF
|
||||
hasher.update(data: chunk)
|
||||
return true // continue
|
||||
}) { }
|
||||
let digest = hasher.finalize()
|
||||
hashes[i] = FlutterStandardTypedData(bytes: Data(Array(digest.makeIterator())))
|
||||
} catch {
|
||||
print("Cannot calculate the digest of the file \(paths[i]) due to \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
// Return result in main thread
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(Array(hashes)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
mobile-v2/lib/platform/messages.dart
Normal file
17
mobile-v2/lib/platform/messages.dart
Normal file
@ -0,0 +1,17 @@
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:pigeon/pigeon.dart';
|
||||
|
||||
@ConfigurePigeon(PigeonOptions(
|
||||
dartOut: 'lib/platform/messages.g.dart',
|
||||
dartOptions: DartOptions(),
|
||||
kotlinOut:
|
||||
'android/app/src/main/kotlin/com/alextran/immich/platform/Messages.g.kt',
|
||||
kotlinOptions: KotlinOptions(),
|
||||
swiftOut: 'ios/Runner/Platform/Messages.g.swift',
|
||||
swiftOptions: SwiftOptions(),
|
||||
))
|
||||
@HostApi()
|
||||
abstract class ImmichHostService {
|
||||
@async
|
||||
List<Uint8List?>? digestFiles(List<String> paths);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user