Implement max storage size slider

This commit is contained in:
Ali 2022-12-24 22:34:27 +04:00
parent f7c73e6ccb
commit ae9eb245c4
4 changed files with 304 additions and 6 deletions

View File

@ -37,6 +37,7 @@ swift_library(
"//submodules/UndoUI",
"//submodules/AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode",
"//submodules/LegacyComponents",
],
visibility = [
"//visibility:public",

View File

@ -181,7 +181,7 @@ final class StorageCategoryItemComponent: Component {
let rightInset: CGFloat = 16.0
var availableWidth: CGFloat = availableSize.width - leftInset
var availableWidth: CGFloat = availableSize.width - leftInset - rightInset
if !component.category.subcategories.isEmpty {
let iconView: UIImageView
@ -218,23 +218,23 @@ final class StorageCategoryItemComponent: Component {
let labelSize = self.label.update(
transition: transition,
component: AnyComponent(Text(text: dataSizeString(Int(component.category.size), formatting: DataSizeStringFormatting(strings: component.strings, decimalSeparator: ".")), font: Font.regular(17.0), color: component.theme.list.itemSecondaryTextColor)),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: dataSizeString(Int(component.category.size), formatting: DataSizeStringFormatting(strings: component.strings, decimalSeparator: ".")), font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)))),
environment: {},
containerSize: CGSize(width: availableWidth, height: 100.0)
)
availableWidth = max(1.0, availableWidth - labelSize.width - 4.0)
availableWidth = max(1.0, availableWidth - labelSize.width - 1.0)
let titleValueSize = self.titleValue.update(
transition: transition,
component: AnyComponent(Text(text: "\(fractionString)%", font: Font.regular(17.0), color: component.theme.list.itemSecondaryTextColor)),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "\(fractionString)%", font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)))),
environment: {},
containerSize: CGSize(width: availableWidth, height: 100.0)
)
availableWidth = max(1.0, availableWidth - titleValueSize.width - 1.0)
availableWidth = max(1.0, availableWidth - titleValueSize.width - 4.0)
let titleSize = self.title.update(
transition: transition,
component: AnyComponent(Text(text: component.category.title, font: Font.regular(17.0), color: component.theme.list.itemPrimaryTextColor)),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: component.category.title, font: Font.regular(17.0), textColor: component.theme.list.itemPrimaryTextColor)))),
environment: {},
containerSize: CGSize(width: availableWidth, height: 100.0)
)

View File

@ -0,0 +1,208 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import ComponentFlow
import SwiftSignalKit
import ViewControllerComponent
import ComponentDisplayAdapters
import TelegramPresentationData
import AccountContext
import TelegramCore
import MultilineTextComponent
import EmojiStatusComponent
import Postbox
import CheckNode
import SolidRoundedButtonComponent
import LegacyComponents
private func stringForCacheSize(strings: PresentationStrings, size: Int32) -> String {
if size > 100 {
return strings.Cache_NoLimit
} else {
return dataSizeString(Int64(size) * 1024 * 1024 * 1024, formatting: DataSizeStringFormatting(strings: strings, decimalSeparator: "."))
}
}
private func totalDiskSpace() -> Int64 {
do {
let systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String)
return (systemAttributes[FileAttributeKey.systemSize] as? NSNumber)?.int64Value ?? 0
} catch {
return 0
}
}
private let maximumCacheSizeValues: [Int32] = {
let diskSpace = totalDiskSpace()
if diskSpace > 100 * 1024 * 1024 * 1024 {
return [5, 20, 50, Int32.max]
} else if diskSpace > 50 * 1024 * 1024 * 1024 {
return [5, 16, 32, Int32.max]
} else if diskSpace > 24 * 1024 * 1024 * 1024 {
return [2, 8, 16, Int32.max]
} else {
return [1, 4, 8, Int32.max]
}
}()
final class StorageKeepSizeComponent: Component {
let theme: PresentationTheme
let strings: PresentationStrings
let value: Int32
let updateValue: (Int32) -> Void
init(
theme: PresentationTheme,
strings: PresentationStrings,
value: Int32,
updateValue: @escaping (Int32) -> Void
) {
self.theme = theme
self.strings = strings
self.value = value
self.updateValue = updateValue
}
static func ==(lhs: StorageKeepSizeComponent, rhs: StorageKeepSizeComponent) -> Bool {
if lhs.theme !== rhs.theme {
return false
}
if lhs.strings !== rhs.strings {
return false
}
if lhs.value != rhs.value {
return false
}
return true
}
class View: UIView {
private let titles: [ComponentView<Empty>]
private var sliderView: TGPhotoEditorSliderView?
private var component: StorageKeepSizeComponent?
private weak var state: EmptyComponentState?
override init(frame: CGRect) {
self.titles = (0 ..< 4).map { _ in ComponentView<Empty>() }
super.init(frame: frame)
self.clipsToBounds = true
self.layer.cornerRadius = 10.0
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(component: StorageKeepSizeComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
let themeUpdated = self.component?.theme !== component.theme
self.component = component
self.state = state
if themeUpdated {
self.backgroundColor = component.theme.list.itemBlocksBackgroundColor
}
let height: CGFloat = 88.0
var titleSizes: [CGSize] = []
for i in 0 ..< self.titles.count {
let titleSize = self.titles[i].update(
transition: .immediate,
component: AnyComponent(Text(text: stringForCacheSize(strings: component.strings, size: maximumCacheSizeValues[i]), font: Font.regular(13.0), color: component.theme.list.itemSecondaryTextColor)),
environment: {},
containerSize: CGSize(width: 100.0, height: 100.0)
)
titleSizes.append(titleSize)
}
let delta = (availableSize.width - 18.0 * 2.0) / CGFloat(titleSizes.count - 1)
for i in 0 ..< titleSizes.count {
let titleSize = titleSizes[i]
if let titleView = self.titles[i].view {
if titleView.superview == nil {
self.addSubview(titleView)
}
var position: CGFloat = 18.0 + delta * CGFloat(i)
if i == titleSizes.count - 1 {
position -= titleSize.width
} else if i > 0 {
position -= titleSize.width / 2.0
}
transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: position, y: 15.0), size: titleSize))
}
}
var sliderFirstTime = false
let sliderView: TGPhotoEditorSliderView
if let current = self.sliderView {
sliderView = current
} else {
sliderFirstTime = true
sliderView = TGPhotoEditorSliderView()
sliderView.enablePanHandling = true
sliderView.trackCornerRadius = 2.0
sliderView.lineSize = 4.0
sliderView.dotSize = 5.0
sliderView.minimumValue = 0.0
sliderView.maximumValue = 3.0
sliderView.startValue = 0.0
sliderView.disablesInteractiveTransitionGestureRecognizer = true
sliderView.positionsCount = 4
sliderView.useLinesForPositions = true
sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
self.sliderView = sliderView
self.addSubview(sliderView)
}
if sliderFirstTime || themeUpdated {
sliderView.backgroundColor = component.theme.list.itemBlocksBackgroundColor
sliderView.backColor = component.theme.list.itemSwitchColors.frameColor
sliderView.startColor = component.theme.list.itemSwitchColors.frameColor
sliderView.trackColor = component.theme.list.itemAccentColor
sliderView.knobImage = PresentationResourcesItemList.knobImage(component.theme)
}
transition.setFrame(view: sliderView, frame: CGRect(origin: CGPoint(x: 15.0, y: 37.0), size: CGSize(width: availableSize.width - 15.0 * 2.0, height: 44.0)))
sliderView.hitTestEdgeInsets = UIEdgeInsets(top: -sliderView.frame.minX, left: 0.0, bottom: 0.0, right: -sliderView.frame.minX)
self.updateSliderView()
return CGSize(width: availableSize.width, height: height)
}
private func updateSliderView() {
guard let sliderView = self.sliderView, let component = self.component else {
return
}
sliderView.maximumValue = 3.0
sliderView.positionsCount = 4
let value = maximumCacheSizeValues.firstIndex(where: { $0 == component.value }) ?? 0
sliderView.value = CGFloat(value)
}
@objc private func sliderValueChanged() {
guard let component = self.component, let sliderView = self.sliderView else {
return
}
let position = Int(sliderView.value)
let value = maximumCacheSizeValues[position]
component.updateValue(value)
}
}
func makeView() -> View {
return View(frame: CGRect())
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}

View File

@ -262,6 +262,10 @@ final class StorageUsageScreenComponent: Component {
private var keepDurationSectionContainerView: UIView
private var keepDurationItems: [AnyHashable: ComponentView<Empty>] = [:]
private let keepSizeTitleView = ComponentView<Empty>()
private let keepSizeView = ComponentView<Empty>()
private let keepSizeDescriptionView = ComponentView<Empty>()
private let panelContainer = ComponentView<StorageUsagePanelContainerEnvironment>()
private var selectionPanel: ComponentView<Empty>?
@ -1261,6 +1265,91 @@ final class StorageUsageScreenComponent: Component {
}
contentHeight += keepDurationDescriptionSize.height
contentHeight += 40.0
//TODO:localize
let keepSizeTitleSize = self.keepSizeTitleView.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .markdown(
text: "MAXIMUM CACHE SIZE", attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
linkAttribute: { _ in nil }
)
),
maximumNumberOfLines: 0
)),
environment: {},
containerSize: CGSize(width: availableSize.width - sideInset * 2.0 - 15.0 * 2.0, height: 10000.0)
)
let keepSizeTitleFrame = CGRect(origin: CGPoint(x: sideInset + 15.0, y: contentHeight), size: keepSizeTitleSize)
if let keepSizeTitleComponentView = self.keepSizeTitleView.view {
if keepSizeTitleComponentView.superview == nil {
self.scrollView.addSubview(keepSizeTitleComponentView)
}
transition.setFrame(view: keepSizeTitleComponentView, frame: keepSizeTitleFrame)
}
contentHeight += keepSizeTitleSize.height
contentHeight += 8.0
let keepSizeSize = self.keepSizeView.update(
transition: transition,
component: AnyComponent(StorageKeepSizeComponent(
theme: environment.theme,
strings: environment.strings,
value: cacheSettings?.defaultCacheStorageLimitGigabytes ?? 32,
updateValue: { [weak self] value in
guard let self, let component = self.component else {
return
}
let value = max(5, value)
let _ = updateCacheStorageSettingsInteractively(accountManager: component.context.sharedContext.accountManager, { current in
var current = current
current.defaultCacheStorageLimitGigabytes = value
return current
}).start()
}
)),
environment: {},
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 10000.0)
)
let keepSizeFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: keepSizeSize)
if let keepSizeComponentView = self.keepSizeView.view {
if keepSizeComponentView.superview == nil {
self.scrollView.addSubview(keepSizeComponentView)
}
transition.setFrame(view: keepSizeComponentView, frame: keepSizeFrame)
}
contentHeight += keepSizeSize.height
contentHeight += 8.0
//TODO:localize
let keepSizeDescriptionSize = self.keepSizeDescriptionView.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .markdown(
text: "If your cache size exceeds this limit, the oldest media will be deleted.", attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
linkAttribute: { _ in nil }
)
),
maximumNumberOfLines: 0
)),
environment: {},
containerSize: CGSize(width: availableSize.width - sideInset * 2.0 - 15.0 * 2.0, height: 10000.0)
)
let keepSizeDescriptionFrame = CGRect(origin: CGPoint(x: sideInset + 15.0, y: contentHeight), size: keepSizeDescriptionSize)
if let keepSizeDescriptionComponentView = self.keepSizeDescriptionView.view {
if keepSizeDescriptionComponentView.superview == nil {
self.scrollView.addSubview(keepSizeDescriptionComponentView)
}
transition.setFrame(view: keepSizeDescriptionComponentView, frame: keepSizeDescriptionFrame)
}
contentHeight += keepSizeDescriptionSize.height
contentHeight += 40.0
}
var panelItems: [StorageUsagePanelContainerComponent.Item] = []