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

Master #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
92916E73642C37BE58708AF3 /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCCA8121B9612C855EEA90E3 /* Pods_Demo.framework */; };
BE0DBBF41DF888BD0076F39D /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE0DBBF31DF888BD0076F39D /* SettingsViewController.swift */; };
C5E01A5F1D642D43005E9818 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5E01A5E1D642D43005E9818 /* AppDelegate.swift */; };
C5E01A641D642D43005E9818 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5E01A621D642D43005E9818 /* Main.storyboard */; };
C5E01A661D642D43005E9818 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C5E01A651D642D43005E9818 /* Assets.xcassets */; };
Expand All @@ -21,6 +22,7 @@
/* Begin PBXFileReference section */
5D9AA14256E74D4E0D365E61 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig"; sourceTree = "<group>"; };
7CD429E81E5908491417D5B7 /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = "<group>"; };
BE0DBBF31DF888BD0076F39D /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
C5E01A5B1D642D43005E9818 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
C5E01A5E1D642D43005E9818 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
C5E01A631D642D43005E9818 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
Expand Down Expand Up @@ -88,6 +90,7 @@
C5E01A5E1D642D43005E9818 /* AppDelegate.swift */,
C5E01A731D64386E005E9818 /* ChatViewController.swift */,
C5E01A711D64386E005E9818 /* ImageViewController.swift */,
BE0DBBF31DF888BD0076F39D /* SettingsViewController.swift */,
C5E01A741D64386E005E9818 /* DemoConversation.swift */,
C5E01A701D64386E005E9818 /* ExampleForceBlurPhotoMediaItem.swift */,
C5E01A651D642D43005E9818 /* Assets.xcassets */,
Expand Down Expand Up @@ -222,6 +225,7 @@
buildActionMask = 2147483647;
files = (
C5E01A791D64386E005E9818 /* DemoConversation.swift in Sources */,
BE0DBBF41DF888BD0076F39D /* SettingsViewController.swift in Sources */,
C5E01A5F1D642D43005E9818 /* AppDelegate.swift in Sources */,
C5E01A761D64386E005E9818 /* ImageViewController.swift in Sources */,
C5E01A781D64386E005E9818 /* ChatViewController.swift in Sources */,
Expand Down
65 changes: 60 additions & 5 deletions Demo/Demo/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="imC-b6-WCj">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11761" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -17,7 +21,9 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="preview" translatesAutoresizingMaskIntoConstraints="NO" id="u3V-fI-R3I" customClass="ForceBlurImageView" customModule="ForceBlur"/>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="preview" translatesAutoresizingMaskIntoConstraints="NO" id="u3V-fI-R3I" customClass="ForceBlurImageView" customModule="ForceBlur">
<rect key="frame" x="0.0" y="64" width="375" height="603"/>
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
Expand All @@ -33,14 +39,63 @@
<action selector="close:" destination="imC-b6-WCj" id="UNC-kB-v6R"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" title="Settings" id="JIo-wb-DUB"/>
</navigationItem>
<connections>
<outlet property="imageView" destination="u3V-fI-R3I" id="Vjj-Qb-95L"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="kLp-VH-bVo" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3666" y="1362"/>
<point key="canvasLocation" x="4604" y="1361.4692653673164"/>
</scene>
<!--Settings View Controller-->
<scene sceneID="jAy-Qk-Enw">
<objects>
<viewController storyboardIdentifier="SettingsViewControllerStoryBoardID" id="Q2n-nE-xOm" customClass="SettingsViewController" customModule="Demo" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="cBM-JH-RhL"/>
<viewControllerLayoutGuide type="bottom" id="ZXk-G4-Wev"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="czB-Wq-eNM">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="lKC-Ae-yIh">
<rect key="frame" x="22" y="318" width="331" height="31"/>
<connections>
<action selector="valueChanged:" destination="Q2n-nE-xOm" eventType="valueChanged" id="SZw-7A-9ll"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5yv-PV-dF3">
<rect key="frame" x="166" y="275" width="42" height="21"/>
<constraints>
<constraint firstAttribute="width" constant="42" id="5up-vU-L4u"/>
<constraint firstAttribute="height" constant="21" id="urW-QM-Iqi"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="lKC-Ae-yIh" secondAttribute="trailing" constant="8" id="0QA-zq-IGQ"/>
<constraint firstItem="lKC-Ae-yIh" firstAttribute="top" secondItem="5yv-PV-dF3" secondAttribute="bottom" constant="22" id="41j-Xu-KgX"/>
<constraint firstItem="5yv-PV-dF3" firstAttribute="centerX" secondItem="czB-Wq-eNM" secondAttribute="centerX" id="4aW-d2-Y9G"/>
<constraint firstItem="lKC-Ae-yIh" firstAttribute="centerX" secondItem="czB-Wq-eNM" secondAttribute="centerX" id="TB2-mP-MSv"/>
<constraint firstItem="lKC-Ae-yIh" firstAttribute="centerY" secondItem="czB-Wq-eNM" secondAttribute="centerY" id="XMo-8q-a2V"/>
<constraint firstItem="lKC-Ae-yIh" firstAttribute="leading" secondItem="czB-Wq-eNM" secondAttribute="leadingMargin" constant="8" id="ZqM-y7-2Gt"/>
</constraints>
</view>
<connections>
<outlet property="label" destination="5yv-PV-dF3" id="J6a-wI-XQm"/>
<outlet property="slider" destination="lKC-Ae-yIh" id="TSk-Ae-ZG1"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="PFG-fF-bHs" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="5488.8000000000002" y="1360.569715142429"/>
</scene>
</scenes>
<resources>
Expand Down
36 changes: 33 additions & 3 deletions Demo/Demo/ChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@

import UIKit
import JSQMessagesViewController

class ChatViewController: JSQMessagesViewController {
import ForceBlur

class ChatViewController: JSQMessagesViewController, SettingsSliderChangeable {

var messages = DemoConversation
var incomingBubble: JSQMessagesBubbleImage!
var outgoingBubble: JSQMessagesBubbleImage!
var radius: CGFloat = 10

override func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -27,6 +29,20 @@ class ChatViewController: JSQMessagesViewController {

collectionView?.collectionViewLayout.incomingAvatarViewSize = .zero
collectionView?.collectionViewLayout.outgoingAvatarViewSize = .zero

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "settings", style: .plain, target: self, action: #selector(settingsButtonTapped))
}

func settingsButtonTapped() {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SettingsViewControllerStoryBoardID") as! SettingsViewController
vc.radius = radius
vc.delegate = self
navigationController?.pushViewController(vc, animated: true)
}

func valueChanged(value: CGFloat) {
radius = value
self.collectionView.reloadData()
}

// MARK: JSQMessagesViewController method overrides
Expand All @@ -40,6 +56,7 @@ class ChatViewController: JSQMessagesViewController {

override func didPressAccessoryButton(_ sender: UIButton) {
let media = ExampleForceBlurPhotoMediaItem(image: UIImage(named: "preview"))
media?.radius = radius
let message = JSQMessage(senderId: senderId, displayName: senderDisplayName, media: media)
messages.append(message!)

Expand All @@ -53,7 +70,20 @@ class ChatViewController: JSQMessagesViewController {
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, messageDataForItemAt indexPath: IndexPath) -> JSQMessageData {
return messages[(indexPath as NSIndexPath).item]
var message = messages[(indexPath as NSIndexPath).item]
if let _ = message.media as? ForceBlurPhotoMediaItem {
let photoItem: ForceBlurPhotoMediaItem = {
let photoItem = ExampleForceBlurPhotoMediaItem(image: UIImage(named: "preview"))!
photoItem.appliesMediaViewMaskAsOutgoing = false
photoItem.radius = radius

return photoItem
}()

message = JSQMessage(senderId: WomanID, displayName: WomanName, media: photoItem)!
}

return message
}

override func collectionView(_ collectionView: JSQMessagesCollectionView, messageBubbleImageDataForItemAt indexPath: IndexPath) -> JSQMessageBubbleImageDataSource {
Expand Down
1 change: 1 addition & 0 deletions Demo/Demo/DemoConversation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ let DemoConversation: [JSQMessage] = {
let photoItem: ForceBlurPhotoMediaItem = {
let photoItem = ExampleForceBlurPhotoMediaItem(image: UIImage(named: "preview"))!
photoItem.appliesMediaViewMaskAsOutgoing = false
//photoItem.radius = 10
return photoItem
}()
let photoMessage2 = JSQMessage(senderId: WomanID, displayName: WomanName, media: photoItem)!
Expand Down
44 changes: 44 additions & 0 deletions Demo/Demo/SettingsViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// SettingsViewController.swift
// Demo
//
// Created by Klevison Matias on 12/7/16.
// Copyright © 2016 Yalantis. All rights reserved.
//

import UIKit

protocol SettingsSliderChangeable {

func valueChanged(value: CGFloat)

}

final class SettingsViewController: UIViewController {

@IBOutlet weak var slider: UISlider!
@IBOutlet weak var label: UILabel!
var radius: CGFloat!
var delegate: SettingsSliderChangeable?


override func viewDidLoad() {
super.viewDidLoad()

slider.maximumValue = 100
slider.minimumValue = 0
slider.value = Float(radius)
self.label.text = "\(Int(radius!))%"

}

@IBAction func valueChanged(_ sender: Any) {
let slider = sender as! UISlider
let currentValue = Int(slider.value)
DispatchQueue.main.async {
self.label.text = "\(currentValue)%"
self.delegate?.valueChanged(value: CGFloat(currentValue))
}
}

}
53 changes: 33 additions & 20 deletions ForceBlur/Classes/SecureImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,78 +11,91 @@ import Darwin

/// Displays an image with blur.
open class ForceBlurImageView: UIImageView {
/// Gets called when pressure changes.

/// Gets called when pressure changes.
/// - warning: On devices without 3d touch it's called with 0, 1 values.
open var pressureChanged: ((CGFloat) -> Void)?

var recognizer: PressureGestureRecognizer!

@objc fileprivate var maskLayer: RadialLayer!

// There should be UIVisualEffectView, but a mask cannot be applied to it on iOS 10: https://forums.developer.apple.com/thread/50854
fileprivate let blurredImageView = UIImageView()

let defaultRadius: CGFloat = 30
open var radius: CGFloat! {
didSet {
blurredImageView.image = image?.applyLightEffect(radius: radius ?? defaultRadius)
}
}

open override var image: UIImage? {
didSet {
blurredImageView.image = image?.applyLightEffect()
blurredImageView.image = image?.applyLightEffect(radius: radius ?? defaultRadius)
blurredImageView.frame = bounds
}
}

open override var contentMode: UIViewContentMode {
didSet {
blurredImageView.contentMode = contentMode
}
}

public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)

setupSubviews()
}

public override init(frame: CGRect = .zero) {
super.init(frame: frame)

setupSubviews()
}

public override init(image: UIImage?) {
super.init(image: image)


setupSubviews()
}

init(image: UIImage?, radius: CGFloat) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If should have a default radius to not break API

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let defaultRadius: CGFloat = 30 (line 25) is the default radius.

self.radius = radius
super.init(image: image)

setupSubviews()
}

fileprivate func setupSubviews() {
recognizer = PressureGestureRecognizer(target: self, action: #selector(tap))
addGestureRecognizer(recognizer)

isUserInteractionEnabled = true

maskLayer = RadialLayer()
maskLayer.frame = bounds
blurredImageView.layer.mask = maskLayer

addSubview(blurredImageView)
}

open override func layoutSubviews() {
super.layoutSubviews()

blurredImageView.frame = bounds
maskLayer.frame = bounds
}
}

// Unblur
private extension ForceBlurImageView {

@objc func tap(_ sender: PressureGestureRecognizer) {
let force = sender.force
pressureChanged?(force)
print("force: \(sender.force); state: \(sender.state.rawValue)")

let fromRadius = maskLayer.radius
stopPerformingTweens()
maskLayer.origin = recognizer.location(in: self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import JSQMessagesViewController
open class ForceBlurPhotoMediaItem: JSQPhotoMediaItem {

open var secureImageView: ForceBlurImageView!

public var radius: CGFloat!
fileprivate var chachedView: UIView?

open override func mediaView() -> UIView? {
guard let image = image else { return nil }
guard chachedView == nil else { return chachedView! }

secureImageView = ForceBlurImageView(image: image)
secureImageView = ForceBlurImageView(image: image, radius: radius)
secureImageView.frame = CGRect(origin: .zero, size: mediaViewDisplaySize())
secureImageView.contentMode = .scaleAspectFill
secureImageView.clipsToBounds = true
Expand Down
4 changes: 2 additions & 2 deletions ForceBlur/Vendor/UIImageEffects.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ import UIKit
import Accelerate

public extension UIImage {
public func applyLightEffect() -> UIImage? {
return applyBlurWithRadius(30, tintColor: UIColor(white: 1.0, alpha: 0.3), saturationDeltaFactor: 1.8)
public func applyLightEffect(radius: CGFloat) -> UIImage? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has the same radius as UIBlurEffectStyleLight. You mustn't change radius here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my project I don't want to use default UIBlurEffectStyleLight, so why not another value?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should create a new effect instead of changing this one

return applyBlurWithRadius(radius, tintColor: UIColor(white: 1.0, alpha: 0.3), saturationDeltaFactor: 1.8)
}

public func applyExtraLightEffect() -> UIImage? {
Expand Down