1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-10 23:22:22 +02:00

feat(mobile): ios widgets (#19148)

* feat: working widgets

* chore/feat: cleaned up API, added album picker to random widget

* album filtering for requests

* check album and throw if not found

* fix app IDs and project configuration

* switch to repository/service model for updating widgets

* fix: remove home widget import

* revert info.plist formatting changes

* ran swift-format on widget code

* more formatting changes (this time run from xcode)

* show memory on widget picker snapshot

* fix: dart changes from code review

* fix: swift code review changes (not including task groups)

* fix: use task groups to run image retrievals concurrently, get rid of do catch in favor of if let

* chore: cleanup widget service in dart app

* chore: format swift

* fix: remove comma

why does xcode not freak out over this >:(

* switch to preview size for thumbnail

* chore: cropped large image

* fix: properly resize widgets so we dont OOM

* fix: set app group on logout

happens on first install

* fix: stupid app ids

* fix: revert back to thumbnail

we are hitting OOM exceptions due to resizing, once we have on-the-fly resizing on server this can be upgraded

* fix: more memory efficient resizing method, remove extraneous resize commands from API call

* fix: random widget use 12 entries instead of 24 to save memory

* fix: modify duration of entries to 20 minutes and only generate 10 at a time to avoid OOM

* feat: toggle to show album name on random widget

* Podfile lock

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Brandon Wees
2025-06-17 09:43:09 -05:00
committed by GitHub
parent 15c488ccd9
commit a0f44f147b
19 changed files with 1092 additions and 1 deletions

View File

@@ -17,12 +17,23 @@
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
D218389C4A4C4693F141F7D1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */; };
F02538E92DFBCBDD008C3FA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
F0B57D3A2DF764BD00DC5BCC /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */; };
F0B57D3C2DF764BD00DC5BCC /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */; };
F0B57D492DF764BE00DC5BCC /* WidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F0B57D382DF764BD00DC5BCC /* WidgetExtension.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 */; };
FAC6F8B92D287F120078CB2F /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FAC6F8B32D287F120078CB2F /* MainInterface.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
F0B57D472DF764BE00DC5BCC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = F0B57D372DF764BD00DC5BCC;
remoteInfo = WidgetExtension;
};
FAC6F8982D287C890078CB2F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
@@ -49,6 +60,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
F0B57D492DF764BE00DC5BCC /* WidgetExtension.appex in Embed Foundation Extensions */,
FAC6F89B2D287C890078CB2F /* ShareExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
@@ -78,6 +90,9 @@
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B1FBA9EE014DE20271B0FE77 /* Pods-ShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
E0E99CDC17B3EB7FA8BA2332 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
F0B57D382DF764BD00DC5BCC /* WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
F7101BB0391A314774615E89 /* 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>"; };
F8A35EA3C3E01BD66AFDE0E5 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
FA9973382CF6DF4B000EF859 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
@@ -89,6 +104,16 @@
FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerProfile.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
F0B57D4D2DF764BE00DC5BCC /* Exceptions for "WidgetExtension" folder in "WidgetExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = F0B57D372DF764BD00DC5BCC /* WidgetExtension */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = {
isa = PBXFileSystemSynchronizedRootGroup;
@@ -97,6 +122,14 @@
path = Sync;
sourceTree = "<group>";
};
F0B57D3D2DF764BD00DC5BCC /* WidgetExtension */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
F0B57D4D2DF764BE00DC5BCC /* Exceptions for "WidgetExtension" folder in "WidgetExtension" target */,
);
path = WidgetExtension;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
@@ -108,6 +141,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F0B57D352DF764BD00DC5BCC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F0B57D3C2DF764BD00DC5BCC /* SwiftUI.framework in Frameworks */,
F0B57D3A2DF764BD00DC5BCC /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC6F88D2D287C890078CB2F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -137,6 +179,8 @@
children = (
886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */,
357FC57E54FD0F51795CF28A /* Pods_ShareExtension.framework */,
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */,
F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -167,6 +211,7 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
FAC6F8B62D287F120078CB2F /* ShareExtension */,
F0B57D3D2DF764BD00DC5BCC /* WidgetExtension */,
97C146EF1CF9000F007C117D /* Products */,
0FB772A5B9601143383626CA /* Pods */,
1754452DD81DA6620E279E51 /* Frameworks */,
@@ -178,6 +223,7 @@
children = (
97C146EE1CF9000F007C117D /* Immich-Debug.app */,
FAC6F8902D287C890078CB2F /* ShareExtension.appex */,
F0B57D382DF764BD00DC5BCC /* WidgetExtension.appex */,
);
name = Products;
sourceTree = "<group>";
@@ -234,6 +280,7 @@
);
dependencies = (
FAC6F8992D287C890078CB2F /* PBXTargetDependency */,
F0B57D482DF764BE00DC5BCC /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
B2CF7F8C2DDE4EBB00744BF6 /* Sync */,
@@ -243,6 +290,26 @@
productReference = 97C146EE1CF9000F007C117D /* Immich-Debug.app */;
productType = "com.apple.product-type.application";
};
F0B57D372DF764BD00DC5BCC /* WidgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = F0B57D4E2DF764BE00DC5BCC /* Build configuration list for PBXNativeTarget "WidgetExtension" */;
buildPhases = (
F0B57D342DF764BD00DC5BCC /* Sources */,
F0B57D352DF764BD00DC5BCC /* Frameworks */,
F0B57D362DF764BD00DC5BCC /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
F0B57D3D2DF764BD00DC5BCC /* WidgetExtension */,
);
name = WidgetExtension;
productName = WidgetExtension;
productReference = F0B57D382DF764BD00DC5BCC /* WidgetExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
FAC6F88F2D287C890078CB2F /* ShareExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = FAC6F8A02D287C890078CB2F /* Build configuration list for PBXNativeTarget "ShareExtension" */;
@@ -268,7 +335,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1600;
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
@@ -277,6 +344,9 @@
LastSwiftMigration = 1100;
ProvisioningStyle = Automatic;
};
F0B57D372DF764BD00DC5BCC = {
CreatedOnToolsVersion = 16.4;
};
FAC6F88F2D287C890078CB2F = {
CreatedOnToolsVersion = 16.0;
ProvisioningStyle = Automatic;
@@ -298,6 +368,7 @@
targets = (
97C146ED1CF9000F007C117D /* Runner */,
FAC6F88F2D287C890078CB2F /* ShareExtension */,
F0B57D372DF764BD00DC5BCC /* WidgetExtension */,
);
};
/* End PBXProject section */
@@ -314,6 +385,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F0B57D362DF764BD00DC5BCC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F02538E92DFBCBDD008C3FA3 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC6F88E2D287C890078CB2F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -448,6 +527,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F0B57D342DF764BD00DC5BCC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
FAC6F88C2D287C890078CB2F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -459,6 +545,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
F0B57D482DF764BE00DC5BCC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = F0B57D372DF764BD00DC5BCC /* WidgetExtension */;
targetProxy = F0B57D472DF764BE00DC5BCC /* PBXContainerItemProxy */;
};
FAC6F8992D287C890078CB2F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FAC6F88F2D287C890078CB2F /* ShareExtension */;
@@ -751,6 +842,129 @@
};
name = Release;
};
F0B57D4A2DF764BE00DC5BCC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = WidgetExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Widget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug.Widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
F0B57D4B2DF764BE00DC5BCC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = WidgetExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Widget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.Widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
F0B57D4C2DF764BE00DC5BCC /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = WidgetExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Widget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile.Widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Profile;
};
FAC6F89C2D287C890078CB2F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = F8A35EA3C3E01BD66AFDE0E5 /* Pods-ShareExtension.debug.xcconfig */;
@@ -900,6 +1114,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F0B57D4E2DF764BE00DC5BCC /* Build configuration list for PBXNativeTarget "WidgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F0B57D4A2DF764BE00DC5BCC /* Debug */,
F0B57D4B2DF764BE00DC5BCC /* Release */,
F0B57D4C2DF764BE00DC5BCC /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FAC6F8A02D287C890078CB2F /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (