-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1141 from anyproto/ios-2381-improve-iconview
iOS-2381 IconView | Migrate to swiftui api 🤞
- Loading branch information
Showing
34 changed files
with
371 additions
and
811 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Common/CircleGradientView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import Foundation | ||
import SwiftUI | ||
import AnytypeCore | ||
|
||
struct CircleGradientView: View { | ||
|
||
private let storage = IconGradientStorage() | ||
private let gradientInfo: IconGradient | ||
|
||
init(gradientId: GradientId) { | ||
self.gradientInfo = storage.gradient(for: gradientId.rawValue) | ||
} | ||
|
||
var body: some View { | ||
GeometryReader { reader in | ||
RadialGradient( | ||
colors: [ | ||
gradientInfo.centerColor.suColor, | ||
gradientInfo.roundColor.suColor | ||
], | ||
center: .center, | ||
startRadius: 0, | ||
endRadius: reader.size.width * 0.5 | ||
) | ||
.clipShape(Circle()) | ||
} | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Common/ImageCharIconView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import Foundation | ||
import SwiftUI | ||
|
||
struct ImageCharIconView: View { | ||
|
||
private struct Config { | ||
let side: CGFloat | ||
let fontSize: CGFloat | ||
|
||
static let zero = Config(side: 0, fontSize: 0) | ||
} | ||
|
||
private static let configs = [ | ||
Config(side: 16, fontSize: 12), | ||
Config(side: 18, fontSize: 14), | ||
Config(side: 40, fontSize: 24), | ||
Config(side: 48, fontSize: 30), | ||
Config(side: 64, fontSize: 36), | ||
Config(side: 80, fontSize: 48) | ||
].sorted(by: { $0.side > $1.side }) // Order by DESC side for simple search | ||
|
||
let text: String | ||
|
||
var body: some View { | ||
GeometryReader { reader in | ||
ZStack(alignment: .center) { | ||
Text(text.prefix(1).uppercased()) | ||
.foregroundColor(Color.Text.white) | ||
.font(font(size: reader.size)) | ||
} | ||
.frame(width: reader.size.width, height: reader.size.height) | ||
} | ||
} | ||
|
||
private func font(size: CGSize) -> Font { | ||
let side = min(size.width, size.height) | ||
let config = Self.configs.first(where: { $0.side <= side }) ?? Self.configs.last ?? .zero | ||
return AnytypeFontBuilder.font(name: .inter, size: config.fontSize, weight: .semibold) | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/Common/ImageIdIconView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Foundation | ||
import SwiftUI | ||
|
||
struct ImageIdIconView: View { | ||
|
||
let imageId: String | ||
|
||
var body: some View { | ||
GeometryReader { reader in | ||
let side = min(reader.size.width, reader.size.height) | ||
AsyncImage( | ||
url: ImageMetadata(id: imageId, width: .width(side)).contentUrl | ||
) { image in | ||
image.resizable().scaledToFill() | ||
} placeholder: { | ||
EmptyView() | ||
} | ||
.frame(width: side, height: side) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 21 additions & 60 deletions
81
Anytype/Sources/PresentationLayer/Common/SwiftUI/IconView/IconView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,37 @@ | ||
import Foundation | ||
import SwiftUI | ||
import Services | ||
|
||
struct IconView: View { | ||
|
||
let icon: Icon? | ||
|
||
@State private var task: Task<Void, Never>? | ||
@State private var size: CGSize? | ||
@State private var placeholderImage: UIImage? | ||
@State private var image: UIImage? | ||
@State private var id = UUID() | ||
|
||
@Environment(\.isEnabled) private var isEnable | ||
@Environment(\.redactionReasons) var redactionReasons | ||
|
||
// MARK: - Public properties | ||
|
||
var body: some View { | ||
content | ||
.readSize { newSize in | ||
size = newSize | ||
} | ||
.onChange(of: isEnable) { isEnable in | ||
updateIcon(isEnable: isEnable) | ||
} | ||
.onChange(of: size) { size in | ||
updateIcon(size: size) | ||
} | ||
.onChange(of: icon) { icon in | ||
// Icon field from struct contains old value | ||
updateIcon(icon) | ||
switch icon { | ||
case .object(let objectIcon): | ||
ObjectIconView(icon: objectIcon) | ||
case .asset(let imageAsset): | ||
Image(asset: imageAsset) | ||
.buttonDynamicForegroundColor() | ||
case .image(let uIImage): | ||
Image(uiImage: uIImage) | ||
.buttonDynamicForegroundColor() | ||
case nil: | ||
EmptyView() | ||
} | ||
.frame(idealWidth: 30, idealHeight: 30) // Default frame | ||
.id(id) | ||
} | ||
|
||
// Root view should be a image view for apply initial frame. | ||
// Don't use a viewbuilder, because view builder make a container | ||
private var content: Image { | ||
if redactionReasons.contains(.placeholder) { | ||
return systemPlaceholder | ||
} else if let image { | ||
return Image(uiImage: image) | ||
} else if let placeholderImage { | ||
return Image(uiImage: placeholderImage) | ||
} else { | ||
return systemPlaceholder | ||
} | ||
} | ||
|
||
extension IconView { | ||
init(asset: ImageAsset) { | ||
self = IconView(icon: .asset(asset)) | ||
} | ||
|
||
private var systemPlaceholder: Image { | ||
// Empty image for native placeholder | ||
Image(uiImage: UIImage()) | ||
.resizable() | ||
init(object: ObjectIcon) { | ||
self = IconView(icon: .object(object)) | ||
} | ||
|
||
private func updateIcon(_ newIcon: Icon? = nil, size newSize: CGSize? = nil, isEnable newIsEnable: Bool? = nil) { | ||
task?.cancel() | ||
guard let icon = newIcon ?? icon, let size = newSize ?? size else { | ||
placeholderImage = nil | ||
image = nil | ||
return | ||
} | ||
let isEnable = newIsEnable ?? isEnable | ||
let maker = IconMaker(icon: icon, size: size, iconContext: IconContext(isEnabled: isEnable)) | ||
if let imageFromCache = maker.makeFromCache() { | ||
image = imageFromCache | ||
} else { | ||
task = Task { @MainActor in | ||
placeholderImage = maker.makePlaceholder() | ||
image = await maker.make() | ||
} | ||
} | ||
init(uiImage: UIImage) { | ||
self = IconView(icon: .image(uiImage)) | ||
} | ||
} |
44 changes: 0 additions & 44 deletions
44
...esentationLayer/Common/SwiftUI/IconView/Painters/Common/Container/CircleIconPainter.swift
This file was deleted.
Oops, something went wrong.
48 changes: 0 additions & 48 deletions
48
...esentationLayer/Common/SwiftUI/IconView/Painters/Common/Container/SquareIconPainter.swift
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.