mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
36e4eb858b
commit
c1c2db4777
@ -2061,6 +2061,7 @@
|
||||
|
||||
"StickerPack.Share" = "Share";
|
||||
"StickerPack.Send" = "Send Sticker";
|
||||
"StickerPack.Select" = "Select Sticker";
|
||||
|
||||
"StickerPack.RemoveStickerCount_1" = "Remove 1 Sticker";
|
||||
"StickerPack.RemoveStickerCount_2" = "Remove 2 Stickers";
|
||||
|
@ -95,6 +95,7 @@ swift_library(
|
||||
"//submodules/FastBlur:FastBlur",
|
||||
"//submodules/TelegramUI/Components/MediaEditor",
|
||||
"//submodules/ChatPresentationInterfaceState:ChatPresentationInterfaceState",
|
||||
"//submodules/StickerPackPreviewUI:StickerPackPreviewUI",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -17,6 +17,7 @@ import ChatEntityKeyboardInputNode
|
||||
import ContextUI
|
||||
import ChatPresentationInterfaceState
|
||||
import MediaEditor
|
||||
import StickerPackPreviewUI
|
||||
|
||||
public struct StickerPickerInputData: Equatable {
|
||||
var emoji: EmojiPagerContentComponent
|
||||
@ -45,6 +46,7 @@ private final class StickerSelectionComponent: Component {
|
||||
let content: StickerPickerInputData
|
||||
let backgroundColor: UIColor
|
||||
let separatorColor: UIColor
|
||||
let getController: () -> StickerPickerScreen?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
@ -54,7 +56,8 @@ private final class StickerSelectionComponent: Component {
|
||||
bottomInset: CGFloat,
|
||||
content: StickerPickerInputData,
|
||||
backgroundColor: UIColor,
|
||||
separatorColor: UIColor
|
||||
separatorColor: UIColor,
|
||||
getController: @escaping () -> StickerPickerScreen?
|
||||
) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
@ -64,6 +67,7 @@ private final class StickerSelectionComponent: Component {
|
||||
self.content = content
|
||||
self.backgroundColor = backgroundColor
|
||||
self.separatorColor = separatorColor
|
||||
self.getController = getController
|
||||
}
|
||||
|
||||
public static func ==(lhs: StickerSelectionComponent, rhs: StickerSelectionComponent) -> Bool {
|
||||
@ -105,6 +109,7 @@ private final class StickerSelectionComponent: Component {
|
||||
private var inputNodeInteraction: ChatMediaInputNodeInteraction?
|
||||
private let trendingGifsPromise = Promise<ChatMediaInputGifPaneTrendingState?>(nil)
|
||||
|
||||
private var searchVisible = false
|
||||
private var forceUpdate = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
@ -122,16 +127,22 @@ private final class StickerSelectionComponent: Component {
|
||||
self.addSubview(self.panelHostView)
|
||||
|
||||
self.interaction = ChatEntityKeyboardInputNode.Interaction(
|
||||
sendSticker: { file, silent, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, _ in
|
||||
let _ = file
|
||||
let _ = silent
|
||||
let _ = schedule
|
||||
let _ = query
|
||||
let _ = clearInput
|
||||
let _ = sourceView
|
||||
let _ = sourceRect
|
||||
let _ = sourceLayer
|
||||
|
||||
sendSticker: { [weak self] file, silent, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, _ in
|
||||
if let self, let controller = self.component?.getController() {
|
||||
controller.completion(.file(file.media))
|
||||
controller.forEachController { c in
|
||||
if let c = c as? StickerPackScreenImpl {
|
||||
c.dismiss(animated: true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
controller.window?.forEachController({ c in
|
||||
if let c = c as? StickerPackScreenImpl {
|
||||
c.dismiss(animated: true)
|
||||
}
|
||||
})
|
||||
controller.dismiss(animated: true)
|
||||
}
|
||||
return false
|
||||
},
|
||||
sendEmoji: { _, _, _ in
|
||||
@ -148,20 +159,23 @@ private final class StickerSelectionComponent: Component {
|
||||
insertText: { _ in
|
||||
},
|
||||
backwardsDeleteText: {},
|
||||
presentController: { c, a in
|
||||
let _ = c
|
||||
let _ = a
|
||||
presentController: { [weak self] c, a in
|
||||
if let self, let controller = self.component?.getController() {
|
||||
controller.present(c, in: .window(.root), with: a)
|
||||
}
|
||||
},
|
||||
presentGlobalOverlayController: { c, a in
|
||||
let _ = c
|
||||
let _ = a
|
||||
presentGlobalOverlayController: { [weak self] c, a in
|
||||
if let self, let controller = self.component?.getController() {
|
||||
controller.presentInGlobalOverlay(c, with: a)
|
||||
}
|
||||
},
|
||||
getNavigationController: {
|
||||
return nil
|
||||
},
|
||||
requestLayout: { transition in
|
||||
let _ = transition
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
self.inputNodeInteraction = ChatMediaInputNodeInteraction(
|
||||
navigateToCollectionId: { _ in
|
||||
@ -237,14 +251,17 @@ private final class StickerSelectionComponent: Component {
|
||||
externalBottomPanelContainer: nil,
|
||||
displayTopPanelBackground: .blur,
|
||||
topPanelExtensionUpdated: { _, _ in },
|
||||
hideInputUpdated: { [weak self] _, _, transition in
|
||||
hideInputUpdated: { [weak self] _, searchVisible, transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.forceUpdate = true
|
||||
self.searchVisible = searchVisible
|
||||
self.state?.updated(transition: transition)
|
||||
},
|
||||
hideTopPanelUpdated: { _, _ in },
|
||||
hideTopPanelUpdated: { _, _ in
|
||||
print()
|
||||
},
|
||||
switchToTextInput: {},
|
||||
switchToGifSubject: { _ in },
|
||||
reorderItems: { _, _ in },
|
||||
@ -269,17 +286,12 @@ private final class StickerSelectionComponent: Component {
|
||||
interaction: interaction,
|
||||
inputNodeInteraction: inputNodeInteraction,
|
||||
mode: mappedMode,
|
||||
stickerActionTitle: presentationData.strings.StickerPack_Select,
|
||||
trendingGifsPromise: trendingGifsPromise,
|
||||
cancel: {
|
||||
},
|
||||
peekBehavior: stickerPeekBehavior
|
||||
)
|
||||
// searchContainerNode.openGifContextMenu = { [weak self] item, sourceNode, sourceRect, gesture, isSaved in
|
||||
// guard let self else {
|
||||
// return
|
||||
// }
|
||||
// self.openGifContextMenu(file: item.file, contextResult: item.contextResult, sourceView: sourceNode.view, sourceRect: sourceRect, gesture: gesture, isSaved: isSaved)
|
||||
// }
|
||||
|
||||
return searchContainerNode
|
||||
},
|
||||
@ -315,8 +327,10 @@ private final class StickerSelectionComponent: Component {
|
||||
transition.setFrame(view: self.panelBackgroundView, frame: CGRect(origin: CGPoint(), size: CGSize(width: keyboardSize.width, height: topPanelHeight)))
|
||||
self.panelBackgroundView.update(size: self.panelBackgroundView.bounds.size, transition: transition.containedViewLayoutTransition)
|
||||
|
||||
transition.setAlpha(view: self.panelBackgroundView, alpha: self.searchVisible ? 0.0 : 1.0)
|
||||
transition.setAlpha(view: self.panelSeparatorView, alpha: self.searchVisible ? 0.0 : 1.0)
|
||||
|
||||
transition.setFrame(view: self.panelSeparatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelHeight), size: CGSize(width: keyboardSize.width, height: UIScreenPixel)))
|
||||
transition.setAlpha(view: self.panelSeparatorView, alpha: 1.0)
|
||||
}
|
||||
|
||||
return availableSize
|
||||
@ -1316,7 +1330,14 @@ public class StickerPickerScreen: ViewController {
|
||||
bottomInset: bottomInset,
|
||||
content: content,
|
||||
backgroundColor: self.theme.list.itemBlocksBackgroundColor,
|
||||
separatorColor: self.theme.list.blocksBackgroundColor
|
||||
separatorColor: self.theme.list.blocksBackgroundColor,
|
||||
getController: { [weak self] in
|
||||
if let self {
|
||||
return self.controller
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
|
@ -208,6 +208,7 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let forceTheme: PresentationTheme?
|
||||
private let interaction: ChatMediaInputTrendingPane.Interaction
|
||||
private let getItemIsPreviewed: (StickerPackItem) -> Bool
|
||||
private let isPane: Bool
|
||||
@ -228,10 +229,13 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
|
||||
public var scrollingInitiated: (() -> Void)?
|
||||
|
||||
public var stickerActionTitle: String?
|
||||
|
||||
private let installDisposable = MetaDisposable()
|
||||
|
||||
public init(context: AccountContext, interaction: ChatMediaInputTrendingPane.Interaction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, isPane: Bool) {
|
||||
public init(context: AccountContext, forceTheme: PresentationTheme?, interaction: ChatMediaInputTrendingPane.Interaction, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, isPane: Bool) {
|
||||
self.context = context
|
||||
self.forceTheme = forceTheme
|
||||
self.interaction = interaction
|
||||
self.getItemIsPreviewed = getItemIsPreviewed
|
||||
self.isPane = isPane
|
||||
@ -290,7 +294,10 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
|
||||
var cancelImpl: (() -> Void)?
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
var presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
if let forceTheme = self?.forceTheme {
|
||||
presentationData = presentationData.withUpdated(theme: forceTheme)
|
||||
}
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
|
||||
cancelImpl?()
|
||||
}))
|
||||
@ -330,7 +337,10 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
}
|
||||
}
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
if let forceTheme = strongSelf.forceTheme {
|
||||
presentationData = presentationData.withUpdated(theme: forceTheme)
|
||||
}
|
||||
strongSelf.interaction.getNavigationController()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: strongSelf.context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
return true
|
||||
}))
|
||||
@ -340,7 +350,12 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
if let strongSelf = self, let info = info as? StickerPackCollectionInfo {
|
||||
strongSelf.view.window?.endEditing(true)
|
||||
let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash)
|
||||
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.interaction.getNavigationController(), sendSticker: { fileReference, sourceNode, sourceRect in
|
||||
var updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)?
|
||||
if let forceTheme = strongSelf.forceTheme {
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: forceTheme)
|
||||
updatedPresentationData = (presentationData, .single(presentationData))
|
||||
}
|
||||
let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], actionTitle: strongSelf.stickerActionTitle, parentNavigationController: strongSelf.interaction.getNavigationController(), sendSticker: { fileReference, sourceNode, sourceRect in
|
||||
if let strongSelf = self {
|
||||
return strongSelf.interaction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, [])
|
||||
} else {
|
||||
@ -358,8 +373,13 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
|
||||
let isPane = self.isPane
|
||||
let previousEntries = Atomic<[TrendingPaneEntry]?>(value: nil)
|
||||
let context = self.context
|
||||
let forceTheme = self.forceTheme
|
||||
self.disposable = (combineLatest(context.account.viewTracker.featuredStickerPacks(), context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]), context.sharedContext.presentationData)
|
||||
|> map { trendingEntries, view, presentationData -> TrendingPaneTransition in
|
||||
var presentationData = presentationData
|
||||
if let forceTheme {
|
||||
presentationData = presentationData.withUpdated(theme: forceTheme)
|
||||
}
|
||||
var installedPacks = Set<ItemCollectionId>()
|
||||
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView {
|
||||
if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] {
|
||||
|
@ -464,7 +464,13 @@ private final class StickerPackContainer: ASDisplayNode {
|
||||
var menuItems: [ContextMenuItem] = []
|
||||
if let (info, _, _) = strongSelf.currentStickerPack, info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks {
|
||||
if strongSelf.sendSticker != nil {
|
||||
menuItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
let actionTitle: String
|
||||
if let title = strongSelf.controller?.actionTitle {
|
||||
actionTitle = title
|
||||
} else {
|
||||
actionTitle = strongSelf.presentationData.strings.StickerPack_Send
|
||||
}
|
||||
menuItems.append(.action(ContextMenuActionItem(text: actionTitle, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||
if let strongSelf = self, let peekController = strongSelf.peekController {
|
||||
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
|
||||
let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds)
|
||||
@ -1901,12 +1907,15 @@ public final class StickerPackScreenImpl: ViewController {
|
||||
let animationCache: AnimationCache
|
||||
let animationRenderer: MultiAnimationRenderer
|
||||
|
||||
let actionTitle: String?
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||
stickerPacks: [StickerPackReference],
|
||||
loadedStickerPacks: [LoadedStickerPack],
|
||||
selectedStickerPackIndex: Int = 0,
|
||||
actionTitle: String? = nil,
|
||||
parentNavigationController: NavigationController? = nil,
|
||||
sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil,
|
||||
sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?,
|
||||
@ -1918,6 +1927,7 @@ public final class StickerPackScreenImpl: ViewController {
|
||||
self.stickerPacks = stickerPacks
|
||||
self.loadedStickerPacks = loadedStickerPacks
|
||||
self.initialSelectedStickerPackIndex = selectedStickerPackIndex
|
||||
self.actionTitle = actionTitle
|
||||
self.parentNavigationController = parentNavigationController
|
||||
self.sendSticker = sendSticker
|
||||
self.sendEmoji = sendEmoji
|
||||
@ -2142,6 +2152,7 @@ public func StickerPackScreen(
|
||||
mainStickerPack: StickerPackReference,
|
||||
stickerPacks: [StickerPackReference],
|
||||
loadedStickerPacks: [LoadedStickerPack] = [],
|
||||
actionTitle: String? = nil,
|
||||
parentNavigationController: NavigationController? = nil,
|
||||
sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil,
|
||||
sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)? = nil,
|
||||
@ -2151,9 +2162,11 @@ public func StickerPackScreen(
|
||||
) -> ViewController {
|
||||
let controller = StickerPackScreenImpl(
|
||||
context: context,
|
||||
updatedPresentationData: updatedPresentationData,
|
||||
stickerPacks: stickerPacks,
|
||||
loadedStickerPacks: loadedStickerPacks,
|
||||
selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0,
|
||||
actionTitle: actionTitle,
|
||||
parentNavigationController: parentNavigationController,
|
||||
sendSticker: sendSticker,
|
||||
sendEmoji: sendEmoji,
|
||||
|
@ -55,7 +55,7 @@ public final class PaneSearchContainerNode: ASDisplayNode, EntitySearchContainer
|
||||
return self.contentNode.ready
|
||||
}
|
||||
|
||||
public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: ChatEntityKeyboardInputNode.Interaction, inputNodeInteraction: ChatMediaInputNodeInteraction, mode: ChatMediaInputSearchMode, trendingGifsPromise: Promise<ChatMediaInputGifPaneTrendingState?>, cancel: @escaping () -> Void, peekBehavior: EmojiContentPeekBehavior?) {
|
||||
public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: ChatEntityKeyboardInputNode.Interaction, inputNodeInteraction: ChatMediaInputNodeInteraction, mode: ChatMediaInputSearchMode, stickerActionTitle: String? = nil, trendingGifsPromise: Promise<ChatMediaInputGifPaneTrendingState?>, cancel: @escaping () -> Void, peekBehavior: EmojiContentPeekBehavior?) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.interaction = interaction
|
||||
@ -65,7 +65,7 @@ public final class PaneSearchContainerNode: ASDisplayNode, EntitySearchContainer
|
||||
case .gif:
|
||||
self.contentNode = GifPaneSearchContentNode(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction, trendingPromise: trendingGifsPromise)
|
||||
case .sticker, .trending:
|
||||
self.contentNode = StickerPaneSearchContentNode(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction)
|
||||
self.contentNode = StickerPaneSearchContentNode(context: context, theme: theme, strings: strings, interaction: interaction, inputNodeInteraction: inputNodeInteraction, stickerActionTitle: stickerActionTitle)
|
||||
}
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
|
||||
|
@ -167,7 +167,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
|
||||
private let installDisposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: ChatEntityKeyboardInputNode.Interaction, inputNodeInteraction: ChatMediaInputNodeInteraction) {
|
||||
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: ChatEntityKeyboardInputNode.Interaction, inputNodeInteraction: ChatMediaInputNodeInteraction, stickerActionTitle: String?) {
|
||||
self.context = context
|
||||
self.interaction = interaction
|
||||
self.inputNodeInteraction = inputNodeInteraction
|
||||
@ -181,9 +181,10 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
||||
getNavigationController: interaction.getNavigationController
|
||||
)
|
||||
|
||||
self.trendingPane = ChatMediaInputTrendingPane(context: context, interaction: trendingPaneInteraction, getItemIsPreviewed: { [weak inputNodeInteraction] item in
|
||||
self.trendingPane = ChatMediaInputTrendingPane(context: context, forceTheme: theme, interaction: trendingPaneInteraction, getItemIsPreviewed: { [weak inputNodeInteraction] item in
|
||||
return inputNodeInteraction?.previewedStickerPackItemFile?.id == item.file.id
|
||||
}, isPane: false)
|
||||
self.trendingPane.stickerActionTitle = stickerActionTitle
|
||||
|
||||
self.gridNode = GridNode()
|
||||
|
||||
|
@ -97,8 +97,7 @@ final class EntitySearchContentComponent: Component {
|
||||
}
|
||||
|
||||
if let containerNode = containerNode {
|
||||
|
||||
let environmentValue = environment[EntitySearchContentEnvironment.self].value
|
||||
let environmentValue = environment[EntitySearchContentEnvironment.self].value
|
||||
transition.setFrame(view: containerNode.view, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
containerNode.updateLayout(
|
||||
size: availableSize,
|
||||
@ -109,7 +108,6 @@ final class EntitySearchContentComponent: Component {
|
||||
deviceMetrics: environmentValue.deviceMetrics,
|
||||
transition: transition.containedViewLayoutTransition
|
||||
)
|
||||
|
||||
containerNode.onCancel = {
|
||||
component.dismissSearch()
|
||||
}
|
||||
|
@ -2440,6 +2440,8 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
if let mediaResult {
|
||||
switch mediaResult {
|
||||
case let .image(image, dimensions):
|
||||
updateProgressImpl?(0.0)
|
||||
|
||||
if let imageData = compressImageToJPEG(image, quality: 0.7) {
|
||||
let _ = (context.engine.messages.editStory(media: .image(dimensions: dimensions, data: imageData), id: id, text: updatedText, entities: updatedEntities, privacy: updatedPrivacy)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
@ -2462,6 +2464,8 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
})
|
||||
}
|
||||
case let .video(content, firstFrameImage, values, duration, dimensions):
|
||||
updateProgressImpl?(0.0)
|
||||
|
||||
if let valuesData = try? JSONEncoder().encode(values) {
|
||||
let data = MemoryBuffer(data: valuesData)
|
||||
let digest = MemoryBuffer(data: data.md5Digest())
|
||||
|
Loading…
x
Reference in New Issue
Block a user