Cache volume samples

This commit is contained in:
nielsandriesse 2020-10-01 14:24:00 +10:00
parent 6fbc7396b8
commit 1e8b1d3fca
6 changed files with 54 additions and 16 deletions

View File

@ -572,6 +572,7 @@
C31D1DE32521718E005D4DA8 /* UserSelectionVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31D1DE22521718E005D4DA8 /* UserSelectionVC.swift */; };
C31D1DE9252172D4005D4DA8 /* ContactUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31D1DE8252172D4005D4DA8 /* ContactUtilities.swift */; };
C31F8117252546F200DD9FD9 /* file_example_MP3_2MG.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C31F8116252546F200DD9FD9 /* file_example_MP3_2MG.mp3 */; };
C31F812625258FB000DD9FD9 /* Storage+VolumeSamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31F812525258FB000DD9FD9 /* Storage+VolumeSamples.swift */; };
C329FEEC24F7277900B1C64C /* LightModeSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEEB24F7277900B1C64C /* LightModeSheet.swift */; };
C329FEEF24F7743F00B1C64C /* UIViewController+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */; };
C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; };
@ -1372,6 +1373,7 @@
C31D1DE22521718E005D4DA8 /* UserSelectionVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSelectionVC.swift; sourceTree = "<group>"; };
C31D1DE8252172D4005D4DA8 /* ContactUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactUtilities.swift; sourceTree = "<group>"; };
C31F8116252546F200DD9FD9 /* file_example_MP3_2MG.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = file_example_MP3_2MG.mp3; sourceTree = "<group>"; };
C31F812525258FB000DD9FD9 /* Storage+VolumeSamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+VolumeSamples.swift"; sourceTree = "<group>"; };
C329FEEB24F7277900B1C64C /* LightModeSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightModeSheet.swift; sourceTree = "<group>"; };
C329FEED24F7742E00B1C64C /* UIViewController+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Utilities.swift"; sourceTree = "<group>"; };
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
@ -2602,6 +2604,7 @@
isa = PBXGroup;
children = (
B8CCF63B239757C10091D419 /* Components */,
C31F812425258F9C00DD9FD9 /* Database */,
C32B405424A961E1001117B5 /* Dependencies */,
B8CCF63C239757DB0091D419 /* Utilities */,
B8CCF63D2397580E0091D419 /* View Controllers */,
@ -2754,6 +2757,14 @@
path = "View Controllers";
sourceTree = "<group>";
};
C31F812425258F9C00DD9FD9 /* Database */ = {
isa = PBXGroup;
children = (
C31F812525258FB000DD9FD9 /* Storage+VolumeSamples.swift */,
);
path = Database;
sourceTree = "<group>";
};
C32B405424A961E1001117B5 /* Dependencies */ = {
isa = PBXGroup;
children = (
@ -3998,6 +4009,7 @@
340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */,
B88847BC23E10BC6009836D2 /* GroupMembersVC.swift in Sources */,
B85357BF23A1AE0800AAF6CD /* SeedReminderView.swift in Sources */,
C31F812625258FB000DD9FD9 /* Storage+VolumeSamples.swift in Sources */,
B85357C723A1FB5100AAF6CD /* LinkDeviceVCDelegate.swift in Sources */,
340FC8C5204DE223007AEB0F /* DebugUIBackup.m in Sources */,
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */,

View File

@ -6,7 +6,6 @@ final class VoiceMessageView2 : UIView {
private var isAnimating = false
private var volumeSamples: [Float] = [] { didSet { updateShapeLayers() } }
private var progress: CGFloat = 0
private var duration: CGFloat = 1 // Not initialized at 0 to avoid division by zero
// MARK: Components
private lazy var loader: UIView = {
@ -31,6 +30,8 @@ final class VoiceMessageView2 : UIView {
private let margin: CGFloat = 4
private let sampleSpacing: CGFloat = 1
@objc public static let contentHeight: CGFloat = 40
// MARK: Initialization
@objc(initWithVoiceMessage:)
init(voiceMessage: TSAttachment) {
@ -54,12 +55,21 @@ final class VoiceMessageView2 : UIView {
guard let url = (voiceMessage as? TSAttachmentStream)?.originalMediaURL else {
return print("[Loki] Couldn't get URL for voice message.")
}
AudioUtilities.getVolumeSamples(for: url).done(on: DispatchQueue.main) { [weak self] volumeSamples in
guard let self = self else { return }
self.volumeSamples = volumeSamples
if let cachedVolumeSamples = Storage.getVolumeSamples(for: voiceMessage.uniqueId!) {
self.volumeSamples = cachedVolumeSamples
self.stopAnimating()
}.catch(on: DispatchQueue.main) { error in
print("[Loki] Couldn't sample audio file due to error: \(error).")
} else {
let voiceMessageID = voiceMessage.uniqueId!
AudioUtilities.getVolumeSamples(for: url).done(on: DispatchQueue.main) { [weak self] volumeSamples in
guard let self = self else { return }
self.volumeSamples = volumeSamples
Storage.write { transaction in
Storage.setVolumeSamples(for: voiceMessageID, to: volumeSamples, using: transaction)
}
self.stopAnimating()
}.catch(on: DispatchQueue.main) { error in
print("[Loki] Couldn't sample audio file due to error: \(error).")
}
}
} else {
showLoader()
@ -68,7 +78,7 @@ final class VoiceMessageView2 : UIView {
private func setUpViewHierarchy() {
set(.width, to: 200)
set(.height, to: 40)
set(.height, to: VoiceMessageView2.contentHeight)
addSubview(loader)
loader.pin(to: self)
layer.insertSublayer(backgroundShapeLayer, at: 0)
@ -83,9 +93,9 @@ final class VoiceMessageView2 : UIView {
}
private func animateLoader() {
loader.frame = CGRect(x: 0, y: 0, width: 0, height: 40)
loader.frame = CGRect(x: 0, y: 0, width: 0, height: VoiceMessageView2.contentHeight)
UIView.animate(withDuration: 2) { [weak self] in
self?.loader.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
self?.loader.frame = CGRect(x: 0, y: 0, width: 200, height: VoiceMessageView2.contentHeight)
} completion: { [weak self] _ in
guard let self = self else { return }
if self.isAnimating { self.animateLoader() }
@ -102,10 +112,9 @@ final class VoiceMessageView2 : UIView {
updateShapeLayers()
}
@objc(updateForProgress:duration:)
func update(for progress: CGFloat, duration: CGFloat) {
@objc(updateForProgress:)
func update(for progress: CGFloat) {
self.progress = progress
self.duration = duration
updateShapeLayers()
}
@ -125,7 +134,7 @@ final class VoiceMessageView2 : UIView {
let y = margin + (h - sH) / 2
let subPath = UIBezierPath(roundedRect: CGRect(x: x, y: y, width: sW, height: sH), cornerRadius: sW / 2)
backgroundPath.append(subPath)
if progress / duration > CGFloat(i) / CGFloat(volumeSamples.count) { foregroundPath.append(subPath) }
if progress > CGFloat(i) / CGFloat(volumeSamples.count) { foregroundPath.append(subPath) }
}
backgroundPath.close()
foregroundPath.close()

View File

@ -0,0 +1,17 @@
extension Storage {
static let volumeSamplesCollection = "LokiVolumeSamplesCollection"
static func getVolumeSamples(for attachment: String) -> [Float]? {
var result: [Float]?
read { transaction in
result = transaction.object(forKey: attachment, inCollection: volumeSamplesCollection) as? [Float]
}
return result
}
static func setVolumeSamples(for attachment: String, to volumeSamples: [Float], using transaction: YapDatabaseReadWriteTransaction) {
transaction.setObject(volumeSamples, forKey: attachment, inCollection: volumeSamplesCollection)
}
}

View File

@ -1063,7 +1063,7 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
case OWSMessageCellType_Audio:
result = CGSizeMake(maxMessageWidth, 40.0f);
result = CGSizeMake(maxMessageWidth, LKVoiceMessageView2.contentHeight);
break;
case OWSMessageCellType_GenericAttachment: {
TSAttachment *attachment = (self.viewItem.attachmentStream ?: self.viewItem.attachmentPointer);

View File

@ -484,7 +484,7 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
self.audioProgressSeconds = progress;
[self.lastAudioMessageView updateForProgress:progress duration:duration];
[self.lastAudioMessageView updateForProgress:progress / duration];
}
#pragma mark - Displayable Text

View File

@ -146,7 +146,7 @@ NS_ASSUME_NONNULL_BEGIN
[self.audioPlayer play];
[self.audioPlayerPoller invalidate];
self.audioPlayerPoller = [NSTimer weakScheduledTimerWithTimeInterval:.5f
self.audioPlayerPoller = [NSTimer weakScheduledTimerWithTimeInterval:.05f
target:self
selector:@selector(audioPlayerUpdated:)
userInfo:nil