Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Live Photo loading from network #2302

Merged
merged 26 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fd37da7
Downloader support for live photo
onevcat Oct 1, 2024
31002aa
Not assertion for default processor
onevcat Oct 1, 2024
a17c444
Test for live photo downloading
onevcat Oct 1, 2024
297e0f7
Add Kingfisher manager support for live photo
onevcat Oct 2, 2024
de8fd84
Unit test for live photo methods in manager
onevcat Oct 2, 2024
388fb84
Add tests for retrieving live photo
onevcat Oct 4, 2024
8be1491
Add extension methods and error cases for live photo
onevcat Oct 5, 2024
51a51e3
File extension guessing
onevcat Oct 5, 2024
880fbff
Add support for force cache file extension
onevcat Oct 5, 2024
c13a805
Fix a flaky test due to task env
onevcat Oct 5, 2024
c7c1e3d
Add file extension guessing from ref and data
onevcat Oct 5, 2024
790b9b6
Make it work with brutal extension
onevcat Oct 5, 2024
bf2039e
Try to guess file extension when getting from cache
onevcat Oct 5, 2024
444fabe
Fix failing tests caused by extension cache
onevcat Oct 5, 2024
1fdae3b
Opt out watchOS target for live photo
onevcat Oct 6, 2024
f79bdec
Add unit tests for resource extension and type guessing
onevcat Oct 6, 2024
126e2d0
Add extension file store test
onevcat Oct 6, 2024
253226e
Minor refactoring and more tests
onevcat Oct 7, 2024
b9c4a7e
Add missing resource error for disk cache
onevcat Oct 7, 2024
eb7ce5a
Prevent reentrance issue and mark progress unavailable
onevcat Oct 7, 2024
b7d3353
Refine API and prevent multiple completion invokes
onevcat Oct 8, 2024
b10ee06
Add documentation for most components of live photo support
onevcat Oct 9, 2024
a51a4cc
Support using data provider to get live photo data
onevcat Oct 9, 2024
7a6306d
More documentations
onevcat Oct 10, 2024
6506de2
Fix tests
onevcat Oct 10, 2024
27f4a73
Rename comment
onevcat Oct 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions Demo/Demo/Kingfisher-Demo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="peg-r0-mlo">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="peg-r0-mlo">
<device id="retina5_5" orientation="portrait" appearance="dark"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand Down Expand Up @@ -491,9 +491,33 @@
<segue destination="wco-eY-gNu" kind="show" id="KCP-ab-diO"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="TIF-8x-GLM">
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="8uq-CX-Fxl">
<rect key="frame" x="0.0" y="710" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="8uq-CX-Fxl" id="I9G-72-N8J">
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Live Photo" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mXz-QJ-f80">
<rect key="frame" x="20" y="11.666666666666664" width="80" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="mXz-QJ-f80" firstAttribute="leading" secondItem="I9G-72-N8J" secondAttribute="leading" constant="20" symbolic="YES" id="1BM-Eu-bcs"/>
<constraint firstItem="mXz-QJ-f80" firstAttribute="centerY" secondItem="I9G-72-N8J" secondAttribute="centerY" id="Fqb-ZQ-J3L"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="mXz-QJ-f80" secondAttribute="trailing" constant="20" symbolic="YES" id="fAH-HG-EXN"/>
</constraints>
</tableViewCellContentView>
<connections>
<segue destination="nhf-ZY-JwU" kind="show" id="Srz-py-yg9"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="TIF-8x-GLM">
<rect key="frame" x="0.0" y="754" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="TIF-8x-GLM" id="ykx-Ds-PkP">
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
Expand Down Expand Up @@ -992,6 +1016,22 @@
</objects>
<point key="canvasLocation" x="2654" y="1061"/>
</scene>
<!--Live Photo View Controller-->
<scene sceneID="50O-N8-WQ3">
<objects>
<viewController id="nhf-ZY-JwU" customClass="LivePhotoViewController" customModule="Kingfisher_Demo" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="G81-wm-Fnw">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="12L-DC-epo"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<navigationItem key="navigationItem" id="bYb-CA-CnJ"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="y5S-MW-IuF" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1851" y="2398"/>
</scene>
<!--Asset Image Generator View Controller-->
<scene sceneID="PCw-9j-oCu">
<objects>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// LivePhotoViewController.swift
// Kingfisher
//
// Created by onevcat on 2024/10/05.
//
// Copyright (c) 2024 Wei Wang <[email protected]>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import UIKit
import PhotosUI
import Kingfisher

class LivePhotoViewController: UIViewController {

private var livePhotoView: PHLivePhotoView!

override func viewDidLoad() {
super.viewDidLoad()
title = "Live Photo"
setupOperationNavigationBar()

livePhotoView = PHLivePhotoView()
livePhotoView.translatesAutoresizingMaskIntoConstraints = false

view.addSubview(livePhotoView)
NSLayoutConstraint.activate([
livePhotoView.heightAnchor.constraint(equalToConstant: 300),
livePhotoView.widthAnchor.constraint(equalToConstant: 300),
livePhotoView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
livePhotoView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -30)
])

let urls = [
"https://github.com/onevcat/Kingfisher-TestImages/raw/refs/heads/master/LivePhotos/live_photo_sample.HEIC",
"https://github.com/onevcat/Kingfisher-TestImages/raw/refs/heads/master/LivePhotos/live_photo_sample.MOV"
].compactMap(URL.init)
livePhotoView.kf.setImage(with: urls, completionHandler: { result in
switch result {
case .success(let r):
print("Live Photo done. \(r.loadingInfo.cacheType)")
print("Info: \(String(describing: r.info))")
case .failure(let error):
print("Live Photo error: \(error)")
}
})
}
}
4 changes: 4 additions & 0 deletions Demo/Kingfisher-Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
D12E0CB61C47F9C100AC98AD /* NormalLoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12E0C941C47F91800AC98AD /* NormalLoadingViewController.swift */; };
D12EB83E24DD902300329EE1 /* TextAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12EB83D24DD902300329EE1 /* TextAttachmentViewController.swift */; };
D12EB84024DDB9E100329EE1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D12EB83F24DDB9E000329EE1 /* LaunchScreen.storyboard */; };
D12F67682CB10AE000AB63AB /* LivePhotoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12F67672CB10AD900AB63AB /* LivePhotoViewController.swift */; };
D1679A461C4E78B20020FD12 /* Kingfisher-watchOS-Demo Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D1679A451C4E78B20020FD12 /* Kingfisher-watchOS-Demo Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
D16CC3D824E03FEA00F1A515 /* AVAssetImageGeneratorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D16CC3D724E03FEA00F1A515 /* AVAssetImageGeneratorViewController.swift */; };
D198F41E25EDC11500C53E0D /* LazyVStackDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D198F41D25EDC11500C53E0D /* LazyVStackDemo.swift */; };
Expand Down Expand Up @@ -204,6 +205,7 @@
D12E0CA11C47F92200AC98AD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D12EB83D24DD902300329EE1 /* TextAttachmentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextAttachmentViewController.swift; sourceTree = "<group>"; };
D12EB83F24DDB9E000329EE1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
D12F67672CB10AD900AB63AB /* LivePhotoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LivePhotoViewController.swift; sourceTree = "<group>"; };
D13F49C21BEDA53F00CE335D /* Kingfisher-tvOS-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Kingfisher-tvOS-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D16218A4238EAA67004A1C6C /* Kingfisher-Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Kingfisher-Demo.entitlements"; sourceTree = "<group>"; };
D1679A391C4E78B20020FD12 /* Kingfisher-watchOS-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Kingfisher-watchOS-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -386,6 +388,7 @@
D1A1CCA921A1936300263AD8 /* ViewControllers */ = {
isa = PBXGroup;
children = (
D12F67672CB10AD900AB63AB /* LivePhotoViewController.swift */,
D10AC99721A300C9005F057C /* ProcessorCollectionViewController.swift */,
4B1C7A3C21A256E300CE9D31 /* InfinityCollectionViewController.swift */,
D1CE1BCF21A1AFA300419000 /* TransitionViewController.swift */,
Expand Down Expand Up @@ -731,6 +734,7 @@
078DCB512BCFEFB40008114E /* PHPickerResultViewController.swift in Sources */,
D1EDF7422C9F01270017FFA5 /* Issue2295View.swift in Sources */,
D1A1CCA321A1879600263AD8 /* MainViewController.swift in Sources */,
D12F67682CB10AE000AB63AB /* LivePhotoViewController.swift in Sources */,
4BC0ED4A29A6EE78003E9CD1 /* Issue2035View.swift in Sources */,
D1F06F3721AAEACF000B1C38 /* GIFViewController.swift in Sources */,
4B120CA726B91BB70060B092 /* TransitionViewDemo.swift in Sources */,
Expand Down
Loading