mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-29 07:42:40 +00:00
Create room avatar view.
This commit is contained in:
parent
d451788b35
commit
e134633cf4
2 changed files with 224 additions and 0 deletions
149
Riot/Modules/Room/Views/Avatar/RoomAvatarView.swift
Normal file
149
Riot/Modules/Room/Views/Avatar/RoomAvatarView.swift
Normal file
|
@ -0,0 +1,149 @@
|
|||
//
|
||||
// Copyright 2020 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Reusable
|
||||
|
||||
final class RoomAvatarView: UIView, NibOwnerLoadable, Themable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var avatarImageView: MXKImageView!
|
||||
@IBOutlet private weak var cameraBadgeContainerView: UIView!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme?
|
||||
|
||||
private var isHighlighted: Bool = false {
|
||||
didSet {
|
||||
self.updateView()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var action: (() -> Void)?
|
||||
|
||||
// MARK: Setup
|
||||
|
||||
private func commonInit() {
|
||||
self.setupAvatarImageView()
|
||||
self.setupGestureRecognizer()
|
||||
self.vc_setupAccessibilityTraitsButton(withTitle: VectorL10n.roomAvatarViewAccessibilityLabel, hint: VectorL10n.roomAvatarViewAccessibilityHint, isEnabled: true)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.loadNibContent()
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.loadNibContent()
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.height/2
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func fill(with viewData: RoomAvatarViewData) {
|
||||
self.updateAvatarImageView(with: viewData)
|
||||
|
||||
// Fix layoutSubviews not triggered issue
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupGestureRecognizer() {
|
||||
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(buttonAction(_:)))
|
||||
gestureRecognizer.minimumPressDuration = 0
|
||||
self.addGestureRecognizer(gestureRecognizer)
|
||||
}
|
||||
|
||||
private func setupAvatarImageView() {
|
||||
self.avatarImageView.defaultBackgroundColor = UIColor.clear
|
||||
self.avatarImageView.enableInMemoryCache = true
|
||||
self.avatarImageView.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
private func updateAvatarImageView(with viewData: RoomAvatarViewData) {
|
||||
guard let avatarImageView = self.avatarImageView else {
|
||||
return
|
||||
}
|
||||
|
||||
let defaultavatarImage = AvatarGenerator.generateAvatar(forMatrixItem: viewData.roomId, withDisplayName: viewData.roomDisplayName)
|
||||
|
||||
if let avatarUrl = viewData.avatarUrl {
|
||||
avatarImageView.setImageURI(avatarUrl,
|
||||
withType: nil,
|
||||
andImageOrientation: .up,
|
||||
toFitViewSize: avatarImageView.frame.size,
|
||||
with: MXThumbnailingMethodScale,
|
||||
previewImage: defaultavatarImage,
|
||||
mediaManager: viewData.mediaManager)
|
||||
} else {
|
||||
avatarImageView.image = defaultavatarImage
|
||||
}
|
||||
|
||||
avatarImageView.contentMode = .scaleAspectFill
|
||||
|
||||
self.cameraBadgeContainerView.isHidden = viewData.avatarUrl != nil
|
||||
}
|
||||
|
||||
private func updateView() {
|
||||
// TODO: Handle highlighted state
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func buttonAction(_ sender: UILongPressGestureRecognizer) {
|
||||
|
||||
let isBackgroundViewTouched = sender.vc_isTouchingInside()
|
||||
|
||||
switch sender.state {
|
||||
case .began, .changed:
|
||||
self.isHighlighted = isBackgroundViewTouched
|
||||
case .ended:
|
||||
self.isHighlighted = false
|
||||
|
||||
if isBackgroundViewTouched {
|
||||
self.action?()
|
||||
}
|
||||
case .cancelled:
|
||||
self.isHighlighted = false
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
75
Riot/Modules/Room/Views/Avatar/RoomAvatarView.xib
Normal file
75
Riot/Modules/Room/Views/Avatar/RoomAvatarView.xib
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RoomAvatarView" customModule="Riot" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="avatarImageView" destination="ln9-Sd-GKd" id="9Zd-LM-hgl"/>
|
||||
<outlet property="cameraBadgeContainerView" destination="0YT-CK-WjK" id="T31-nq-8PB"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iK1-yG-fEu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ln9-Sd-GKd" customClass="MXKImageView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0YT-CK-WjK">
|
||||
<rect key="frame" x="56" y="56" width="24" height="24"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="capture_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="vGE-Mx-xPX">
|
||||
<rect key="frame" x="0.0" y="0.0" width="24" height="24"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="24" id="AIT-k4-SJZ"/>
|
||||
<constraint firstItem="vGE-Mx-xPX" firstAttribute="leading" secondItem="0YT-CK-WjK" secondAttribute="leading" id="IoL-FC-x3t"/>
|
||||
<constraint firstAttribute="trailing" secondItem="vGE-Mx-xPX" secondAttribute="trailing" id="KDL-CV-LNm"/>
|
||||
<constraint firstItem="vGE-Mx-xPX" firstAttribute="top" secondItem="0YT-CK-WjK" secondAttribute="top" id="PLP-FV-9fe"/>
|
||||
<constraint firstAttribute="bottom" secondItem="vGE-Mx-xPX" secondAttribute="bottom" id="bIo-ge-7Ud"/>
|
||||
<constraint firstAttribute="width" constant="24" id="ugV-gr-fbC"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="0YT-CK-WjK" secondAttribute="trailing" id="8HT-uc-Dd2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ln9-Sd-GKd" secondAttribute="trailing" id="ABF-Wz-ZZy"/>
|
||||
<constraint firstAttribute="height" constant="80" id="GdE-dy-bxN"/>
|
||||
<constraint firstAttribute="width" constant="80" id="NCu-Xg-4p3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ln9-Sd-GKd" secondAttribute="bottom" id="NZp-ao-R0Q"/>
|
||||
<constraint firstItem="ln9-Sd-GKd" firstAttribute="top" secondItem="iK1-yG-fEu" secondAttribute="top" id="VZt-Uu-toa"/>
|
||||
<constraint firstItem="ln9-Sd-GKd" firstAttribute="leading" secondItem="iK1-yG-fEu" secondAttribute="leading" id="jEs-Ac-ock"/>
|
||||
<constraint firstAttribute="bottom" secondItem="0YT-CK-WjK" secondAttribute="bottom" id="wIN-TR-RZm"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="iK1-yG-fEu" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="GZx-C7-FF8"/>
|
||||
<constraint firstAttribute="trailing" secondItem="iK1-yG-fEu" secondAttribute="trailing" id="UPO-MZ-XUZ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="iK1-yG-fEu" secondAttribute="bottom" id="g7y-SL-f3s"/>
|
||||
<constraint firstItem="iK1-yG-fEu" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="imn-uW-TTP"/>
|
||||
</constraints>
|
||||
<nil key="simulatedTopBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="-433" y="-802"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="capture_avatar" width="25" height="25"/>
|
||||
</resources>
|
||||
</document>
|
Loading…
Reference in a new issue