restore xcode settings

formatting

restore xcode settings

fix rebase
This commit is contained in:
mertalev 2025-07-24 14:25:25 +03:00
parent fc6415cdc3
commit 97a6c6d7a0
No known key found for this signature in database
GPG Key ID: DF6ABC77AAD98C95
18 changed files with 255 additions and 908 deletions

View File

@ -24,7 +24,6 @@
FAC6F89B2D287C890078CB2F /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = FAC6F8902D287C890078CB2F /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; FAC6F89B2D287C890078CB2F /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = FAC6F8902D287C890078CB2F /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
FAC6F8B72D287F120078CB2F /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6F8B52D287F120078CB2F /* ShareViewController.swift */; }; FAC6F8B72D287F120078CB2F /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6F8B52D287F120078CB2F /* ShareViewController.swift */; };
FAC6F8B92D287F120078CB2F /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FAC6F8B32D287F120078CB2F /* MainInterface.storyboard */; }; FAC6F8B92D287F120078CB2F /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FAC6F8B32D287F120078CB2F /* MainInterface.storyboard */; };
FE1BEAC92E264F8400D7F138 /* Thumbhash.swift in Resources */ = {isa = PBXBuildFile; fileRef = FE1BEAC82E264F8400D7F138 /* Thumbhash.swift */; };
FED3B1962E253E9B0030FD97 /* ThumbnailsImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED3B1942E253E9B0030FD97 /* ThumbnailsImpl.swift */; }; FED3B1962E253E9B0030FD97 /* ThumbnailsImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED3B1942E253E9B0030FD97 /* ThumbnailsImpl.swift */; };
FED3B1972E253E9B0030FD97 /* Thumbnails.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED3B1932E253E9B0030FD97 /* Thumbnails.g.swift */; }; FED3B1972E253E9B0030FD97 /* Thumbnails.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED3B1932E253E9B0030FD97 /* Thumbnails.g.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -47,6 +46,16 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */ = { FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase; isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -95,8 +104,6 @@
FAC6F8B42D287F120078CB2F /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = "<group>"; }; FAC6F8B42D287F120078CB2F /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = "<group>"; };
FAC6F8B52D287F120078CB2F /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; }; FAC6F8B52D287F120078CB2F /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = "<group>"; }; FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = "<group>"; };
FE1BEAC82E264F8400D7F138 /* Thumbhash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbhash.swift; sourceTree = "<group>"; };
FED3B1472E253B110030FD97 /* Flutter.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = ../../../Flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework; sourceTree = "<group>"; };
FED3B1932E253E9B0030FD97 /* Thumbnails.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbnails.g.swift; sourceTree = "<group>"; }; FED3B1932E253E9B0030FD97 /* Thumbnails.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbnails.g.swift; sourceTree = "<group>"; };
FED3B1942E253E9B0030FD97 /* ThumbnailsImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailsImpl.swift; sourceTree = "<group>"; }; FED3B1942E253E9B0030FD97 /* ThumbnailsImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailsImpl.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -114,6 +121,8 @@
/* Begin PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFileSystemSynchronizedRootGroup section */
B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = { B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = {
isa = PBXFileSystemSynchronizedRootGroup; isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
);
path = Sync; path = Sync;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -172,7 +181,6 @@
1754452DD81DA6620E279E51 /* Frameworks */ = { 1754452DD81DA6620E279E51 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FED3B1472E253B110030FD97 /* Flutter.xcframework */,
886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */, 886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */,
357FC57E54FD0F51795CF28A /* Pods_ShareExtension.framework */, 357FC57E54FD0F51795CF28A /* Pods_ShareExtension.framework */,
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */, F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */,
@ -258,7 +266,6 @@
FED3B1952E253E9B0030FD97 /* Images */ = { FED3B1952E253E9B0030FD97 /* Images */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FE1BEAC82E264F8400D7F138 /* Thumbhash.swift */,
FED3B1932E253E9B0030FD97 /* Thumbnails.g.swift */, FED3B1932E253E9B0030FD97 /* Thumbnails.g.swift */,
FED3B1942E253E9B0030FD97 /* ThumbnailsImpl.swift */, FED3B1942E253E9B0030FD97 /* ThumbnailsImpl.swift */,
); );
@ -277,6 +284,7 @@
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */, FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
D218A34AEE62BC1EF119F5B0 /* [CP] Embed Pods Frameworks */, D218A34AEE62BC1EF119F5B0 /* [CP] Embed Pods Frameworks */,
@ -385,7 +393,6 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
FE1BEAC92E264F8400D7F138 /* Thumbhash.swift in Resources */,
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
@ -660,7 +667,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0; IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@ -669,7 +676,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.121.0; MARKETING_VERSION = 1.121.0;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.profile; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile;
PRODUCT_NAME = "Immich-Profile"; PRODUCT_NAME = "Immich-Profile";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -804,7 +811,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0; IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@ -813,7 +820,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.121.0; MARKETING_VERSION = 1.121.0;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.vdebug; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug;
PRODUCT_NAME = "Immich-Debug"; PRODUCT_NAME = "Immich-Debug";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -834,7 +841,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0; IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@ -843,7 +850,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.121.0; MARKETING_VERSION = 1.121.0;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich;
PRODUCT_NAME = Immich; PRODUCT_NAME = Immich;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@ -867,7 +874,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -884,7 +891,7 @@
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.vdebug.Widget; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug.Widget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
@ -910,7 +917,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -926,7 +933,7 @@
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.Widget; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.Widget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
@ -950,7 +957,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -966,7 +973,7 @@
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.profile.Widget; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile.Widget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
@ -990,7 +997,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -1007,7 +1014,7 @@
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.vdebug.ShareExtension; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -1034,7 +1041,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -1050,7 +1057,7 @@
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.ShareExtension; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
@ -1075,7 +1082,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 213; CURRENT_PROJECT_VERSION = 213;
CUSTOM_GROUP_ID = group.app.immich.share; CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 33MF3D8ZGA; DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -1091,7 +1098,7 @@
LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.mertalev.immich.profile.ShareExtension; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;

View File

@ -1,649 +0,0 @@
import Foundation
// NOTE: Swift has an exponential-time type checker and compiling very simple
// expressions can easily take many seconds, especially when expressions involve
// numeric type constructors.
//
// This file deliberately breaks compound expressions up into separate variables
// to improve compile time even though this comes at the expense of readability.
// This is a known workaround for this deficiency in the Swift compiler.
//
// The following command is helpful when debugging Swift compile time issues:
//
// swiftc ThumbHash.swift -Xfrontend -debug-time-function-bodies
//
// These optimizations brought the compile time for this file from around 2.5
// seconds to around 250ms (10x faster).
// NOTE: Swift's debug-build performance of for-in loops over numeric ranges is
// really awful. Debug builds compile a very generic indexing iterator thing
// that makes many nested calls for every iteration, which makes debug-build
// performance crawl.
//
// This file deliberately avoids for-in loops that loop for more than a few
// times to improve debug-build run time even though this comes at the expense
// of readability. Similarly unsafe pointers are used instead of array getters
// to avoid unnecessary bounds checks, which have extra overhead in debug builds.
//
// These optimizations brought the run time to encode and decode 10 ThumbHashes
// in debug mode from 700ms to 70ms (10x faster).
func rgbaToThumbHash(w: Int, h: Int, rgba: Data) -> Data {
// Encoding an image larger than 100x100 is slow with no benefit
assert(w <= 100 && h <= 100)
assert(rgba.count == w * h * 4)
// Determine the average color
var avg_r: Float32 = 0
var avg_g: Float32 = 0
var avg_b: Float32 = 0
var avg_a: Float32 = 0
rgba.withUnsafeBytes { rgba in
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
let n = w * h
var i = 0
while i < n {
let alpha = Float32(rgba[3]) / 255
avg_r += alpha / 255 * Float32(rgba[0])
avg_g += alpha / 255 * Float32(rgba[1])
avg_b += alpha / 255 * Float32(rgba[2])
avg_a += alpha
rgba = rgba.advanced(by: 4)
i += 1
}
}
if avg_a > 0 {
avg_r /= avg_a
avg_g /= avg_a
avg_b /= avg_a
}
let hasAlpha = avg_a < Float32(w * h)
let l_limit = hasAlpha ? 5 : 7 // Use fewer luminance bits if there's alpha
let imax_wh = max(w, h)
let iwl_limit = l_limit * w
let ihl_limit = l_limit * h
let fmax_wh = Float32(imax_wh)
let fwl_limit = Float32(iwl_limit)
let fhl_limit = Float32(ihl_limit)
let flx = round(fwl_limit / fmax_wh)
let fly = round(fhl_limit / fmax_wh)
var lx = Int(flx)
var ly = Int(fly)
lx = max(1, lx)
ly = max(1, ly)
var lpqa = [Float32](repeating: 0, count: w * h * 4)
// Convert the image from RGBA to LPQA (composite atop the average color)
rgba.withUnsafeBytes { rgba in
lpqa.withUnsafeMutableBytes { lpqa in
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
var lpqa = lpqa.baseAddress!.bindMemory(to: Float32.self, capacity: lpqa.count)
let n = w * h
var i = 0
while i < n {
let alpha = Float32(rgba[3]) / 255
let r = avg_r * (1 - alpha) + alpha / 255 * Float32(rgba[0])
let g = avg_g * (1 - alpha) + alpha / 255 * Float32(rgba[1])
let b = avg_b * (1 - alpha) + alpha / 255 * Float32(rgba[2])
lpqa[0] = (r + g + b) / 3
lpqa[1] = (r + g) / 2 - b
lpqa[2] = r - g
lpqa[3] = alpha
rgba = rgba.advanced(by: 4)
lpqa = lpqa.advanced(by: 4)
i += 1
}
}
}
// Encode using the DCT into DC (constant) and normalized AC (varying) terms
let encodeChannel = { (channel: UnsafePointer<Float32>, nx: Int, ny: Int) -> (Float32, [Float32], Float32) in
var dc: Float32 = 0
var ac: [Float32] = []
var scale: Float32 = 0
var fx = [Float32](repeating: 0, count: w)
fx.withUnsafeMutableBytes { fx in
let fx = fx.baseAddress!.bindMemory(to: Float32.self, capacity: fx.count)
var cy = 0
while cy < ny {
var cx = 0
while cx * ny < nx * (ny - cy) {
var ptr = channel
var f: Float32 = 0
var x = 0
while x < w {
let fw = Float32(w)
let fxx = Float32(x)
let fcx = Float32(cx)
fx[x] = cos(Float32.pi / fw * fcx * (fxx + 0.5))
x += 1
}
var y = 0
while y < h {
let fh = Float32(h)
let fyy = Float32(y)
let fcy = Float32(cy)
let fy = cos(Float32.pi / fh * fcy * (fyy + 0.5))
var x = 0
while x < w {
f += ptr.pointee * fx[x] * fy
x += 1
ptr = ptr.advanced(by: 4)
}
y += 1
}
f /= Float32(w * h)
if cx > 0 || cy > 0 {
ac.append(f)
scale = max(scale, abs(f))
} else {
dc = f
}
cx += 1
}
cy += 1
}
}
if scale > 0 {
let n = ac.count
var i = 0
while i < n {
ac[i] = 0.5 + 0.5 / scale * ac[i]
i += 1
}
}
return (dc, ac, scale)
}
let (
(l_dc, l_ac, l_scale),
(p_dc, p_ac, p_scale),
(q_dc, q_ac, q_scale),
(a_dc, a_ac, a_scale)
) = lpqa.withUnsafeBytes { lpqa in
let lpqa = lpqa.baseAddress!.bindMemory(to: Float32.self, capacity: lpqa.count)
return (
encodeChannel(lpqa, max(3, lx), max(3, ly)),
encodeChannel(lpqa.advanced(by: 1), 3, 3),
encodeChannel(lpqa.advanced(by: 2), 3, 3),
hasAlpha ? encodeChannel(lpqa.advanced(by: 3), 5, 5) : (1, [], 1)
)
}
// Write the constants
let isLandscape = w > h
let fl_dc = round(63.0 * l_dc)
let fp_dc = round(31.5 + 31.5 * p_dc)
let fq_dc = round(31.5 + 31.5 * q_dc)
let fl_scale = round(31.0 * l_scale)
let il_dc = UInt32(fl_dc)
let ip_dc = UInt32(fp_dc)
let iq_dc = UInt32(fq_dc)
let il_scale = UInt32(fl_scale)
let ihasAlpha = UInt32(hasAlpha ? 1 : 0)
let header24 = il_dc | (ip_dc << 6) | (iq_dc << 12) | (il_scale << 18) | (ihasAlpha << 23)
let fp_scale = round(63.0 * p_scale)
let fq_scale = round(63.0 * q_scale)
let ilxy = UInt16(isLandscape ? ly : lx)
let ip_scale = UInt16(fp_scale)
let iq_scale = UInt16(fq_scale)
let iisLandscape = UInt16(isLandscape ? 1 : 0)
let header16 = ilxy | (ip_scale << 3) | (iq_scale << 9) | (iisLandscape << 15)
var hash = Data(capacity: 25)
hash.append(UInt8(header24 & 255))
hash.append(UInt8((header24 >> 8) & 255))
hash.append(UInt8(header24 >> 16))
hash.append(UInt8(header16 & 255))
hash.append(UInt8(header16 >> 8))
var isOdd = false
if hasAlpha {
let fa_dc = round(15.0 * a_dc)
let fa_scale = round(15.0 * a_scale)
let ia_dc = UInt8(fa_dc)
let ia_scale = UInt8(fa_scale)
hash.append(ia_dc | (ia_scale << 4))
}
// Write the varying factors
for ac in [l_ac, p_ac, q_ac] {
for f in ac {
let f15 = round(15.0 * f)
let i15 = UInt8(f15)
if isOdd {
hash[hash.count - 1] |= i15 << 4
} else {
hash.append(i15)
}
isOdd = !isOdd
}
}
if hasAlpha {
for f in a_ac {
let f15 = round(15.0 * f)
let i15 = UInt8(f15)
if isOdd {
hash[hash.count - 1] |= i15 << 4
} else {
hash.append(i15)
}
isOdd = !isOdd
}
}
return hash
}
func thumbHashToRGBA(hash: Data) -> (Int, Int, Data) {
// Read the constants
let h0 = UInt32(hash[0])
let h1 = UInt32(hash[1])
let h2 = UInt32(hash[2])
let h3 = UInt16(hash[3])
let h4 = UInt16(hash[4])
let header24 = h0 | (h1 << 8) | (h2 << 16)
let header16 = h3 | (h4 << 8)
let il_dc = header24 & 63
let ip_dc = (header24 >> 6) & 63
let iq_dc = (header24 >> 12) & 63
var l_dc = Float32(il_dc)
var p_dc = Float32(ip_dc)
var q_dc = Float32(iq_dc)
l_dc = l_dc / 63
p_dc = p_dc / 31.5 - 1
q_dc = q_dc / 31.5 - 1
let il_scale = (header24 >> 18) & 31
var l_scale = Float32(il_scale)
l_scale = l_scale / 31
let hasAlpha = (header24 >> 23) != 0
let ip_scale = (header16 >> 3) & 63
let iq_scale = (header16 >> 9) & 63
var p_scale = Float32(ip_scale)
var q_scale = Float32(iq_scale)
p_scale = p_scale / 63
q_scale = q_scale / 63
let isLandscape = (header16 >> 15) != 0
let lx16 = max(3, isLandscape ? hasAlpha ? 5 : 7 : header16 & 7)
let ly16 = max(3, isLandscape ? header16 & 7 : hasAlpha ? 5 : 7)
let lx = Int(lx16)
let ly = Int(ly16)
var a_dc = Float32(1)
var a_scale = Float32(1)
if hasAlpha {
let ia_dc = hash[5] & 15
let ia_scale = hash[5] >> 4
a_dc = Float32(ia_dc)
a_scale = Float32(ia_scale)
a_dc /= 15
a_scale /= 15
}
// Read the varying factors (boost saturation by 1.25x to compensate for quantization)
let ac_start = hasAlpha ? 6 : 5
var ac_index = 0
let decodeChannel = { (nx: Int, ny: Int, scale: Float32) -> [Float32] in
var ac: [Float32] = []
for cy in 0 ..< ny {
var cx = cy > 0 ? 0 : 1
while cx * ny < nx * (ny - cy) {
let iac = (hash[ac_start + (ac_index >> 1)] >> ((ac_index & 1) << 2)) & 15;
var fac = Float32(iac)
fac = (fac / 7.5 - 1) * scale
ac.append(fac)
ac_index += 1
cx += 1
}
}
return ac
}
let l_ac = decodeChannel(lx, ly, l_scale)
let p_ac = decodeChannel(3, 3, p_scale * 1.25)
let q_ac = decodeChannel(3, 3, q_scale * 1.25)
let a_ac = hasAlpha ? decodeChannel(5, 5, a_scale) : []
// Decode using the DCT into RGB
let ratio = thumbHashToApproximateAspectRatio(hash: hash)
let fw = round(ratio > 1 ? 32 : 32 * ratio)
let fh = round(ratio > 1 ? 32 / ratio : 32)
let w = Int(fw)
let h = Int(fh)
var rgba = Data(count: w * h * 4)
let cx_stop = max(lx, hasAlpha ? 5 : 3)
let cy_stop = max(ly, hasAlpha ? 5 : 3)
var fx = [Float32](repeating: 0, count: cx_stop)
var fy = [Float32](repeating: 0, count: cy_stop)
fx.withUnsafeMutableBytes { fx in
let fx = fx.baseAddress!.bindMemory(to: Float32.self, capacity: fx.count)
fy.withUnsafeMutableBytes { fy in
let fy = fy.baseAddress!.bindMemory(to: Float32.self, capacity: fy.count)
rgba.withUnsafeMutableBytes { rgba in
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
var y = 0
while y < h {
var x = 0
while x < w {
var l = l_dc
var p = p_dc
var q = q_dc
var a = a_dc
// Precompute the coefficients
var cx = 0
while cx < cx_stop {
let fw = Float32(w)
let fxx = Float32(x)
let fcx = Float32(cx)
fx[cx] = cos(Float32.pi / fw * (fxx + 0.5) * fcx)
cx += 1
}
var cy = 0
while cy < cy_stop {
let fh = Float32(h)
let fyy = Float32(y)
let fcy = Float32(cy)
fy[cy] = cos(Float32.pi / fh * (fyy + 0.5) * fcy)
cy += 1
}
// Decode L
var j = 0
cy = 0
while cy < ly {
var cx = cy > 0 ? 0 : 1
let fy2 = fy[cy] * 2
while cx * ly < lx * (ly - cy) {
l += l_ac[j] * fx[cx] * fy2
j += 1
cx += 1
}
cy += 1
}
// Decode P and Q
j = 0
cy = 0
while cy < 3 {
var cx = cy > 0 ? 0 : 1
let fy2 = fy[cy] * 2
while cx < 3 - cy {
let f = fx[cx] * fy2
p += p_ac[j] * f
q += q_ac[j] * f
j += 1
cx += 1
}
cy += 1
}
// Decode A
if hasAlpha {
j = 0
cy = 0
while cy < 5 {
var cx = cy > 0 ? 0 : 1
let fy2 = fy[cy] * 2
while cx < 5 - cy {
a += a_ac[j] * fx[cx] * fy2
j += 1
cx += 1
}
cy += 1
}
}
// Convert to RGB
var b = l - 2 / 3 * p
var r = (3 * l - b + q) / 2
var g = r - q
r = max(0, 255 * min(1, r))
g = max(0, 255 * min(1, g))
b = max(0, 255 * min(1, b))
a = max(0, 255 * min(1, a))
rgba[0] = UInt8(r)
rgba[1] = UInt8(g)
rgba[2] = UInt8(b)
rgba[3] = UInt8(a)
rgba = rgba.advanced(by: 4)
x += 1
}
y += 1
}
}
}
}
return (w, h, rgba)
}
func thumbHashToAverageRGBA(hash: Data) -> (Float32, Float32, Float32, Float32) {
let h0 = UInt32(hash[0])
let h1 = UInt32(hash[1])
let h2 = UInt32(hash[2])
let header = h0 | (h1 << 8) | (h2 << 16)
let il = header & 63
let ip = (header >> 6) & 63
let iq = (header >> 12) & 63
var l = Float32(il)
var p = Float32(ip)
var q = Float32(iq)
l = l / 63
p = p / 31.5 - 1
q = q / 31.5 - 1
let hasAlpha = (header >> 23) != 0
var a = Float32(1)
if hasAlpha {
let ia = hash[5] & 15
a = Float32(ia)
a = a / 15
}
let b = l - 2 / 3 * p
let r = (3 * l - b + q) / 2
let g = r - q
return (
max(0, min(1, r)),
max(0, min(1, g)),
max(0, min(1, b)),
a
)
}
func thumbHashToApproximateAspectRatio(hash: Data) -> Float32 {
let header = hash[3]
let hasAlpha = (hash[2] & 0x80) != 0
let isLandscape = (hash[4] & 0x80) != 0
let lx = isLandscape ? hasAlpha ? 5 : 7 : header & 7
let ly = isLandscape ? header & 7 : hasAlpha ? 5 : 7
return Float32(lx) / Float32(ly)
}
#if os(macOS)
import Cocoa
func imageToThumbHash(image: NSImage) -> Data {
let size = image.size
let fw = round(100 * size.width / max(size.width, size.height))
let fh = round(100 * size.height / max(size.width, size.height))
let w = Int(fw)
let h = Int(fh)
var rgba = Data(count: w * h * 4)
rgba.withUnsafeMutableBytes { rgba in
var rect = NSRect(x: 0, y: 0, width: w, height: h)
if
let cgImage = image.cgImage(forProposedRect: &rect, context: nil, hints: nil),
let space = (image.representations[0] as? NSBitmapImageRep)?.colorSpace.cgColorSpace,
let context = CGContext(
data: rgba.baseAddress,
width: w,
height: h,
bitsPerComponent: 8,
bytesPerRow: w * 4,
space: space,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
)
{
context.draw(cgImage, in: rect)
// Convert from premultiplied alpha to unpremultiplied alpha
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
let n = w * h
var i = 0
while i < n {
let a = UInt16(rgba[3])
if a > 0 && a < 255 {
var r = UInt16(rgba[0])
var g = UInt16(rgba[1])
var b = UInt16(rgba[2])
r = min(255, r * 255 / a)
g = min(255, g * 255 / a)
b = min(255, b * 255 / a)
rgba[0] = UInt8(r)
rgba[1] = UInt8(g)
rgba[2] = UInt8(b)
}
rgba = rgba.advanced(by: 4)
i += 1
}
}
}
return rgbaToThumbHash(w: w, h: h, rgba: rgba)
}
func thumbHashToImage(hash: Data) -> NSImage {
let (w, h, rgba) = thumbHashToRGBA(hash: hash)
let bitmap = NSBitmapImageRep(
bitmapDataPlanes: nil,
pixelsWide: w,
pixelsHigh: h,
bitsPerSample: 8,
samplesPerPixel: 4,
hasAlpha: true,
isPlanar: false,
colorSpaceName: .deviceRGB,
bytesPerRow: w * 4,
bitsPerPixel: 32
)!
rgba.withUnsafeBytes { rgba in
// Convert from unpremultiplied alpha to premultiplied alpha
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
var to = bitmap.bitmapData!
let n = w * h
var i = 0
while i < n {
let a = rgba[3]
if a == 255 {
to[0] = rgba[0]
to[1] = rgba[1]
to[2] = rgba[2]
} else {
var r = UInt16(rgba[0])
var g = UInt16(rgba[1])
var b = UInt16(rgba[2])
let a = UInt16(a)
r = min(255, r * a / 255)
g = min(255, g * a / 255)
b = min(255, b * a / 255)
to[0] = UInt8(r)
to[1] = UInt8(g)
to[2] = UInt8(b)
}
to[3] = a
rgba = rgba.advanced(by: 4)
to = to.advanced(by: 4)
i += 1
}
}
let image = NSImage(size: NSSize(width: w, height: h))
image.addRepresentation(bitmap)
return image
}
#endif
#if os(iOS)
import UIKit
func imageToThumbHash(image: UIImage) -> Data {
let size = image.size
let w = Int(round(100 * size.width / max(size.width, size.height)))
let h = Int(round(100 * size.height / max(size.width, size.height)))
var rgba = Data(count: w * h * 4)
rgba.withUnsafeMutableBytes { rgba in
if
let space = image.cgImage?.colorSpace,
let context = CGContext(
data: rgba.baseAddress,
width: w,
height: h,
bitsPerComponent: 8,
bytesPerRow: w * 4,
space: space,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
)
{
// EXIF orientation only works if you draw the UIImage, not the CGImage
context.concatenate(CGAffineTransform(1, 0, 0, -1, 0, CGFloat(h)))
UIGraphicsPushContext(context)
image.draw(in: CGRect(x: 0, y: 0, width: w, height: h))
UIGraphicsPopContext()
// Convert from premultiplied alpha to unpremultiplied alpha
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
let n = w * h
var i = 0
while i < n {
let a = UInt16(rgba[3])
if a > 0 && a < 255 {
var r = UInt16(rgba[0])
var g = UInt16(rgba[1])
var b = UInt16(rgba[2])
r = min(255, r * 255 / a)
g = min(255, g * 255 / a)
b = min(255, b * 255 / a)
rgba[0] = UInt8(r)
rgba[1] = UInt8(g)
rgba[2] = UInt8(b)
}
rgba = rgba.advanced(by: 4)
i += 1
}
}
}
return rgbaToThumbHash(w: w, h: h, rgba: rgba)
}
func thumbHashToImage(hash: Data) -> UIImage {
var (w, h, rgba) = thumbHashToRGBA(hash: hash)
rgba.withUnsafeMutableBytes { rgba in
// Convert from unpremultiplied alpha to premultiplied alpha
var rgba = rgba.baseAddress!.bindMemory(to: UInt8.self, capacity: rgba.count)
let n = w * h
var i = 0
while i < n {
let a = UInt16(rgba[3])
if a < 255 {
var r = UInt16(rgba[0])
var g = UInt16(rgba[1])
var b = UInt16(rgba[2])
r = min(255, r * a / 255)
g = min(255, g * a / 255)
b = min(255, b * a / 255)
rgba[0] = UInt8(r)
rgba[1] = UInt8(g)
rgba[2] = UInt8(b)
}
rgba = rgba.advanced(by: 4)
i += 1
}
}
let image = CGImage(
width: w,
height: h,
bitsPerComponent: 8,
bitsPerPixel: 32,
bytesPerRow: w * 4,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGBitmapInfo(rawValue: CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue),
provider: CGDataProvider(data: rgba as CFData)!,
decode: nil,
shouldInterpolate: true,
intent: .perceptual
)
return UIImage(cgImage: image!)
}
#endif

View File

@ -1,187 +1,187 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>AppGroupId</key> <key>AppGroupId</key>
<string>$(CUSTOM_GROUP_ID)</string> <string>$(CUSTOM_GROUP_ID)</string>
<key>BGTaskSchedulerPermittedIdentifiers</key> <key>BGTaskSchedulerPermittedIdentifiers</key>
<array> <array>
<string>app.alextran.immich.backgroundFetch</string> <string>app.alextran.immich.backgroundFetch</string>
<string>app.alextran.immich.backgroundProcessing</string> <string>app.alextran.immich.backgroundProcessing</string>
</array> </array>
<key>CADisableMinimumFrameDurationOnPhone</key> <key>CADisableMinimumFrameDurationOnPhone</key>
<true/> <true />
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string> <string>${PRODUCT_NAME}</string>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
<array> <array>
<dict> <dict>
<key>CFBundleTypeName</key> <key>CFBundleTypeName</key>
<string>ShareHandler</string> <string>ShareHandler</string>
<key>LSHandlerRank</key> <key>LSHandlerRank</key>
<string>Alternate</string> <string>Alternate</string>
<key>LSItemContentTypes</key> <key>LSItemContentTypes</key>
<array> <array>
<string>public.file-url</string> <string>public.file-url</string>
<string>public.image</string> <string>public.image</string>
<string>public.text</string> <string>public.text</string>
<string>public.movie</string> <string>public.movie</string>
<string>public.url</string> <string>public.url</string>
<string>public.data</string> <string>public.data</string>
</array> </array>
</dict> </dict>
</array> </array>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleLocalizations</key> <key>CFBundleLocalizations</key>
<array> <array>
<string>en</string> <string>en</string>
<string>ar</string> <string>ar</string>
<string>ca</string> <string>ca</string>
<string>cs</string> <string>cs</string>
<string>da</string> <string>da</string>
<string>de</string> <string>de</string>
<string>es</string> <string>es</string>
<string>fi</string> <string>fi</string>
<string>fr</string> <string>fr</string>
<string>he</string> <string>he</string>
<string>hi</string> <string>hi</string>
<string>hu</string> <string>hu</string>
<string>it</string> <string>it</string>
<string>ja</string> <string>ja</string>
<string>ko</string> <string>ko</string>
<string>lv</string> <string>lv</string>
<string>mn</string> <string>mn</string>
<string>nb</string> <string>nb</string>
<string>nl</string> <string>nl</string>
<string>pl</string> <string>pl</string>
<string>pt</string> <string>pt</string>
<string>ro</string> <string>ro</string>
<string>ru</string> <string>ru</string>
<string>sk</string> <string>sk</string>
<string>sl</string> <string>sl</string>
<string>sr</string> <string>sr</string>
<string>sv</string> <string>sv</string>
<string>th</string> <string>th</string>
<string>uk</string> <string>uk</string>
<string>vi</string> <string>vi</string>
<string>zh</string> <string>zh</string>
</array> </array>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>immich_mobile</string> <string>immich_mobile</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.137.2</string> <string>1.137.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
<array> <array>
<dict> <dict>
<key>CFBundleTypeRole</key> <key>CFBundleTypeRole</key>
<string>Editor</string> <string>Editor</string>
<key>CFBundleURLName</key> <key>CFBundleURLName</key>
<string>Share Extension</string> <string>Share Extension</string>
<key>CFBundleURLSchemes</key> <key>CFBundleURLSchemes</key>
<array> <array>
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array> </array>
</dict> </dict>
<dict> <dict>
<key>CFBundleTypeRole</key> <key>CFBundleTypeRole</key>
<string>Editor</string> <string>Editor</string>
<key>CFBundleURLName</key> <key>CFBundleURLName</key>
<string>Deep Link</string> <string>Deep Link</string>
<key>CFBundleURLSchemes</key> <key>CFBundleURLSchemes</key>
<array> <array>
<string>immich</string> <string>immich</string>
</array> </array>
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>213</string> <string>213</string>
<key>FLTEnableImpeller</key> <key>FLTEnableImpeller</key>
<true/> <true />
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false />
<key>LSApplicationQueriesSchemes</key> <key>LSApplicationQueriesSchemes</key>
<array> <array>
<string>https</string> <string>https</string>
</array> </array>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true />
<key>LSSupportsOpeningDocumentsInPlace</key> <key>LSSupportsOpeningDocumentsInPlace</key>
<string>No</string> <string>No</string>
<key>MGLMapboxMetricsEnabledSettingShownInApp</key> <key>MGLMapboxMetricsEnabledSettingShownInApp</key>
<true/> <true />
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true />
</dict> </dict>
<key>NSBonjourServices</key> <key>NSBonjourServices</key>
<array> <array>
<string>_googlecast._tcp</string> <string>_googlecast._tcp</string>
<string>_CC1AD845._googlecast._tcp</string> <string>_CC1AD845._googlecast._tcp</string>
</array> </array>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>We need to access the camera to let you take beautiful video using this app</string> <string>We need to access the camera to let you take beautiful video using this app</string>
<key>NSFaceIDUsageDescription</key> <key>NSFaceIDUsageDescription</key>
<string>We need to use FaceID to allow access to your locked folder</string> <string>We need to use FaceID to allow access to your locked folder</string>
<key>NSLocalNetworkUsageDescription</key> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need local network permission to connect to the local server using IP address and <string>We require this permission to access the local WiFi name for background upload mechanism</string>
<key>NSLocationUsageDescription</key>
<string>We require this permission to access the local WiFi name</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We require this permission to access the local WiFi name</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need to access the microphone to let you take beautiful video using this app</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSUserActivityTypes</key>
<array>
<string>INSendMessageIntent</string>
</array>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true />
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIStatusBarHidden</key>
<false />
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true />
<key>io.flutter.embedded_views_preview</key>
<true />
<key>NSLocalNetworkUsageDescription</key>
<string>We need local network permission to connect to the local server using IP address and
allow the casting feature to work</string> allow the casting feature to work</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key> </dict>
<string>We require this permission to access the local WiFi name for background upload mechanism</string>
<key>NSLocationUsageDescription</key>
<string>We require this permission to access the local WiFi name</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We require this permission to access the local WiFi name</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need to access the microphone to let you take beautiful video using this app</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need to manage backup your photos album</string>
<key>NSUserActivityTypes</key>
<array>
<string>INSendMessageIntent</string>
</array>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIStatusBarHidden</key>
<false/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>io.flutter.embedded_views_preview</key>
<true/>
</dict>
</plist> </plist>

View File

@ -9,6 +9,8 @@
<key>com.apple.developer.networking.wifi-info</key> <key>com.apple.developer.networking.wifi-info</key>
<true/> <true/>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array/> <array>
<string>group.app.immich.share</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -11,6 +11,8 @@
<key>com.apple.developer.networking.wifi-info</key> <key>com.apple.developer.networking.wifi-info</key>
<true/> <true/>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array/> <array>
<string>group.app.immich.share</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -3,6 +3,8 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array/> <array>
<string>group.app.immich.share</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -3,6 +3,8 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>
<array/> <array>
<string>group.app.immich.share</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -23,8 +23,7 @@ class AssetMediaRepository {
final actualSize = actualWidth * actualHeight * 4; final actualSize = actualWidth * actualHeight * 4;
try { try {
final buffer = final buffer = await ImmutableBuffer.fromUint8List(pointer.asTypedList(actualSize));
await ImmutableBuffer.fromUint8List(pointer.asTypedList(actualSize));
final descriptor = ui.ImageDescriptor.raw( final descriptor = ui.ImageDescriptor.raw(
buffer, buffer,
width: actualWidth, width: actualWidth,

View File

@ -71,8 +71,7 @@ Future<void> initApp() async {
} }
} }
PaintingBinding.instance.imageCache.maximumSizeBytes = PaintingBinding.instance.imageCache.maximumSizeBytes = kTimelineImageCacheMemory;
kTimelineImageCacheMemory;
await DynamicTheme.fetchSystemPalette(); await DynamicTheme.fetchSystemPalette();

View File

@ -12,6 +12,7 @@ import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/models/albums/album_search.model.dart'; import 'package:immich_mobile/models/albums/album_search.model.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart'; import 'package:immich_mobile/pages/common/large_leading_tile.dart';
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
@ -443,7 +444,7 @@ class _AlbumList extends ConsumerWidget {
leading: album.thumbnailAssetId != null leading: album.thumbnailAssetId != null
? ClipRRect( ? ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(15)), borderRadius: const BorderRadius.all(Radius.circular(15)),
child: SizedBox(width: 80, height: 80, child: Thumbnail(remoteId: album.thumbnailAssetId)), child: SizedBox(width: 80, height: 80, child: Thumbnail(imageProvider: RemoteThumbProvider(assetId: album.thumbnailAssetId!))),
) )
: SizedBox( : SizedBox(
width: 80, width: 80,
@ -529,7 +530,7 @@ class _GridAlbumCard extends ConsumerWidget {
child: SizedBox( child: SizedBox(
width: double.infinity, width: double.infinity,
child: album.thumbnailAssetId != null child: album.thumbnailAssetId != null
? Thumbnail(remoteId: album.thumbnailAssetId) ? Thumbnail(imageProvider: RemoteThumbProvider(assetId: album.thumbnailAssetId!))
: Container( : Container(
color: context.colorScheme.surfaceContainerHighest, color: context.colorScheme.surfaceContainerHighest,
child: const Icon(Icons.photo_album_rounded, size: 40, color: Colors.grey), child: const Icon(Icons.photo_album_rounded, size: 40, color: Colors.grey),

View File

@ -577,10 +577,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
// Using multiple selectors to avoid unnecessary rebuilds for other state changes // Using multiple selectors to avoid unnecessary rebuilds for other state changes
ref.watch( ref.watch(
assetViewerProvider.select( assetViewerProvider.select(
(s) => (s) => s.showingBottomSheet.hashCode ^ s.backgroundOpacity.hashCode ^ s.stackIndex.hashCode,
s.showingBottomSheet.hashCode ^
s.backgroundOpacity.hashCode ^
s.stackIndex.hashCode,
), ),
); );
ref.watch(isPlayingMotionVideoProvider); ref.watch(isPlayingMotionVideoProvider);

View File

@ -77,7 +77,7 @@ class AssetViewerStateNotifier extends AutoDisposeNotifier<AssetViewerState> {
void setAsset(BaseAsset? asset) { void setAsset(BaseAsset? asset) {
if (asset != state.currentAsset) { if (asset != state.currentAsset) {
state = state.copyWith(currentAsset: asset, stackIndex: 0); state = state.copyWith(currentAsset: asset, stackIndex: 0);
} }
} }
void setOpacity(int opacity) { void setOpacity(int opacity) {

View File

@ -39,8 +39,7 @@ class LocalThumbProvider extends ImageProvider<LocalThumbProvider> {
} }
Future<ImageInfo> _codec(LocalThumbProvider key) async { Future<ImageInfo> _codec(LocalThumbProvider key) async {
final codec = final codec = await _assetMediaRepository.getLocalThumbnail(key.id, key.size);
await _assetMediaRepository.getLocalThumbnail(key.id, key.size);
return ImageInfo(image: (await codec.getNextFrame()).image, scale: 1.0); return ImageInfo(image: (await codec.getNextFrame()).image, scale: 1.0);
} }
@ -48,9 +47,7 @@ class LocalThumbProvider extends ImageProvider<LocalThumbProvider> {
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) return true; if (identical(this, other)) return true;
if (other is LocalThumbProvider) { if (other is LocalThumbProvider) {
return id == other.id && return id == other.id && size == other.size && updatedAt == other.updatedAt;
size == other.size &&
updatedAt == other.updatedAt;
} }
return false; return false;
} }
@ -81,8 +78,7 @@ class LocalFullImageProvider extends ImageProvider<LocalFullImageProvider> {
} }
Future<ImageInfo> _codec(LocalFullImageProvider key) async { Future<ImageInfo> _codec(LocalFullImageProvider key) async {
final devicePixelRatio = final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
PlatformDispatcher.instance.views.first.devicePixelRatio;
final codec = await _assetMediaRepository.getLocalThumbnail( final codec = await _assetMediaRepository.getLocalThumbnail(
key.id, key.id,
Size(size.width * devicePixelRatio, size.height * devicePixelRatio), Size(size.width * devicePixelRatio, size.height * devicePixelRatio),

View File

@ -106,8 +106,7 @@ class _ThumbnailState extends State<Thumbnail> {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.imageProvider != widget.imageProvider || if (oldWidget.imageProvider != widget.imageProvider ||
oldWidget.blurhash != widget.blurhash || oldWidget.blurhash != widget.blurhash ||
(oldWidget.thumbhashMode == ThumbhashMode.disabled && (oldWidget.thumbhashMode == ThumbhashMode.disabled && oldWidget.thumbhashMode != ThumbhashMode.disabled)) {
oldWidget.thumbhashMode != ThumbhashMode.disabled)) {
_loadImage(); _loadImage();
} }
} }
@ -120,13 +119,11 @@ class _ThumbnailState extends State<Thumbnail> {
void _loadImage() { void _loadImage() {
_stopListeningToStream(); _stopListeningToStream();
if (widget.thumbhashMode != ThumbhashMode.disabled && if (widget.thumbhashMode != ThumbhashMode.disabled && widget.blurhash != null) {
widget.blurhash != null) {
_decodeThumbhash(); _decodeThumbhash();
} }
if (widget.thumbhashMode != ThumbhashMode.only && if (widget.thumbhashMode != ThumbhashMode.only && widget.imageProvider != null) {
widget.imageProvider != null) {
_loadFromProvider(); _loadFromProvider();
} }
} }
@ -298,9 +295,7 @@ class _ThumbnailRenderBox extends RenderBox {
if (_fadeStartTime != null) { if (_fadeStartTime != null) {
final elapsed = DateTime.now().difference(_fadeStartTime!); final elapsed = DateTime.now().difference(_fadeStartTime!);
_crossFadeProgress = _crossFadeProgress = (elapsed.inMilliseconds / _fadeDuration.inMilliseconds).clamp(0.0, 1.0);
(elapsed.inMilliseconds / _fadeDuration.inMilliseconds)
.clamp(0.0, 1.0);
if (_crossFadeProgress < 1.0) { if (_crossFadeProgress < 1.0) {
SchedulerBinding.instance.scheduleFrameCallback((_) { SchedulerBinding.instance.scheduleFrameCallback((_) {

View File

@ -42,8 +42,7 @@ class ThumbnailTile extends ConsumerWidget {
final isSelected = ref.watch( final isSelected = ref.watch(
multiSelectProvider.select((multiselect) => multiselect.selectedAssets.contains(asset)), multiSelectProvider.select((multiselect) => multiselect.selectedAssets.contains(asset)),
); );
final isScrubbing = final isScrubbing = ref.watch(timelineStateProvider.select((state) => state.isScrubbing));
ref.watch(timelineStateProvider.select((state) => state.isScrubbing));
final borderStyle = lockSelection final borderStyle = lockSelection
? BoxDecoration( ? BoxDecoration(
@ -79,9 +78,7 @@ class ThumbnailTile extends ConsumerWidget {
tag: '${asset?.heroTag ?? ''}_$heroIndex', tag: '${asset?.heroTag ?? ''}_$heroIndex',
child: Thumbnail.fromBaseAsset( child: Thumbnail.fromBaseAsset(
asset: asset, asset: asset,
thumbhashMode: isScrubbing thumbhashMode: isScrubbing ? ThumbhashMode.only : ThumbhashMode.enabled,
? ThumbhashMode.only
: ThumbhashMode.enabled,
), ),
), ),
), ),

View File

@ -61,11 +61,11 @@ class DriftMemoryCard extends ConsumerWidget {
Colors.black.withValues(alpha: 0.2), Colors.black.withValues(alpha: 0.2),
BlendMode.darken, BlendMode.darken,
), ),
child: SizedBox( child: SizedBox(
width: 205, width: 205,
height: 200, height: 200,
child: Thumbnail.fromBaseAsset(asset: memory.assets[0]), child: Thumbnail.fromBaseAsset(asset: memory.assets[0]),
), ),
), ),
Positioned( Positioned(
bottom: 16, bottom: 16,

View File

@ -131,8 +131,8 @@ class _FixedSegmentRow extends ConsumerWidget {
future: timelineService.loadAssets(assetIndex, assetCount), future: timelineService.loadAssets(assetIndex, assetCount),
builder: (context, snapshot) { builder: (context, snapshot) {
return _buildAssetRow(context, snapshot.data, timelineService); return _buildAssetRow(context, snapshot.data, timelineService);
}, },
); );
} }
} }
@ -217,14 +217,12 @@ class _AssetTileWidget extends ConsumerWidget {
return GestureDetector( return GestureDetector(
onTap: () => lockSelection || asset == null ? null : _handleOnTap(context, ref, assetIndex, asset, heroOffset), onTap: () => lockSelection || asset == null ? null : _handleOnTap(context, ref, assetIndex, asset, heroOffset),
onLongPress: () => lockSelection || asset == null onLongPress: () => lockSelection || asset == null ? null : _handleOnLongPress(ref, asset),
? null child: ThumbnailTile(
: _handleOnLongPress(ref, asset), asset,
child: ThumbnailTile( lockSelection: lockSelection,
asset, showStorageIndicator: showStorageIndicator,
lockSelection: lockSelection, heroOffset: heroOffset,
showStorageIndicator: showStorageIndicator,
heroOffset: heroOffset,
), ),
); );
} }

View File

@ -68,8 +68,7 @@ class ImmichThumbnail extends HookConsumerWidget {
fadeInDuration: Duration.zero, fadeInDuration: Duration.zero,
fadeOutDuration: const Duration(milliseconds: 100), fadeOutDuration: const Duration(milliseconds: 100),
octoSet: OctoSet( octoSet: OctoSet(
placeholderBuilder: placeholderBuilder: blurHashPlaceholderBuilder(asset?.thumbhash, fit: fit),
blurHashPlaceholderBuilder(asset?.thumbhash, fit: fit),
errorBuilder: customErrorBuilder, errorBuilder: customErrorBuilder,
), ),
image: thumbnailProviderInstance, image: thumbnailProviderInstance,