mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-23 00:40:59 +00:00
Fix flickering issues when resizing window (#1644)
* Fix flickering issues when resizing window, or hiding notifications on macOS * Restore processor and add debouncing to the processor updates * Fix indentation * Add LazyResizableImage to the Design system module
This commit is contained in:
parent
b2550d28ac
commit
b2933b8c75
3 changed files with 59 additions and 23 deletions
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// LazyResizableImage.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Hugo Saynac on 28/10/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Nuke
|
||||||
|
import NukeUI
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
/// A LazyImage (Nuke) with a geometry reader under the hood in order to use a Resize Processor to optimize performances on lists.
|
||||||
|
/// This views also allows smooth resizing of the images by debouncing the update of the ImageProcessor.
|
||||||
|
struct LazyResizableImage<Content: View>: View {
|
||||||
|
init(url: URL?, @ViewBuilder content: @escaping (LazyImageState, GeometryProxy) -> Content) {
|
||||||
|
self.imageURL = url
|
||||||
|
self.content = content
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageURL: URL?
|
||||||
|
@State private var resizeProcessor: ImageProcessors.Resize?
|
||||||
|
@State private var debouncedTask: Task<Void, Never>?
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var content: (LazyImageState, _ proxy: GeometryProxy) -> Content
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
GeometryReader { proxy in
|
||||||
|
LazyImage(url: imageURL) { state in
|
||||||
|
content(state, proxy)
|
||||||
|
}
|
||||||
|
.processors([resizeProcessor == nil ? .resize(size: proxy.size) : resizeProcessor!])
|
||||||
|
.onChange(of: proxy.size, initial: true) { oldValue, newValue in
|
||||||
|
debouncedTask?.cancel()
|
||||||
|
debouncedTask = Task {
|
||||||
|
do { try await Task.sleep(for: .milliseconds(200)) } catch { return }
|
||||||
|
resizeProcessor = .resize(size: newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,27 +47,23 @@ public struct StatusRowCardView: View {
|
||||||
if let title = card.title, let url = URL(string: card.url) {
|
if let title = card.title, let url = URL(string: card.url) {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
if let imageURL = card.image, !isInCaptureMode {
|
if let imageURL = card.image, !isInCaptureMode {
|
||||||
GeometryReader { proxy in
|
LazyResizableImage(url: imageURL) { state, proxy in
|
||||||
let width = imageWidthFor(proxy: proxy)
|
let width = imageWidthFor(proxy: proxy)
|
||||||
let processors: [ImageProcessing] = [.resize(size: .init(width: width, height: imageHeight))]
|
if let image = state.image {
|
||||||
LazyImage(url: imageURL) { state in
|
image
|
||||||
if let image = state.image {
|
.resizable()
|
||||||
image
|
.aspectRatio(contentMode: .fill)
|
||||||
.resizable()
|
.frame(height: imageHeight)
|
||||||
.aspectRatio(contentMode: .fill)
|
.frame(maxWidth: width)
|
||||||
.frame(height: imageHeight)
|
.clipped()
|
||||||
.frame(maxWidth: width)
|
} else if state.isLoading {
|
||||||
.clipped()
|
Rectangle()
|
||||||
} else if state.isLoading {
|
.fill(Color.gray)
|
||||||
Rectangle()
|
.frame(height: imageHeight)
|
||||||
.fill(Color.gray)
|
|
||||||
.frame(height: imageHeight)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.processors(processors)
|
|
||||||
// This image is decorative
|
|
||||||
.accessibilityHidden(true)
|
|
||||||
}
|
}
|
||||||
|
// This image is decorative
|
||||||
|
.accessibilityHidden(true)
|
||||||
.frame(height: imageHeight)
|
.frame(height: imageHeight)
|
||||||
}
|
}
|
||||||
HStack {
|
HStack {
|
||||||
|
|
|
@ -29,7 +29,7 @@ public struct StatusRowMediaPreviewView: View {
|
||||||
|
|
||||||
var availableWidth: CGFloat {
|
var availableWidth: CGFloat {
|
||||||
if UIDevice.current.userInterfaceIdiom == .phone &&
|
if UIDevice.current.userInterfaceIdiom == .phone &&
|
||||||
(UIDevice.current.orientation == .landscapeLeft || UIDevice.current.orientation == .landscapeRight) || theme.statusDisplayStyle == .medium
|
(UIDevice.current.orientation == .landscapeLeft || UIDevice.current.orientation == .landscapeRight) || theme.statusDisplayStyle == .medium
|
||||||
{
|
{
|
||||||
return sceneDelegate.windowWidth * 0.80
|
return sceneDelegate.windowWidth * 0.80
|
||||||
}
|
}
|
||||||
|
@ -217,10 +217,9 @@ public struct StatusRowMediaPreviewView: View {
|
||||||
GeometryReader { proxy in
|
GeometryReader { proxy in
|
||||||
switch type {
|
switch type {
|
||||||
case .image:
|
case .image:
|
||||||
let width = isCompact ? imageMaxHeight : proxy.frame(in: .local).width
|
|
||||||
let processors: [ImageProcessing] = [.resize(size: .init(width: width, height: imageMaxHeight))]
|
|
||||||
ZStack(alignment: .bottomTrailing) {
|
ZStack(alignment: .bottomTrailing) {
|
||||||
LazyImage(url: attachment.previewUrl ?? attachment.url) { state in
|
LazyResizableImage(url: attachment.previewUrl ?? attachment.url) { state, proxy in
|
||||||
|
let width = isCompact ? imageMaxHeight : proxy.frame(in: .local).width
|
||||||
if let image = state.image {
|
if let image = state.image {
|
||||||
image
|
image
|
||||||
.resizable()
|
.resizable()
|
||||||
|
@ -240,7 +239,6 @@ public struct StatusRowMediaPreviewView: View {
|
||||||
.frame(maxWidth: width)
|
.frame(maxWidth: width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.processors(processors)
|
|
||||||
if sensitive, !isInCaptureMode {
|
if sensitive, !isInCaptureMode {
|
||||||
cornerSensitiveButton
|
cornerSensitiveButton
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue