Storage management improvements

This commit is contained in:
Ali 2022-12-25 01:54:30 +04:00
parent c714d23730
commit 4d84b04173
7 changed files with 257 additions and 68 deletions

View File

@ -8561,3 +8561,33 @@ Sorry for the inconvenience.";
"Paint.MoveForward" = "Move Forward";
"StorageManagement.Title" = "Storage Usage";
"StorageManagement.TitleCleared" = "Storage Cleared";
"StorageManagement.DescriptionCleared" = "All media can be re-downloaded from the Telegram cloud if you need it again.";
"StorageManagement.DescriptionChatUsage" = "This chat uses %1$@%% of your Telegram cache.";
"StorageManagement.DescriptionAppUsage" = "Telegram uses %1$@%% of your free disk space.";
"StorageManagement.ClearAll" = "Clear All Cache";
"StorageManagement.ClearSelected" = "Clear Selected";
"StorageManagement.SectionPhotos" = "Photos";
"StorageManagement.SectionVideos" = "Videos";
"StorageManagement.SectionFiles" = "Files";
"StorageManagement.SectionMusic" = "Music";
"StorageManagement.SectionOther" = "Other";
"StorageManagement.SectionStickers" = "Stickers";
"StorageManagement.SectionAvatars" = "Avatars";
"StorageManagement.SectionMiscellaneous" = "Miscellaneous";
"StorageManagement.SectionsDescription" = "All media will stay in the Telegram cloud and can be re-downloaded if you need it again.";
"StorageManagement.AutoremoveHeader" = "AUTO-REMOVE CACHED MEDIA";
"StorageManagement.AutoremoveDescription" = "Photos, videos and other files from cloud chats that you have **not accessed** during this period will be removed from this device to save disk space.";
"StorageManagement.AutoremoveSpaceDescription" = "If your cache size exceeds this limit, the oldest media will be deleted.";
"StorageManagement.TabChats" = "Chats";
"StorageManagement.TabMedia" = "Media";
"StorageManagement.TabFiles" = "Files";
"StorageManagement.TabMusic" = "Music";

View File

@ -84,6 +84,54 @@ private func processChartData(data: PieChartComponent.ChartData) -> PieChartComp
return data
}
private let chartLabelFont = Font.with(size: 16.0, design: .round, weight: .semibold)
private final class ChartLabel: UIView {
private let label: ImmediateTextView
private var currentText: String?
override init(frame: CGRect) {
self.label = ImmediateTextView()
super.init(frame: frame)
self.addSubview(self.label)
}
required init(coder: NSCoder) {
preconditionFailure()
}
func update(text: String) -> CGSize {
if self.currentText == text {
return self.label.bounds.size
}
var snapshotView: UIView?
if self.currentText != nil {
snapshotView = self.label.snapshotView(afterScreenUpdates: false)
snapshotView?.frame = self.label.frame
}
self.currentText = text
self.label.attributedText = NSAttributedString(string: text, font: chartLabelFont, textColor: .white)
let size = self.label.updateLayout(CGSize(width: 100.0, height: 100.0))
self.label.frame = CGRect(origin: CGPoint(x: floor(-size.width * 0.5), y: floor(-size.height * 0.5)), size: size)
if let snapshotView {
self.addSubview(snapshotView)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
snapshotView.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, removeOnCompletion: false)
self.label.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.label.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
}
return size
}
}
final class PieChartComponent: Component {
struct ChartData: Equatable {
struct Item: Equatable {
@ -136,7 +184,7 @@ final class PieChartComponent: Component {
private var currentAnimation: (start: ChartData, end: ChartData, current: ChartData, progress: CGFloat)?
private var animator: DisplayLinkAnimator?
private var labels: [StorageUsageScreenComponent.Category: ComponentView<Empty>] = [:]
private var labels: [StorageUsageScreenComponent.Category: ChartLabel] = [:]
override init(frame: CGRect) {
super.init(frame: frame)
@ -195,7 +243,7 @@ final class PieChartComponent: Component {
guard let context = UIGraphicsGetCurrentContext() else {
return
}
guard let theme = self.theme, let data = self.currentAnimation?.current ?? self.data else {
guard let _ = self.theme, let data = self.currentAnimation?.current ?? self.data else {
return
}
if data.items.isEmpty {
@ -267,14 +315,14 @@ final class PieChartComponent: Component {
fractionString = "\(fractionValue)"
}
let label: ComponentView<Empty>
let label: ChartLabel
if let current = self.labels[item.id] {
label = current
} else {
label = ComponentView<Empty>()
label = ChartLabel()
self.labels[item.id] = label
}
let labelSize = label.update(transition: .immediate, component: AnyComponent(Text(text: "\(fractionString)%", font: Font.with(size: 16.0, design: .round, weight: .semibold), color: theme.list.itemCheckColors.foregroundColor)), environment: {}, containerSize: CGSize(width: 100.0, height: 100.0))
let labelSize = label.update(text: "\(fractionString)%")
var labelFrame: CGRect?
@ -408,14 +456,14 @@ final class PieChartComponent: Component {
labelFrame = CGRect(origin: CGPoint(x: labelCenter.x - minSize.width * 0.5, y: labelCenter.y - minSize.height * 0.5), size: minSize)
}
if let labelView = label.view, let labelFrame {
let labelView = label
if let labelFrame {
var animateIn: Bool = false
if labelView.superview == nil {
animateIn = true
self.addSubview(labelView)
}
labelView.bounds = CGRect(origin: CGPoint(), size: labelSize)
var labelScale = labelFrame.width / labelSize.width
let normalAlpha: CGFloat = labelScale < 0.4 ? 0.0 : 1.0

View File

@ -199,13 +199,13 @@ final class StorageCategoriesComponent: Component {
let clearTitle: String
let label: String?
if totalSelectedSize == 0 {
clearTitle = "Clear"
clearTitle = component.strings.StorageManagement_ClearSelected
label = nil
} else if hasDeselected {
clearTitle = "Clear Selected"
clearTitle = component.strings.StorageManagement_ClearSelected
label = dataSizeString(totalSelectedSize, formatting: DataSizeStringFormatting(strings: component.strings, decimalSeparator: "."))
} else {
clearTitle = "Clear All Cache"
clearTitle = component.strings.StorageManagement_ClearAll
label = dataSizeString(totalSelectedSize, formatting: DataSizeStringFormatting(strings: component.strings, decimalSeparator: "."))
}

View File

@ -768,7 +768,7 @@ final class StorageFileListPanelComponent: Component {
let _ = isAudio
let _ = isVoice
var title: String = "File"
var title: String = environment.strings.Message_File
var subtitle = stringForFullDate(timestamp: item.message.timestamp, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
@ -800,7 +800,7 @@ final class StorageFileListPanelComponent: Component {
//iconImage = .albumArt(file, SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: false)))
}
} else {
title = "Audio"
title = environment.strings.Message_Audio
}
}
}
@ -851,7 +851,7 @@ final class StorageFileListPanelComponent: Component {
descriptionText = NSAttributedString(string: descriptionString, font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)
iconImage = .roundVideo(file)*/
} else if !isAudio {
var fileName: String = file.fileName ?? "File"
var fileName: String = file.fileName ?? environment.strings.Message_File
if file.isVideo {
fileName = environment.strings.Message_Video
}
@ -868,8 +868,7 @@ final class StorageFileListPanelComponent: Component {
}
}
} else if let image = media as? TelegramMediaImage {
//TODO:localize
title = "Photo"
title = environment.strings.Message_Photo
if let representation = largestImageRepresentation(image.representations) {
imageIconValue = .media(image, representation)

View File

@ -24,6 +24,7 @@ final class StoragePeerTypeItemComponent: Component {
let theme: PresentationTheme
let iconName: String
let title: String
let subtitle: String?
let value: String
let hasNext: Bool
let action: (View) -> Void
@ -32,6 +33,7 @@ final class StoragePeerTypeItemComponent: Component {
theme: PresentationTheme,
iconName: String,
title: String,
subtitle: String?,
value: String,
hasNext: Bool,
action: @escaping (View) -> Void
@ -39,6 +41,7 @@ final class StoragePeerTypeItemComponent: Component {
self.theme = theme
self.iconName = iconName
self.title = title
self.subtitle = subtitle
self.value = value
self.hasNext = hasNext
self.action = action
@ -54,6 +57,9 @@ final class StoragePeerTypeItemComponent: Component {
if lhs.title != rhs.title {
return false
}
if lhs.subtitle != rhs.subtitle {
return false
}
if lhs.value != rhs.value {
return false
}
@ -66,6 +72,7 @@ final class StoragePeerTypeItemComponent: Component {
class View: HighlightTrackingButton {
private let iconView: UIImageView
private let title = ComponentView<Empty>()
private var subtitle: ComponentView<Empty>?
private let label = ComponentView<Empty>()
private let separatorLayer: SimpleLayer
private let arrowIconView: UIImageView
@ -171,9 +178,48 @@ final class StoragePeerTypeItemComponent: Component {
containerSize: CGSize(width: availableWidth, height: 100.0)
)
let height: CGFloat = 44.0
var subtitleSize: CGSize?
if let subtitleValue = component.subtitle {
let subtitle: ComponentView<Empty>
if let current = self.subtitle {
subtitle = current
} else {
subtitle = ComponentView()
self.subtitle = subtitle
}
let subtitleSizeValue = subtitle.update(
transition: transition,
component: AnyComponent(Text(text: subtitleValue, font: Font.regular(15.0), color: component.theme.list.itemSecondaryTextColor)),
environment: {},
containerSize: CGSize(width: availableWidth, height: 100.0)
)
subtitleSize = subtitleSizeValue
} else {
if let subtitle = self.subtitle {
self.subtitle = nil
subtitle.view?.removeFromSuperview()
}
}
var height: CGFloat = 44.0
if subtitleSize != nil {
height = 60.0
}
let titleFrame: CGRect
var subtitleFrame: CGRect?
if let subtitleSize = subtitleSize {
let spacing: CGFloat = 1.0
let verticalSize: CGFloat = titleSize.height + subtitleSize.height + spacing
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((height - verticalSize) / 2.0)), size: titleSize)
subtitleFrame = CGRect(origin: CGPoint(x: leftInset, y: titleFrame.maxY + spacing), size: subtitleSize)
} else {
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((height - titleSize.height) / 2.0)), size: titleSize)
}
let titleFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((height - titleSize.height) / 2.0)), size: titleSize)
let labelFrame = CGRect(origin: CGPoint(x: availableSize.width - rightInset - labelSize.width, y: floor((height - labelSize.height) / 2.0)), size: labelSize)
if let titleView = self.title.view {
@ -183,6 +229,13 @@ final class StoragePeerTypeItemComponent: Component {
}
transition.setFrame(view: titleView, frame: titleFrame)
}
if let subtitleView = self.subtitle?.view, let subtitleFrame {
if subtitleView.superview == nil {
subtitleView.isUserInteractionEnabled = false
self.addSubview(subtitleView)
}
transition.setFrame(view: subtitleView, frame: subtitleFrame)
}
if let labelView = self.label.view {
if labelView.superview == nil {
labelView.isUserInteractionEnabled = false

View File

@ -195,21 +195,21 @@ final class StorageUsageScreenComponent: Component {
func title(strings: PresentationStrings) -> String {
switch self {
case .photos:
return "Photos"
return strings.StorageManagement_SectionPhotos
case .videos:
return "Videos"
return strings.StorageManagement_SectionVideos
case .files:
return "Files"
return strings.StorageManagement_SectionFiles
case .music:
return "Music"
return strings.StorageManagement_SectionMusic
case .other:
return "Other"
return strings.StorageManagement_SectionOther
case .stickers:
return "Stickers"
return strings.StorageManagement_SectionStickers
case .avatars:
return "Avatars"
return strings.StorageManagement_SectionAvatars
case .misc:
return "Miscellaneous"
return strings.StorageManagement_SectionMiscellaneous
}
}
}
@ -222,6 +222,8 @@ final class StorageUsageScreenComponent: Component {
private var currentMessages: [MessageId: Message] = [:]
private var cacheSettings: CacheStorageSettings?
private var cacheSettingsExceptionCount: [CacheStorageSettings.PeerStorageCategory: Int32]?
private var peerItems: StoragePeerListPanelComponent.Items?
private var imageItems: StorageFileListPanelComponent.Items?
private var fileItems: StorageFileListPanelComponent.Items?
@ -449,22 +451,69 @@ final class StorageUsageScreenComponent: Component {
let environment = environment[ViewControllerComponentContainer.Environment.self].value
if self.statsDisposable == nil {
self.cacheSettingsDisposable = (component.context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.cacheStorageSettings])
|> map { sharedData -> CacheStorageSettings in
let cacheSettings: CacheStorageSettings
if let value = sharedData.entries[SharedDataKeys.cacheStorageSettings]?.get(CacheStorageSettings.self) {
let context = component.context
let viewKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.accountSpecificCacheStorageSettings]))
let cacheSettingsExceptionCount: Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> = component.context.account.postbox.combinedView(keys: [viewKey])
|> map { views -> AccountSpecificCacheStorageSettings in
let cacheSettings: AccountSpecificCacheStorageSettings
if let view = views.views[viewKey] as? PreferencesView, let value = view.values[PreferencesKeys.accountSpecificCacheStorageSettings]?.get(AccountSpecificCacheStorageSettings.self) {
cacheSettings = value
} else {
cacheSettings = CacheStorageSettings.defaultSettings
cacheSettings = AccountSpecificCacheStorageSettings.defaultSettings
}
return cacheSettings
}
|> deliverOnMainQueue).start(next: { [weak self] cacheSettings in
|> distinctUntilChanged
|> mapToSignal { accountSpecificSettings -> Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> in
return context.engine.data.get(
EngineDataMap(accountSpecificSettings.peerStorageTimeoutExceptions.map(\.key).map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
)
|> map { peers -> [CacheStorageSettings.PeerStorageCategory: Int32] in
var result: [CacheStorageSettings.PeerStorageCategory: Int32] = [:]
for (_, peer) in peers {
guard let peer else {
continue
}
switch peer {
case .user, .secretChat:
result[.privateChats, default: 0] += 1
case .legacyGroup:
result[.groups, default: 0] += 1
case let .channel(channel):
if case .group = channel.info {
result[.groups, default: 0] += 1
} else {
result[.channels, default: 0] += 1
}
}
}
return result
}
}
self.cacheSettingsDisposable = (combineLatest(queue: .mainQueue(),
component.context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.cacheStorageSettings])
|> map { sharedData -> CacheStorageSettings in
let cacheSettings: CacheStorageSettings
if let value = sharedData.entries[SharedDataKeys.cacheStorageSettings]?.get(CacheStorageSettings.self) {
cacheSettings = value
} else {
cacheSettings = CacheStorageSettings.defaultSettings
}
return cacheSettings
},
cacheSettingsExceptionCount
)
|> deliverOnMainQueue).start(next: { [weak self] cacheSettings, cacheSettingsExceptionCount in
guard let self else {
return
}
self.cacheSettings = cacheSettings
self.cacheSettingsExceptionCount = cacheSettingsExceptionCount
if self.currentStats != nil {
self.state?.updated(transition: .immediate)
}
@ -620,7 +669,7 @@ final class StorageUsageScreenComponent: Component {
transition: selectionPanelTransition,
component: AnyComponent(StorageUsageScreenSelectionPanelComponent(
theme: environment.theme,
title: "Clear Selected",
title: environment.strings.StorageManagement_ClearSelected,
label: selectedSize == 0 ? nil : dataSizeString(Int(selectedSize), formatting: DataSizeStringFormatting(strings: environment.strings, decimalSeparator: ".")),
isEnabled: selectedSize != 0,
insets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: environment.safeInsets.bottom, right: sideInset),
@ -887,19 +936,19 @@ final class StorageUsageScreenComponent: Component {
}
}
contentHeight += 26.0
contentHeight += 23.0
let headerText: String
if listCategories.isEmpty {
headerText = "Storage Cleared"
headerText = environment.strings.StorageManagement_TitleCleared
} else if let peer = component.peer {
headerText = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)
} else {
headerText = "Storage Usage"
headerText = environment.strings.StorageManagement_Title
}
let headerViewSize = self.headerView.update(
transition: transition,
component: AnyComponent(Text(text: headerText, font: Font.semibold(22.0), color: environment.theme.list.itemPrimaryTextColor)),
component: AnyComponent(Text(text: headerText, font: Font.semibold(20.0), color: environment.theme.list.itemPrimaryTextColor)),
environment: {},
containerSize: CGSize(width: floor((availableSize.width - navigationRightButtonMaxWidth * 2.0) / 0.8), height: 100.0)
)
@ -913,16 +962,15 @@ final class StorageUsageScreenComponent: Component {
}
contentHeight += headerViewSize.height
contentHeight += 4.0
contentHeight += 6.0
let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor)
let bold = MarkdownAttributeSet(font: Font.semibold(13.0), textColor: environment.theme.list.freeTextColor)
//TODO:localize
var usageFraction: Double = 0.0
let totalUsageText: String
if listCategories.isEmpty {
totalUsageText = "All media can be re-downloaded from the Telegram cloud if you need it again."
totalUsageText = environment.strings.StorageManagement_DescriptionCleared
} else if let currentStats = self.currentStats {
let contextStats: StorageUsageStats
if let peer = component.peer {
@ -959,7 +1007,7 @@ final class StorageUsageScreenComponent: Component {
fractionString = "\(fractionValue)"
}
totalUsageText = "This chat uses \(fractionString)% of your Telegram cache."
totalUsageText = environment.strings.StorageManagement_DescriptionChatUsage(fractionString).string
} else {
let fraction: Double
if currentStats.deviceFreeSpace != 0 && totalStatsSize != 0 {
@ -978,7 +1026,7 @@ final class StorageUsageScreenComponent: Component {
fractionString = "\(fractionValue)"
}
totalUsageText = "Telegram uses \(fractionString)% of your free disk space."
totalUsageText = environment.strings.StorageManagement_DescriptionAppUsage(fractionString).string
}
} else {
totalUsageText = " "
@ -1117,10 +1165,9 @@ final class StorageUsageScreenComponent: Component {
contentHeight += 8.0
//TODO:localize
let categoriesDescriptionSize = self.categoriesDescriptionView.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(text: .markdown(text: "All media will stay in the Telegram cloud and can be re-downloaded if you need it again.", attributes: MarkdownAttributes(
component: AnyComponent(MultilineTextComponent(text: .markdown(text: environment.strings.StorageManagement_SectionsDescription, attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
@ -1144,12 +1191,11 @@ final class StorageUsageScreenComponent: Component {
}
if component.peer == nil {
//TODO:localize
let keepDurationTitleSize = self.keepDurationTitleView.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .markdown(
text: "KEEP MEDIA", attributes: MarkdownAttributes(
text: environment.strings.StorageManagement_AutoremoveHeader, attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
@ -1184,21 +1230,20 @@ final class StorageUsageScreenComponent: Component {
let mappedCategory: CacheStorageSettings.PeerStorageCategory
//TODO:localize
let iconName: String
let title: String
switch i {
case 0:
iconName = "Settings/Menu/EditProfile"
title = "Private Chats"
title = environment.strings.Notifications_PrivateChats
mappedCategory = .privateChats
case 1:
iconName = "Settings/Menu/GroupChats"
title = "Group Chats"
title = environment.strings.Notifications_GroupChats
mappedCategory = .groups
default:
iconName = "Settings/Menu/Channels"
title = "Channels"
title = environment.strings.Notifications_Channels
mappedCategory = .channels
}
@ -1210,12 +1255,18 @@ final class StorageUsageScreenComponent: Component {
optionText = timeIntervalString(strings: environment.strings, value: value)
}
var subtitle: String?
if let cacheSettingsExceptionCount = self.cacheSettingsExceptionCount, let categoryCount = cacheSettingsExceptionCount[mappedCategory] {
subtitle = environment.strings.CacheEvictionMenu_CategoryExceptions(Int32(categoryCount))
}
let itemSize = item.update(
transition: transition,
component: AnyComponent(StoragePeerTypeItemComponent(
theme: environment.theme,
iconName: iconName,
title: title,
subtitle: subtitle,
value: optionText,
hasNext: i != 3 - 1,
action: { [weak self] sourceView in
@ -1242,12 +1293,11 @@ final class StorageUsageScreenComponent: Component {
contentHeight += keepContentHeight
contentHeight += 8.0
//TODO:localize
let keepDurationDescriptionSize = self.keepDurationDescriptionView.update(
transition: transition,
component: AnyComponent(MultilineTextComponent(
text: .markdown(
text: "Photos, videos and other files from cloud chats that you have **not accessed** during this period will be removed from this device to save disk space.", attributes: MarkdownAttributes(
text: environment.strings.StorageManagement_AutoremoveDescription, attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
@ -1269,12 +1319,11 @@ 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(
text: environment.strings.Cache_MaximumCacheSize.uppercased(), attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
@ -1327,12 +1376,11 @@ final class StorageUsageScreenComponent: Component {
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(
text: environment.strings.StorageManagement_AutoremoveSpaceDescription, attributes: MarkdownAttributes(
body: body,
bold: bold,
link: body,
@ -1356,10 +1404,10 @@ final class StorageUsageScreenComponent: Component {
}
var panelItems: [StorageUsagePanelContainerComponent.Item] = []
if let peerItems = self.peerItems, !peerItems.items.isEmpty {
if let peerItems = self.peerItems, !peerItems.items.isEmpty, !listCategories.isEmpty {
panelItems.append(StorageUsagePanelContainerComponent.Item(
id: "peers",
title: "Chats",
title: environment.strings.StorageManagement_TabChats,
panel: AnyComponent(StoragePeerListPanelComponent(
context: component.context,
items: self.peerItems,
@ -1378,10 +1426,10 @@ final class StorageUsageScreenComponent: Component {
))
))
}
if let imageItems = self.imageItems, !imageItems.items.isEmpty {
if let imageItems = self.imageItems, !imageItems.items.isEmpty, !listCategories.isEmpty {
panelItems.append(StorageUsagePanelContainerComponent.Item(
id: "images",
title: "Media",
title: environment.strings.StorageManagement_TabMedia,
panel: AnyComponent(StorageFileListPanelComponent(
context: component.context,
items: self.imageItems,
@ -1399,10 +1447,10 @@ final class StorageUsageScreenComponent: Component {
))
))
}
if let fileItems = self.fileItems, !fileItems.items.isEmpty {
if let fileItems = self.fileItems, !fileItems.items.isEmpty, !listCategories.isEmpty {
panelItems.append(StorageUsagePanelContainerComponent.Item(
id: "files",
title: "Files",
title: environment.strings.StorageManagement_TabFiles,
panel: AnyComponent(StorageFileListPanelComponent(
context: component.context,
items: self.fileItems,
@ -1420,10 +1468,10 @@ final class StorageUsageScreenComponent: Component {
))
))
}
if let musicItems = self.musicItems, !musicItems.items.isEmpty {
if let musicItems = self.musicItems, !musicItems.items.isEmpty, !listCategories.isEmpty {
panelItems.append(StorageUsagePanelContainerComponent.Item(
id: "music",
title: "Music",
title: environment.strings.StorageManagement_TabMusic,
panel: AnyComponent(StorageFileListPanelComponent(
context: component.context,
items: self.musicItems,
@ -1651,8 +1699,11 @@ final class StorageUsageScreenComponent: Component {
if let message = messages[id] {
var matches = false
for media in message.media {
if media is TelegramMediaFile {
matches = true
if let file = media as? TelegramMediaFile {
if file.isSticker || file.isCustomEmoji {
} else {
matches = true
}
}
}
@ -1772,11 +1823,19 @@ final class StorageUsageScreenComponent: Component {
}
let context = component.context
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationData: presentationData)
//TODO:localizable
let clearTitle: String
if categories == self.existingCategories {
clearTitle = presentationData.strings.StorageManagement_ClearAll
} else {
clearTitle = presentationData.strings.StorageManagement_ClearSelected
}
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: "Clear Selected", color: .destructive, action: { [weak self, weak actionSheet] in
ActionSheetButtonItem(title: clearTitle, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
self?.commitClear(categories: categories, peers: peers, messages: messages)

View File

@ -2695,7 +2695,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
subtitleStringText = subtitle
subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: presentationData.theme.list.itemSecondaryTextColor)
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor)
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: UIColor(white: 1.0, alpha: 0.7))
usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor))
} else if let _ = threadData {