From 9f513947881e87a42d205cd20c2671e7e44829b3 Mon Sep 17 00:00:00 2001 From: aminecmi Date: Fri, 26 Jul 2024 15:16:48 +0200 Subject: [PATCH] Initial Commit --- .gitignore | 130 ++++++ Swipe That Pic.xcodeproj/project.pbxproj | 421 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 14 + .../AppIcon.appiconset/Frame 1(2).png | Bin 0 -> 13336 bytes Swipe That Pic/Assets.xcassets/Contents.json | 6 + Swipe That Pic/Models/Extension.swift | 16 + Swipe That Pic/Models/Item.swift | 17 + Swipe That Pic/PhotosService.swift | 98 ++++ .../Preview Assets.xcassets/Contents.json | 6 + Swipe That Pic/Swipe_That_PicApp.swift | 34 ++ Swipe That Pic/Views/BigPicture.swift | 79 ++++ Swipe That Pic/Views/ContentView.swift | 70 +++ Swipe That Pic/Views/IgnoredPictures.swift | 53 +++ .../Views/PhotoTumbnailFromStringView.swift | 73 +++ Swipe That Pic/Views/PhotoTumbnailView.swift | 73 +++ Swipe-That-Pic-Info.plist | 5 + 20 files changed, 1135 insertions(+) create mode 100644 .gitignore create mode 100644 Swipe That Pic.xcodeproj/project.pbxproj create mode 100644 Swipe That Pic.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Swipe That Pic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Swipe That Pic.xcodeproj/xcuserdata/amine.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 Swipe That Pic/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Frame 1(2).png create mode 100644 Swipe That Pic/Assets.xcassets/Contents.json create mode 100644 Swipe That Pic/Models/Extension.swift create mode 100644 Swipe That Pic/Models/Item.swift create mode 100644 Swipe That Pic/PhotosService.swift create mode 100644 Swipe That Pic/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 Swipe That Pic/Swipe_That_PicApp.swift create mode 100644 Swipe That Pic/Views/BigPicture.swift create mode 100644 Swipe That Pic/Views/ContentView.swift create mode 100644 Swipe That Pic/Views/IgnoredPictures.swift create mode 100644 Swipe That Pic/Views/PhotoTumbnailFromStringView.swift create mode 100644 Swipe That Pic/Views/PhotoTumbnailView.swift create mode 100644 Swipe-That-Pic-Info.plist diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97a5e00 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Created by https://www.toptal.com/developers/gitignore/api/osx,swift,xcode +# Edit at https://www.toptal.com/developers/gitignore?templates=osx,swift,xcode + +### OSX ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Xcode ### + +## Xcode 8 and earlier + +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno +**/xcshareddata/WorkspaceSettings.xcsettings + +# End of https://www.toptal.com/developers/gitignore/api/osx,swift,xcode diff --git a/Swipe That Pic.xcodeproj/project.pbxproj b/Swipe That Pic.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e63df07 --- /dev/null +++ b/Swipe That Pic.xcodeproj/project.pbxproj @@ -0,0 +1,421 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 670F9C902C558799008BDD2F /* PhotoTumbnailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670F9C8F2C558799008BDD2F /* PhotoTumbnailView.swift */; }; + 670F9C922C558E0F008BDD2F /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670F9C912C558E0F008BDD2F /* Extension.swift */; }; + 670F9C942C56680C008BDD2F /* IgnoredPictures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670F9C932C56680C008BDD2F /* IgnoredPictures.swift */; }; + 670F9C982C566EF6008BDD2F /* PhotoTumbnailFromStringView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670F9C972C566EF6008BDD2F /* PhotoTumbnailFromStringView.swift */; }; + 670F9C9A2C5678B9008BDD2F /* BigPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 670F9C992C5678B9008BDD2F /* BigPicture.swift */; }; + 67672FEA2C5915F6003AE9A6 /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = 67672FE92C5915F6003AE9A6 /* .gitignore */; }; + 67E5F04E2C53D93E005DDD7A /* Swipe_That_PicApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E5F04D2C53D93E005DDD7A /* Swipe_That_PicApp.swift */; }; + 67E5F0502C53D93E005DDD7A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E5F04F2C53D93E005DDD7A /* ContentView.swift */; }; + 67E5F0522C53D93E005DDD7A /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E5F0512C53D93E005DDD7A /* Item.swift */; }; + 67E5F0542C53D93F005DDD7A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67E5F0532C53D93F005DDD7A /* Assets.xcassets */; }; + 67E5F0572C53D93F005DDD7A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67E5F0562C53D93F005DDD7A /* Preview Assets.xcassets */; }; + 67E5F0692C551489005DDD7A /* PhotosService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E5F0682C551489005DDD7A /* PhotosService.swift */; }; + 67E5F06B2C5514DD005DDD7A /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67E5F06A2C5514DD005DDD7A /* PhotosUI.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 670F9C8F2C558799008BDD2F /* PhotoTumbnailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoTumbnailView.swift; sourceTree = ""; }; + 670F9C912C558E0F008BDD2F /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = ""; }; + 670F9C932C56680C008BDD2F /* IgnoredPictures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IgnoredPictures.swift; sourceTree = ""; }; + 670F9C972C566EF6008BDD2F /* PhotoTumbnailFromStringView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoTumbnailFromStringView.swift; sourceTree = ""; }; + 670F9C992C5678B9008BDD2F /* BigPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BigPicture.swift; sourceTree = ""; }; + 67672FE92C5915F6003AE9A6 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; + 67E5F04A2C53D93E005DDD7A /* Swipe That Pic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Swipe That Pic.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 67E5F04D2C53D93E005DDD7A /* Swipe_That_PicApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swipe_That_PicApp.swift; sourceTree = ""; }; + 67E5F04F2C53D93E005DDD7A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 67E5F0512C53D93E005DDD7A /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; + 67E5F0532C53D93F005DDD7A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 67E5F0562C53D93F005DDD7A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 67E5F0642C550FCE005DDD7A /* Swipe-That-Pic-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Swipe-That-Pic-Info.plist"; sourceTree = SOURCE_ROOT; }; + 67E5F0662C5511F7005DDD7A /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; + 67E5F0682C551489005DDD7A /* PhotosService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotosService.swift; sourceTree = ""; }; + 67E5F06A2C5514DD005DDD7A /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = System/Library/Frameworks/PhotosUI.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 67E5F0472C53D93E005DDD7A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 67E5F06B2C5514DD005DDD7A /* PhotosUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 67E5F0412C53D93E005DDD7A = { + isa = PBXGroup; + children = ( + 67672FE92C5915F6003AE9A6 /* .gitignore */, + 67E5F04C2C53D93E005DDD7A /* Swipe That Pic */, + 67E5F04B2C53D93E005DDD7A /* Products */, + 67E5F0652C5511F7005DDD7A /* Frameworks */, + ); + sourceTree = ""; + }; + 67E5F04B2C53D93E005DDD7A /* Products */ = { + isa = PBXGroup; + children = ( + 67E5F04A2C53D93E005DDD7A /* Swipe That Pic.app */, + ); + name = Products; + sourceTree = ""; + }; + 67E5F04C2C53D93E005DDD7A /* Swipe That Pic */ = { + isa = PBXGroup; + children = ( + 67E5F0682C551489005DDD7A /* PhotosService.swift */, + 67E5F0642C550FCE005DDD7A /* Swipe-That-Pic-Info.plist */, + 67E5F0612C53DF09005DDD7A /* Models */, + 67E5F0602C53DF01005DDD7A /* Views */, + 67E5F04D2C53D93E005DDD7A /* Swipe_That_PicApp.swift */, + 67E5F0532C53D93F005DDD7A /* Assets.xcassets */, + 67E5F0552C53D93F005DDD7A /* Preview Content */, + ); + path = "Swipe That Pic"; + sourceTree = ""; + }; + 67E5F0552C53D93F005DDD7A /* Preview Content */ = { + isa = PBXGroup; + children = ( + 67E5F0562C53D93F005DDD7A /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 67E5F0602C53DF01005DDD7A /* Views */ = { + isa = PBXGroup; + children = ( + 67E5F04F2C53D93E005DDD7A /* ContentView.swift */, + 670F9C8F2C558799008BDD2F /* PhotoTumbnailView.swift */, + 670F9C972C566EF6008BDD2F /* PhotoTumbnailFromStringView.swift */, + 670F9C932C56680C008BDD2F /* IgnoredPictures.swift */, + 670F9C992C5678B9008BDD2F /* BigPicture.swift */, + ); + path = Views; + sourceTree = ""; + }; + 67E5F0612C53DF09005DDD7A /* Models */ = { + isa = PBXGroup; + children = ( + 67E5F0512C53D93E005DDD7A /* Item.swift */, + 670F9C912C558E0F008BDD2F /* Extension.swift */, + ); + path = Models; + sourceTree = ""; + }; + 67E5F0652C5511F7005DDD7A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 67E5F06A2C5514DD005DDD7A /* PhotosUI.framework */, + 67E5F0662C5511F7005DDD7A /* Photos.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 67E5F0492C53D93E005DDD7A /* Swipe That Pic */ = { + isa = PBXNativeTarget; + buildConfigurationList = 67E5F05A2C53D93F005DDD7A /* Build configuration list for PBXNativeTarget "Swipe That Pic" */; + buildPhases = ( + 67E5F0462C53D93E005DDD7A /* Sources */, + 67E5F0472C53D93E005DDD7A /* Frameworks */, + 67E5F0482C53D93E005DDD7A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Swipe That Pic"; + packageProductDependencies = ( + ); + productName = "Swipe That Pic"; + productReference = 67E5F04A2C53D93E005DDD7A /* Swipe That Pic.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 67E5F0422C53D93E005DDD7A /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 67E5F0492C53D93E005DDD7A = { + CreatedOnToolsVersion = 15.4; + }; + }; + }; + buildConfigurationList = 67E5F0452C53D93E005DDD7A /* Build configuration list for PBXProject "Swipe That Pic" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 67E5F0412C53D93E005DDD7A; + packageReferences = ( + ); + productRefGroup = 67E5F04B2C53D93E005DDD7A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 67E5F0492C53D93E005DDD7A /* Swipe That Pic */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 67E5F0482C53D93E005DDD7A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 67E5F0572C53D93F005DDD7A /* Preview Assets.xcassets in Resources */, + 67672FEA2C5915F6003AE9A6 /* .gitignore in Resources */, + 67E5F0542C53D93F005DDD7A /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 67E5F0462C53D93E005DDD7A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 670F9C982C566EF6008BDD2F /* PhotoTumbnailFromStringView.swift in Sources */, + 67E5F0692C551489005DDD7A /* PhotosService.swift in Sources */, + 67E5F0502C53D93E005DDD7A /* ContentView.swift in Sources */, + 670F9C942C56680C008BDD2F /* IgnoredPictures.swift in Sources */, + 670F9C9A2C5678B9008BDD2F /* BigPicture.swift in Sources */, + 67E5F0522C53D93E005DDD7A /* Item.swift in Sources */, + 670F9C922C558E0F008BDD2F /* Extension.swift in Sources */, + 670F9C902C558799008BDD2F /* PhotoTumbnailView.swift in Sources */, + 67E5F04E2C53D93E005DDD7A /* Swipe_That_PicApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 67E5F0582C53D93F005DDD7A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + 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; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 67E5F0592C53D93F005DDD7A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + 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; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 67E5F05B2C53D93F005DDD7A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Swipe That Pic/Preview Content\""; + DEVELOPMENT_TEAM = SH3XZXB7R8; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Swipe-That-Pic-Info.plist"; + INFOPLIST_KEY_NSPhotoLibraryUsageDescription = ""; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "apps.amine.bou.Swipe-That-Pic"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 67E5F05C2C53D93F005DDD7A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Swipe That Pic/Preview Content\""; + DEVELOPMENT_TEAM = SH3XZXB7R8; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Swipe-That-Pic-Info.plist"; + INFOPLIST_KEY_NSPhotoLibraryUsageDescription = ""; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "apps.amine.bou.Swipe-That-Pic"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 67E5F0452C53D93E005DDD7A /* Build configuration list for PBXProject "Swipe That Pic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 67E5F0582C53D93F005DDD7A /* Debug */, + 67E5F0592C53D93F005DDD7A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 67E5F05A2C53D93F005DDD7A /* Build configuration list for PBXNativeTarget "Swipe That Pic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 67E5F05B2C53D93F005DDD7A /* Debug */, + 67E5F05C2C53D93F005DDD7A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 67E5F0422C53D93E005DDD7A /* Project object */; +} diff --git a/Swipe That Pic.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Swipe That Pic.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Swipe That Pic.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Swipe That Pic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Swipe That Pic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Swipe That Pic.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Swipe That Pic.xcodeproj/xcuserdata/amine.xcuserdatad/xcschemes/xcschememanagement.plist b/Swipe That Pic.xcodeproj/xcuserdata/amine.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..8931a81 --- /dev/null +++ b/Swipe That Pic.xcodeproj/xcuserdata/amine.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Swipe That Pic.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Swipe That Pic/Assets.xcassets/AccentColor.colorset/Contents.json b/Swipe That Pic/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Swipe That Pic/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Contents.json b/Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..363cd1c --- /dev/null +++ b/Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "Frame 1(2).png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Frame 1(2).png b/Swipe That Pic/Assets.xcassets/AppIcon.appiconset/Frame 1(2).png new file mode 100644 index 0000000000000000000000000000000000000000..bb2cc02c1490e08ad9df73c801c00c5e3243fab0 GIT binary patch literal 13336 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 literal 0 HcmV?d00001 diff --git a/Swipe That Pic/Assets.xcassets/Contents.json b/Swipe That Pic/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Swipe That Pic/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swipe That Pic/Models/Extension.swift b/Swipe That Pic/Models/Extension.swift new file mode 100644 index 0000000..7731c43 --- /dev/null +++ b/Swipe That Pic/Models/Extension.swift @@ -0,0 +1,16 @@ +// +// Extension.swift +// Swipe That Pic +// +// Created by Amine Bou on 27/07/2024. +// + +import Foundation +import Photos + +extension Array { + func random() -> Element { + let randomIndex = Int(arc4random()) % self.count + return self[randomIndex] + } +} diff --git a/Swipe That Pic/Models/Item.swift b/Swipe That Pic/Models/Item.swift new file mode 100644 index 0000000..f3516b4 --- /dev/null +++ b/Swipe That Pic/Models/Item.swift @@ -0,0 +1,17 @@ +// +// Item.swift +// Swipe That Pic +// +// Created by Amine Bou on 26/07/2024. +// + +import Foundation +import SwiftData + +@Model +final class Item { + @Attribute(.unique) var localIdentfier: String + init(localIdentfier: String) { + self.localIdentfier = localIdentfier + } +} diff --git a/Swipe That Pic/PhotosService.swift b/Swipe That Pic/PhotosService.swift new file mode 100644 index 0000000..7e7ad99 --- /dev/null +++ b/Swipe That Pic/PhotosService.swift @@ -0,0 +1,98 @@ +// +// PhotosService.swift +// Swipe That Pic +// +// Created by Amine Bou on 27/07/2024. +// + +import Foundation +import Photos +import UIKit +import SwiftData +import SwiftUI + +class PhotosService: ObservableObject { + var notKept: PHFetchResult = PHFetchResult() + @Published var one: PHAsset? + var modelContainer: ModelContainer + + init(modelContainer: ModelContainer) { + self.modelContainer = modelContainer + } + + var imageCachingManager = PHCachingImageManager() + + @MainActor func fetchNotKeptPhotos() { + PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in + switch status { + case .authorized: + self.fetchNotKeptPhotosAuthorized() + break; + @unknown default: + fatalError() + } + } + } + + @MainActor func fetchNotKeptPhotosAuthorized() { + imageCachingManager.allowsCachingHighQualityImages = false + let fetchOptions = PHFetchOptions() + fetchOptions.includeHiddenAssets = false + do { + let items = try self.modelContainer.mainContext.fetch(FetchDescriptor()) + if (items.count > 0) { + fetchOptions.predicate = NSPredicate(format: "NOT localIdentifier IN %@", + argumentArray: [items.map {$0.localIdentfier}]) + } + } catch { + print("Can't get model") + } + fetchOptions.sortDescriptors = [ + NSSortDescriptor(key: "creationDate", ascending: false) + ] + DispatchQueue.main.async { + self.notKept = PHAsset.fetchAssets(with: .image, options: fetchOptions) + if (self.notKept.count > 0) { + self.one = self.notKept.object(at: Int.random(in: 0.. UIImage? { + let results = PHAsset.fetchAssets( + withLocalIdentifiers: [localId], + options: nil + ) + guard let asset = results.firstObject else { + fatalError("No asset") + } + let options = PHImageRequestOptions() + options.deliveryMode = .opportunistic + options.resizeMode = .fast + options.isNetworkAccessAllowed = true + options.isSynchronous = true + return try await withCheckedThrowingContinuation { [weak self] continuation in + /// Use the imageCachingManager to fetch the image + self?.imageCachingManager.requestImage( + for: asset, + targetSize: targetSize, + contentMode: contentMode, + options: options, + resultHandler: { image, info in + /// image is of type UIImage + if let error = info?[PHImageErrorKey] as? Error { + continuation.resume(throwing: error) + return + } + continuation.resume(returning: image) + } + ) + } + } +} diff --git a/Swipe That Pic/Preview Content/Preview Assets.xcassets/Contents.json b/Swipe That Pic/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Swipe That Pic/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swipe That Pic/Swipe_That_PicApp.swift b/Swipe That Pic/Swipe_That_PicApp.swift new file mode 100644 index 0000000..aac6ebb --- /dev/null +++ b/Swipe That Pic/Swipe_That_PicApp.swift @@ -0,0 +1,34 @@ +// +// Swipe_That_PicApp.swift +// Swipe That Pic +// +// Created by Amine Bou on 26/07/2024. +// + +import SwiftUI +import SwiftData +import Photos + +@main +struct Swipe_That_PicApp: App { + var sharedModelContainer: ModelContainer = { + let schema = Schema([ + Item.self, + ]) + let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) + + do { + return try ModelContainer(for: schema, configurations: [modelConfiguration]) + } catch { + fatalError("Could not create ModelContainer: \(error)") + } + }() + + var body: some Scene { + WindowGroup { + ContentView().environmentObject(PhotosService(modelContainer: sharedModelContainer)) + + } + .modelContainer(sharedModelContainer) + } +} diff --git a/Swipe That Pic/Views/BigPicture.swift b/Swipe That Pic/Views/BigPicture.swift new file mode 100644 index 0000000..4c8f77e --- /dev/null +++ b/Swipe That Pic/Views/BigPicture.swift @@ -0,0 +1,79 @@ +// +// PhotoTumbnailView.swift +// Swipe That Pic +// +// Created by Amine Bou on 27/07/2024. +// + +import Foundation +import Photos +import SwiftUI + +struct BigPicture: View { + private var image: Image + + @State var scale = 1.0 + @State var lastScale = 0.0 + @State var offset: CGSize = .zero + @State var lastOffset: CGSize = .zero + + init(image: Image) { + self.image = image + } + + var body: some View { + GeometryReader { proxy in + image + .resizable() + .scaledToFill() + .scaleEffect(scale) + .offset(offset) + .frame(width: proxy.size.width, height: proxy.size.height) + .gesture( + MagnificationGesture(minimumScaleDelta: 0) + .onChanged({ value in + withAnimation(.interactiveSpring()) { + scale = handleScaleChange(value) + } + }) + .onEnded({ _ in + lastScale = scale + }).simultaneously( + with: DragGesture(minimumDistance: 0) + .onChanged({ value in + withAnimation(.interactiveSpring()) { + offset = handleOffsetChange(value.translation) + } + }) + .onEnded({ _ in + lastOffset = offset + }) + + ).simultaneously(with: TapGesture(count: 2).onEnded({ Void in + scale = 1.0 + lastScale = 0.0 + offset = .zero + lastOffset = .zero + })) + ) + + } + // We'll also make sure that the photo will + // be square + .aspectRatio(1, contentMode: .fit) + + } + + private func handleScaleChange(_ zoom: CGFloat) -> CGFloat { + lastScale + zoom - (lastScale == 0 ? 0 : 1) + } + + private func handleOffsetChange(_ offset: CGSize) -> CGSize { + var newOffset: CGSize = .zero + + newOffset.width = offset.width + lastOffset.width + newOffset.height = offset.height + lastOffset.height + + return newOffset + } +} diff --git a/Swipe That Pic/Views/ContentView.swift b/Swipe That Pic/Views/ContentView.swift new file mode 100644 index 0000000..f060114 --- /dev/null +++ b/Swipe That Pic/Views/ContentView.swift @@ -0,0 +1,70 @@ +// +// ContentView.swift +// Swipe That Pic +// +// Created by Amine Bou on 26/07/2024. +// + +import SwiftUI +import SwiftData +import Photos + +struct ContentView: View { + @Environment(\.modelContext) private var modelContext + @EnvironmentObject var photoLibraryService: PhotosService + @Query private var items: [Item] + + var body: some View { + NavigationSplitView { + VStack { + PhotoThumbnailView(asset: $photoLibraryService.one) + Spacer() + HStack { + Button(role: .destructive, action: { + PHPhotoLibrary.shared().performChanges({ + PHAssetChangeRequest.deleteAssets([photoLibraryService.one as Any] as NSArray) + }, completionHandler: { success, error in + if success { + photoLibraryService.fetchNotKeptPhotos() + + } else { + }}) + }) { + Label("Supprimer", systemImage: "minus.circle.fill") + }.buttonStyle(.borderedProminent) + + Spacer() + Button(action: { + let newItem = Item(localIdentfier: photoLibraryService.one!.localIdentifier) + modelContext.insert(newItem) + photoLibraryService.fetchNotKeptPhotos() + }) { + Label("Garder", systemImage: "plus.circle.fill") + }.buttonStyle(.borderedProminent) + }.disabled(photoLibraryService.one == nil) + } + + .toolbar { + if (items.count > 0) { + ToolbarItem { + NavigationLink(destination: IgnoredPictures()) { + Label("Handle kept", systemImage: "tray.and.arrow.up.fill") + } + } + } + + } + } detail: { + Text("Select an item") + }.onAppear(perform: { + photoLibraryService.fetchNotKeptPhotos() + }) + } + +} + +#Preview { + ContentView() + .modelContainer(for: Item.self, inMemory: true) +} + diff --git a/Swipe That Pic/Views/IgnoredPictures.swift b/Swipe That Pic/Views/IgnoredPictures.swift new file mode 100644 index 0000000..96c364b --- /dev/null +++ b/Swipe That Pic/Views/IgnoredPictures.swift @@ -0,0 +1,53 @@ +// +// ContentView.swift +// Swipe That Pic +// +// Created by Amine Bou on 26/07/2024. +// + +import SwiftUI +import SwiftData +import Photos + +struct IgnoredPictures: View { + @Environment(\.modelContext) private var modelContext + @Query private var items: [Item] + + var body: some View { + NavigationSplitView { + ScrollView { + LazyVGrid(columns: [GridItem(.adaptive(minimum: 200)), GridItem(.adaptive(minimum: 200))], alignment: .leading) { + ForEach(items) { item in + PhotoThumbnailFromStringView(localIdentifier: item.localIdentfier) + } + } + .toolbar { + ToolbarItem { + Button(action: clearItems) { + Label("Clear", systemImage: "bubbles.and.sparkles.fill") + } + } + } + } + } detail : { + Text("Ignored pictures") + } + } + + private func clearItems() { + withAnimation { + do { + try modelContext.delete(model: Item.self) + } catch { + print("did not work") + } + } + } + +} + +#Preview { + ContentView() + .modelContainer(for: Item.self, inMemory: true) +} + diff --git a/Swipe That Pic/Views/PhotoTumbnailFromStringView.swift b/Swipe That Pic/Views/PhotoTumbnailFromStringView.swift new file mode 100644 index 0000000..90a8005 --- /dev/null +++ b/Swipe That Pic/Views/PhotoTumbnailFromStringView.swift @@ -0,0 +1,73 @@ +// +// PhotoTumbnailView.swift +// Swipe That Pic +// +// Created by Amine Bou on 27/07/2024. +// + +import Foundation +import Photos +import SwiftUI + +struct PhotoThumbnailFromStringView: View { + @EnvironmentObject var photoLibraryService: PhotosService + @State private var image: Image? + @State var localIdentifier: String? + + func loadImageAsset( + targetSize: CGSize = PHImageManagerMaximumSize + ) async { + if (localIdentifier != nil) { + guard let uiImage = try? await photoLibraryService + .fetchImage( + byLocalIdentifier: localIdentifier!, + targetSize: targetSize + ) else { + image = nil + return + } + image = Image(uiImage: uiImage) + } else { + image = nil + } + } + + var body: some View { + ZStack { + // Show the image if it's available + if let image = image { + GeometryReader { proxy in + image + .resizable() + .aspectRatio(contentMode: .fill) + .frame( + width: proxy.size.width, + height: proxy.size.width + ) + .clipped() + } + // We'll also make sure that the photo will + // be square + .aspectRatio(1, contentMode: .fit) + } else { + // Otherwise, show a gray rectangle with a + // spinning progress view + Rectangle() + .foregroundColor(.gray) + .aspectRatio(1, contentMode: .fit) + ProgressView() + } + } + // We need to use the task to work on a concurrent request to + // load the image from the photo library service, which + // is asynchronous work. + .task(id: localIdentifier) { + await loadImageAsset() + } + // Finally, when the view disappears, we need to free it + // up from the memory + .onDisappear { + image = nil + } + } +} diff --git a/Swipe That Pic/Views/PhotoTumbnailView.swift b/Swipe That Pic/Views/PhotoTumbnailView.swift new file mode 100644 index 0000000..1cba3e4 --- /dev/null +++ b/Swipe That Pic/Views/PhotoTumbnailView.swift @@ -0,0 +1,73 @@ +// +// PhotoTumbnailView.swift +// Swipe That Pic +// +// Created by Amine Bou on 27/07/2024. +// + +import Foundation +import Photos +import SwiftUI + +struct PhotoThumbnailView: View { + @EnvironmentObject var photoLibraryService: PhotosService + @State private var image: Image? + @Binding var asset: PHAsset? + + func loadImageAsset( + targetSize: CGSize = PHImageManagerMaximumSize + ) async { + if (asset != nil) { + guard let uiImage = try? await photoLibraryService + .fetchImage( + byLocalIdentifier: asset!.localIdentifier, + targetSize: targetSize + ) else { + image = nil + return + } + image = Image(uiImage: uiImage) + } else { + image = nil + } + } + + var body: some View { + ZStack { + // Show the image if it's available + if let image = image { + GeometryReader { proxy in + NavigationLink(destination: BigPicture(image: image)) { + image + .resizable() + .aspectRatio(contentMode: .fill) + .frame( + width: proxy.size.width, + height: proxy.size.width + ) + .clipped() + } + + } + } else { + // Otherwise, show a gray rectangle with a + // spinning progress view + Rectangle() + .foregroundColor(.gray) + .aspectRatio(1, contentMode: .fit) + ProgressView() + } + } + // We need to use the task to work on a concurrent request to + // load the image from the photo library service, which + // is asynchronous work. + .task(id: asset?.localIdentifier) { + await loadImageAsset() + } + // Finally, when the view disappears, we need to free it + // up from the memory + .onDisappear { + image = nil + } + } +} diff --git a/Swipe-That-Pic-Info.plist b/Swipe-That-Pic-Info.plist new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/Swipe-That-Pic-Info.plist @@ -0,0 +1,5 @@ + + + + +