Various fixes

This commit is contained in:
Ilya Laktyushin 2023-08-10 17:34:56 +02:00
parent e7c717867c
commit 5bf4a36d46
6 changed files with 155 additions and 45 deletions

View File

@ -9,6 +9,7 @@ import Display
import TelegramCore import TelegramCore
import TelegramPresentationData import TelegramPresentationData
import FastBlur import FastBlur
import AccountContext
public struct MediaEditorPlayerState { public struct MediaEditorPlayerState {
public let generationTimestamp: Double public let generationTimestamp: Double
@ -41,6 +42,7 @@ public final class MediaEditor {
} }
} }
private let context: AccountContext
private let subject: Subject private let subject: Subject
private var player: AVPlayer? private var player: AVPlayer?
private var additionalPlayer: AVPlayer? private var additionalPlayer: AVPlayer?
@ -253,7 +255,8 @@ public final class MediaEditor {
} }
} }
public init(subject: Subject, values: MediaEditorValues? = nil, hasHistogram: Bool = false) { public init(context: AccountContext, subject: Subject, values: MediaEditorValues? = nil, hasHistogram: Bool = false) {
self.context = context
self.subject = subject self.subject = subject
if let values { if let values {
self.values = values self.values = values
@ -332,6 +335,7 @@ public final class MediaEditor {
print("error") print("error")
} }
let context = self.context
let textureSource: Signal<(TextureSource, UIImage?, AVPlayer?, AVPlayer?, UIColor, UIColor), NoError> let textureSource: Signal<(TextureSource, UIImage?, AVPlayer?, AVPlayer?, UIColor, UIColor), NoError>
switch subject { switch subject {
case let .image(image, _): case let .image(image, _):
@ -340,7 +344,7 @@ public final class MediaEditor {
case let .draft(draft): case let .draft(draft):
if draft.isVideo { if draft.isVideo {
textureSource = Signal { subscriber in textureSource = Signal { subscriber in
let url = URL(fileURLWithPath: draft.fullPath()) let url = URL(fileURLWithPath: draft.fullPath(engine: context.engine))
let asset = AVURLAsset(url: url) let asset = AVURLAsset(url: url)
let playerItem = AVPlayerItem(asset: asset) let playerItem = AVPlayerItem(asset: asset)
@ -372,7 +376,7 @@ public final class MediaEditor {
} }
} }
} else { } else {
guard let image = UIImage(contentsOfFile: draft.fullPath()) else { guard let image = UIImage(contentsOfFile: draft.fullPath(engine: context.engine)) else {
return return
} }
let colors: (UIColor, UIColor) let colors: (UIColor, UIColor)

View File

@ -70,6 +70,7 @@ public final class MediaEditorDraft: Codable, Equatable {
case timestamp case timestamp
case locationLatitude case locationLatitude
case locationLongitude case locationLongitude
case expiresOn
} }
public let path: String public let path: String
@ -82,8 +83,9 @@ public final class MediaEditorDraft: Codable, Equatable {
public let privacy: MediaEditorResultPrivacy? public let privacy: MediaEditorResultPrivacy?
public let timestamp: Int32 public let timestamp: Int32
public let location: CLLocationCoordinate2D? public let location: CLLocationCoordinate2D?
public let expiresOn: Int32?
public init(path: String, isVideo: Bool, thumbnail: UIImage, dimensions: PixelDimensions, duration: Double?, values: MediaEditorValues, caption: NSAttributedString, privacy: MediaEditorResultPrivacy?, timestamp: Int32, location: CLLocationCoordinate2D?) { public init(path: String, isVideo: Bool, thumbnail: UIImage, dimensions: PixelDimensions, duration: Double?, values: MediaEditorValues, caption: NSAttributedString, privacy: MediaEditorResultPrivacy?, timestamp: Int32, location: CLLocationCoordinate2D?, expiresOn: Int32?) {
self.path = path self.path = path
self.isVideo = isVideo self.isVideo = isVideo
self.thumbnail = thumbnail self.thumbnail = thumbnail
@ -94,6 +96,7 @@ public final class MediaEditorDraft: Codable, Equatable {
self.privacy = privacy self.privacy = privacy
self.timestamp = timestamp self.timestamp = timestamp
self.location = location self.location = location
self.expiresOn = expiresOn
} }
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
@ -133,6 +136,8 @@ public final class MediaEditorDraft: Codable, Equatable {
} else { } else {
self.location = nil self.location = nil
} }
self.expiresOn = try container.decodeIfPresent(Int32.self, forKey: .expiresOn)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -170,6 +175,7 @@ public final class MediaEditorDraft: Codable, Equatable {
try container.encodeNil(forKey: .locationLatitude) try container.encodeNil(forKey: .locationLatitude)
try container.encodeNil(forKey: .locationLongitude) try container.encodeNil(forKey: .locationLongitude)
} }
try container.encodeIfPresent(self.expiresOn, forKey: .expiresOn)
} }
} }
@ -207,14 +213,25 @@ public func addStoryDraft(engine: TelegramEngine, item: MediaEditorDraft) {
public func removeStoryDraft(engine: TelegramEngine, path: String, delete: Bool) { public func removeStoryDraft(engine: TelegramEngine, path: String, delete: Bool) {
if delete { if delete {
try? FileManager.default.removeItem(atPath: fullDraftPath(path)) try? FileManager.default.removeItem(atPath: fullDraftPath(engine: engine, path: path))
} }
let itemId = MediaEditorDraftItemId(path.persistentHashValue) let itemId = MediaEditorDraftItemId(path.persistentHashValue)
let _ = engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.storyDrafts, id: itemId.rawValue).start() let _ = engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.storyDrafts, id: itemId.rawValue).start()
} }
public func clearStoryDrafts(engine: TelegramEngine) { public func clearStoryDrafts(engine: TelegramEngine) {
let _ = engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.storyDrafts).start() let _ = engine.data.get(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.storyDrafts)).start(next: { items in
for item in items {
if let draft = item.contents.get(MediaEditorDraft.self) {
removeStoryDraft(engine: engine, path: draft.path, delete: true)
}
}
})
}
public func deleteAllStoryDrafts(peerId: EnginePeer.Id) {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/storyDrafts_\(peerId.toInt64())/"
try? FileManager.default.removeItem(atPath: path)
} }
public func storyDrafts(engine: TelegramEngine) -> Signal<[MediaEditorDraft], NoError> { public func storyDrafts(engine: TelegramEngine) -> Signal<[MediaEditorDraft], NoError> {
@ -230,12 +247,27 @@ public func storyDrafts(engine: TelegramEngine) -> Signal<[MediaEditorDraft], No
} }
} }
public func updateStoryDrafts(engine: TelegramEngine) {
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
let _ = engine.data.get(
TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.storyDrafts)
).start(next: { items in
for item in items {
if let draft = item.contents.get(MediaEditorDraft.self) {
if let expiresOn = draft.expiresOn, expiresOn < currentTimestamp {
removeStoryDraft(engine: engine, path: draft.path, delete: true)
}
}
}
})
}
public extension MediaEditorDraft { public extension MediaEditorDraft {
func fullPath() -> String { func fullPath(engine: TelegramEngine) -> String {
return fullDraftPath(self.path) return fullDraftPath(engine: engine, path: self.path)
} }
} }
private func fullDraftPath(_ path: String) -> String { private func fullDraftPath(engine: TelegramEngine, path: String) -> String {
return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/storyDrafts/" + path return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/storyDrafts_\(engine.account.peerId.toInt64())/" + path
} }

View File

@ -1886,7 +1886,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} }
} }
let mediaEditor = MediaEditor(subject: subject.editorSubject, values: initialValues, hasHistogram: true) let mediaEditor = MediaEditor(context: self.context, subject: subject.editorSubject, values: initialValues, hasHistogram: true)
if let initialVideoPosition = self.controller?.initialVideoPosition { if let initialVideoPosition = self.controller?.initialVideoPosition {
mediaEditor.seek(initialVideoPosition, andPlay: true) mediaEditor.seek(initialVideoPosition, andPlay: true)
} }
@ -3441,6 +3441,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} }
}) })
} }
updateStorySources(engine: self.context.engine)
updateStoryDrafts(engine: self.context.engine)
} }
required public init(coder aDecoder: NSCoder) { required public init(coder aDecoder: NSCoder) {
@ -3827,23 +3830,35 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
guard let subject = self.node.subject, let mediaEditor = self.node.mediaEditor else { guard let subject = self.node.subject, let mediaEditor = self.node.mediaEditor else {
return return
} }
try? FileManager.default.createDirectory(atPath: draftPath(), withIntermediateDirectories: true) try? FileManager.default.createDirectory(atPath: draftPath(engine: self.context.engine), withIntermediateDirectories: true)
let values = mediaEditor.values let values = mediaEditor.values
let privacy = self.state.privacy let privacy = self.state.privacy
let caption = self.getCaption() let caption = self.getCaption()
let duration = mediaEditor.duration ?? 0.0 let duration = mediaEditor.duration ?? 0.0
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
var timestamp: Int32 var timestamp: Int32
var location: CLLocationCoordinate2D? var location: CLLocationCoordinate2D?
let expiresOn: Int32
if case let .draft(draft, _) = subject { if case let .draft(draft, _) = subject {
timestamp = draft.timestamp timestamp = draft.timestamp
location = draft.location location = draft.location
if let _ = id {
expiresOn = draft.expiresOn ?? currentTimestamp + 3600 * 24 * 7
} else {
expiresOn = currentTimestamp + 3600 * 24 * 7
}
} else { } else {
timestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) timestamp = currentTimestamp
if case let .asset(asset) = subject { if case let .asset(asset) = subject {
location = asset.location?.coordinate location = asset.location?.coordinate
} }
if let _ = id {
expiresOn = currentTimestamp + Int32(self.state.privacy.timeout)
} else {
expiresOn = currentTimestamp + 3600 * 24 * 7
}
} }
if let resultImage = mediaEditor.resultImage { if let resultImage = mediaEditor.resultImage {
@ -3859,8 +3874,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
if let thumbnailImage = generateScaledImage(image: resultImage, size: fittedSize) { if let thumbnailImage = generateScaledImage(image: resultImage, size: fittedSize) {
let path = "\(Int64.random(in: .min ... .max)).jpg" let path = "\(Int64.random(in: .min ... .max)).jpg"
if let data = image.jpegData(compressionQuality: 0.87) { if let data = image.jpegData(compressionQuality: 0.87) {
let draft = MediaEditorDraft(path: path, isVideo: false, thumbnail: thumbnailImage, dimensions: dimensions, duration: nil, values: values, caption: caption, privacy: privacy, timestamp: timestamp, location: location) let draft = MediaEditorDraft(path: path, isVideo: false, thumbnail: thumbnailImage, dimensions: dimensions, duration: nil, values: values, caption: caption, privacy: privacy, timestamp: timestamp, location: location, expiresOn: expiresOn)
try? data.write(to: URL(fileURLWithPath: draft.fullPath())) try? data.write(to: URL(fileURLWithPath: draft.fullPath(engine: context.engine)))
if let id { if let id {
saveStorySource(engine: context.engine, item: draft, peerId: context.account.peerId, id: id) saveStorySource(engine: context.engine, item: draft, peerId: context.account.peerId, id: id)
} else { } else {
@ -3873,8 +3888,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let saveVideoDraft: (String, PixelDimensions, Double) -> Void = { videoPath, dimensions, duration in let saveVideoDraft: (String, PixelDimensions, Double) -> Void = { videoPath, dimensions, duration in
if let thumbnailImage = generateScaledImage(image: resultImage, size: fittedSize) { if let thumbnailImage = generateScaledImage(image: resultImage, size: fittedSize) {
let path = "\(Int64.random(in: .min ... .max)).mp4" let path = "\(Int64.random(in: .min ... .max)).mp4"
let draft = MediaEditorDraft(path: path, isVideo: true, thumbnail: thumbnailImage, dimensions: dimensions, duration: duration, values: values, caption: caption, privacy: privacy, timestamp: timestamp, location: location) let draft = MediaEditorDraft(path: path, isVideo: true, thumbnail: thumbnailImage, dimensions: dimensions, duration: duration, values: values, caption: caption, privacy: privacy, timestamp: timestamp, location: location, expiresOn: expiresOn)
try? FileManager.default.moveItem(atPath: videoPath, toPath: draft.fullPath()) try? FileManager.default.moveItem(atPath: videoPath, toPath: draft.fullPath(engine: context.engine))
if let id { if let id {
saveStorySource(engine: context.engine, item: draft, peerId: context.account.peerId, id: id) saveStorySource(engine: context.engine, item: draft, peerId: context.account.peerId, id: id)
} else { } else {
@ -3906,8 +3921,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} }
case let .draft(draft, _): case let .draft(draft, _):
if draft.isVideo { if draft.isVideo {
saveVideoDraft(draft.fullPath(), draft.dimensions, draft.duration ?? 0.0) saveVideoDraft(draft.fullPath(engine: context.engine), draft.dimensions, draft.duration ?? 0.0)
} else if let image = UIImage(contentsOfFile: draft.fullPath()) { } else if let image = UIImage(contentsOfFile: draft.fullPath(engine: context.engine)) {
saveImageDraft(image, draft.dimensions) saveImageDraft(image, draft.dimensions)
} }
removeStoryDraft(engine: self.context.engine, path: draft.path, delete: false) removeStoryDraft(engine: self.context.engine, path: draft.path, delete: false)
@ -3943,6 +3958,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
mediaEditor.invalidate() mediaEditor.invalidate()
self.node.entitiesView.invalidate() self.node.entitiesView.invalidate()
let context = self.context
if let navigationController = self.navigationController as? NavigationController { if let navigationController = self.navigationController as? NavigationController {
navigationController.updateRootContainerTransitionOffset(0.0, transition: .immediate) navigationController.updateRootContainerTransitionOffset(0.0, transition: .immediate)
} }
@ -4109,15 +4125,16 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
return EmptyDisposable return EmptyDisposable
} }
case let .draft(draft, _): case let .draft(draft, _):
let draftPath = draft.fullPath(engine: context.engine)
if draft.isVideo { if draft.isVideo {
videoResult = .videoFile(path: draft.fullPath()) videoResult = .videoFile(path: draftPath)
if let videoTrimRange = mediaEditor.values.videoTrimRange { if let videoTrimRange = mediaEditor.values.videoTrimRange {
duration = videoTrimRange.upperBound - videoTrimRange.lowerBound duration = videoTrimRange.upperBound - videoTrimRange.lowerBound
} else { } else {
duration = min(draft.duration ?? 5.0, storyMaxVideoDuration) duration = min(draft.duration ?? 5.0, storyMaxVideoDuration)
} }
firstFrame = Signal<(UIImage?, UIImage?), NoError> { subscriber in firstFrame = Signal<(UIImage?, UIImage?), NoError> { subscriber in
let avAsset = AVURLAsset(url: URL(fileURLWithPath: draft.fullPath())) let avAsset = AVURLAsset(url: URL(fileURLWithPath: draftPath))
let avAssetGenerator = AVAssetImageGenerator(asset: avAsset) let avAssetGenerator = AVAssetImageGenerator(asset: avAsset)
avAssetGenerator.appliesPreferredTrackTransform = true avAssetGenerator.appliesPreferredTrackTransform = true
avAssetGenerator.generateCGImagesAsynchronously(forTimes: [NSValue(time: firstFrameTime)], completionHandler: { _, cgImage, _, _, _ in avAssetGenerator.generateCGImagesAsynchronously(forTimes: [NSValue(time: firstFrameTime)], completionHandler: { _, cgImage, _, _, _ in
@ -4131,10 +4148,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} }
} }
} else { } else {
videoResult = .imageFile(path: draft.fullPath()) videoResult = .imageFile(path: draftPath)
duration = 5.0 duration = 5.0
if let image = UIImage(contentsOfFile: draft.fullPath()) { if let image = UIImage(contentsOfFile: draftPath) {
firstFrame = .single((image, nil)) firstFrame = .single((image, nil))
} else { } else {
firstFrame = .single((UIImage(), nil)) firstFrame = .single((UIImage(), nil))
@ -4228,6 +4245,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
return return
} }
let context = self.context
let entities = self.node.entitiesView.entities.filter { !($0 is DrawingMediaEntity) } let entities = self.node.entitiesView.entities.filter { !($0 is DrawingMediaEntity) }
let codableEntities = DrawingEntitiesView.encodeEntities(entities, entitiesView: self.node.entitiesView) let codableEntities = DrawingEntitiesView.encodeEntities(entities, entitiesView: self.node.entitiesView)
mediaEditor.setDrawingAndEntities(data: nil, image: mediaEditor.values.drawing, entities: codableEntities) mediaEditor.setDrawingAndEntities(data: nil, image: mediaEditor.values.drawing, entities: codableEntities)
@ -4292,10 +4311,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
} }
case let .draft(draft, _): case let .draft(draft, _):
if draft.isVideo { if draft.isVideo {
let asset = AVURLAsset(url: NSURL(fileURLWithPath: draft.fullPath()) as URL) let asset = AVURLAsset(url: NSURL(fileURLWithPath: draft.fullPath(engine: context.engine)) as URL)
exportSubject = .single(.video(asset)) exportSubject = .single(.video(asset))
} else { } else {
if let image = UIImage(contentsOfFile: draft.fullPath()) { if let image = UIImage(contentsOfFile: draft.fullPath(engine: context.engine)) {
exportSubject = .single(.image(image)) exportSubject = .single(.image(image))
} else { } else {
fatalError() fatalError()
@ -4768,8 +4787,8 @@ public final class BlurredGradientComponent: Component {
} }
} }
func draftPath() -> String { func draftPath(engine: TelegramEngine) -> String {
return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/storyDrafts" return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/storyDrafts_\(engine.account.peerId.toInt64())"
} }
func hasFirstResponder(_ view: UIView) -> Bool { func hasFirstResponder(_ view: UIView) -> Bool {

View File

@ -6,24 +6,79 @@ import TelegramUIPreferences
import MediaEditor import MediaEditor
import AccountContext import AccountContext
public func saveStorySource(engine: TelegramEngine, item: MediaEditorDraft, peerId: EnginePeer.Id, id: Int64) { public func updateStorySources(engine: TelegramEngine) {
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
let _ = engine.data.get(
TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.storySources)
).start(next: { items in
for item in items {
let key = EngineDataBuffer(item.id)
let _ = getStorySource(engine: engine, key: key).start(next: { source in
if let source {
if let expiresOn = source.expiresOn, expiresOn < currentTimestamp {
let _ = removeStorySource(engine: engine, key: key, delete: true).start()
}
}
})
}
})
}
private func key(peerId: EnginePeer.Id, id: Int64) -> EngineDataBuffer {
let key = EngineDataBuffer(length: 16) let key = EngineDataBuffer(length: 16)
key.setInt64(0, value: peerId.toInt64()) key.setInt64(0, value: peerId.toInt64())
key.setInt64(8, value: id) key.setInt64(8, value: id)
return key
}
private class StorySourceItem: Codable {
}
private func addStorySource(engine: TelegramEngine, key: EngineDataBuffer) {
let _ = engine.orderedLists.addOrMoveToFirstPosition(
collectionId: ApplicationSpecificOrderedItemListCollectionId.storySources,
id: key.toMemoryBuffer(),
item: StorySourceItem(),
removeTailIfCountExceeds: nil
).start()
}
private func removeStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, id: Int64, delete: Bool) -> Signal<Never, NoError> {
let key = key(peerId: peerId, id: id)
return getStorySource(engine: engine, peerId: peerId, id: id)
|> mapToSignal { source in
if let source {
let _ = engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key).start()
removeStoryDraft(engine: engine, path: source.path, delete: delete)
}
return engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.storySources, id: key.toMemoryBuffer())
}
}
private func removeStorySource(engine: TelegramEngine, key: EngineDataBuffer, delete: Bool) -> Signal<Never, NoError> {
return getStorySource(engine: engine, key: key)
|> mapToSignal { source in
if let source {
let _ = engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key).start()
removeStoryDraft(engine: engine, path: source.path, delete: delete)
}
return engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.storySources, id: key.toMemoryBuffer())
}
}
public func saveStorySource(engine: TelegramEngine, item: MediaEditorDraft, peerId: EnginePeer.Id, id: Int64) {
let key = key(peerId: peerId, id: id)
addStorySource(engine: engine, key: key)
let _ = engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key, item: item).start() let _ = engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key, item: item).start()
} }
public func removeStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, id: Int64) { public func getStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, id: Int64) -> Signal<MediaEditorDraft?, NoError> {
let key = EngineDataBuffer(length: 16) let key = key(peerId: peerId, id: id)
key.setInt64(0, value: peerId.toInt64()) return getStorySource(engine: engine, key: key)
key.setInt64(8, value: id)
let _ = engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key).start()
} }
public func getStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, id: Int64) -> Signal<MediaEditorDraft?, NoError> { private func getStorySource(engine: TelegramEngine, key: EngineDataBuffer) -> Signal<MediaEditorDraft?, NoError> {
let key = EngineDataBuffer(length: 16)
key.setInt64(0, value: peerId.toInt64())
key.setInt64(8, value: id)
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key)) return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: key))
|> map { result -> MediaEditorDraft? in |> map { result -> MediaEditorDraft? in
return result?.get(MediaEditorDraft.self) return result?.get(MediaEditorDraft.self)
@ -31,20 +86,16 @@ public func getStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, id: In
} }
public func moveStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, from fromId: Int64, to toId: Int64) { public func moveStorySource(engine: TelegramEngine, peerId: EnginePeer.Id, from fromId: Int64, to toId: Int64) {
let fromKey = EngineDataBuffer(length: 16) let fromKey = key(peerId: peerId, id: fromId)
fromKey.setInt64(0, value: peerId.toInt64()) let toKey = key(peerId: peerId, id: toId)
fromKey.setInt64(8, value: fromId)
let toKey = EngineDataBuffer(length: 16)
toKey.setInt64(0, value: peerId.toInt64())
toKey.setInt64(8, value: toId)
let _ = (engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: fromKey)) let _ = (engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: fromKey))
|> mapToSignal { item -> Signal<Never, NoError> in |> mapToSignal { item -> Signal<Never, NoError> in
if let item = item?.get(MediaEditorDraft.self) { if let item = item?.get(MediaEditorDraft.self) {
addStorySource(engine: engine, key: toKey)
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: toKey, item: item) return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: toKey, item: item)
|> then( |> then(
engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.storySource, id: fromKey) removeStorySource(engine: engine, key: fromKey, delete: false)
) )
} else { } else {
return .complete() return .complete()

View File

@ -38,6 +38,7 @@ import PhoneNumberFormat
import AuthorizationUI import AuthorizationUI
import ManagedFile import ManagedFile
import DeviceProximity import DeviceProximity
import MediaEditor
#if canImport(AppCenter) #if canImport(AppCenter)
import AppCenter import AppCenter
@ -1291,6 +1292,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
let _ = (updateIntentsSettingsInteractively(accountManager: accountManager) { current in let _ = (updateIntentsSettingsInteractively(accountManager: accountManager) { current in
var updated = current var updated = current
for peerId in loggedOutAccountPeerIds { for peerId in loggedOutAccountPeerIds {
deleteAllStoryDrafts(peerId: peerId)
if peerId == updated.account { if peerId == updated.account {
deleteAllSendMessageIntents() deleteAllSendMessageIntents()
updated = updated.withUpdatedAccount(nil) updated = updated.withUpdatedAccount(nil)

View File

@ -100,6 +100,7 @@ private enum ApplicationSpecificOrderedItemListCollectionIdValues: Int32 {
case settingsSearchRecentItems = 2 case settingsSearchRecentItems = 2
case localThemes = 3 case localThemes = 3
case storyDrafts = 4 case storyDrafts = 4
case storySources = 5
} }
public struct ApplicationSpecificOrderedItemListCollectionId { public struct ApplicationSpecificOrderedItemListCollectionId {
@ -108,4 +109,5 @@ public struct ApplicationSpecificOrderedItemListCollectionId {
public static let settingsSearchRecentItems = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.settingsSearchRecentItems.rawValue) public static let settingsSearchRecentItems = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.settingsSearchRecentItems.rawValue)
public static let localThemes = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.localThemes.rawValue) public static let localThemes = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.localThemes.rawValue)
public static let storyDrafts = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.storyDrafts.rawValue) public static let storyDrafts = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.storyDrafts.rawValue)
public static let storySources = applicationSpecificOrderedItemListCollectionId(ApplicationSpecificOrderedItemListCollectionIdValues.storySources.rawValue)
} }