Cache volume samples
This commit is contained in:
parent
6fbc7396b8
commit
1e8b1d3fca
|
@ -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 */,
|
||||
|
|
|
@ -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,13 +55,22 @@ final class VoiceMessageView2 : UIView {
|
|||
guard let url = (voiceMessage as? TSAttachmentStream)?.originalMediaURL else {
|
||||
return print("[Loki] Couldn't get URL for voice message.")
|
||||
}
|
||||
if let cachedVolumeSamples = Storage.getVolumeSamples(for: voiceMessage.uniqueId!) {
|
||||
self.volumeSamples = cachedVolumeSamples
|
||||
self.stopAnimating()
|
||||
} 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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue