Swiftgram/TelegramUI/PeerMediaAudioPlaylist.swift
2018-01-09 13:18:08 +04:00

223 lines
9.5 KiB
Swift

import Foundation
import Postbox
import TelegramCore
import SwiftSignalKit
struct PeerMessageHistoryAudioPlaylistItemId: AudioPlaylistItemId {
let id: MessageId
var hashValue: Int {
return self.id.hashValue
}
func isEqual(to: AudioPlaylistItemId) -> Bool {
if let other = to as? PeerMessageHistoryAudioPlaylistItemId {
return self.id == other.id
} else {
return false
}
}
}
final class PeerMessageHistoryAudioPlaylistItem: AudioPlaylistItem {
let entry: MessageHistoryEntry
var id: AudioPlaylistItemId {
return PeerMessageHistoryAudioPlaylistItemId(id: self.entry.index.id)
}
var resource: MediaResource? {
switch self.entry {
case let .MessageEntry(message, _, _, _):
for media in message.media {
if let file = media as? TelegramMediaFile {
return file.resource
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let file = content.file {
return file.resource
}
}
return nil
case .HoleEntry:
return nil
}
}
var streamable: Bool {
switch self.entry {
case let .MessageEntry(message, _, _, _):
for media in message.media {
if let file = media as? TelegramMediaFile {
if file.isMusic {
return true
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let file = content.file {
if file.isMusic {
return true
}
}
}
}
return false
case .HoleEntry:
return false
}
}
var info: AudioPlaylistItemInfo? {
switch self.entry {
case let .MessageEntry(message, _, _, _):
for media in message.media {
if let file = media as? TelegramMediaFile {
for attribute in file.attributes {
switch attribute {
case let .Audio(isVoice, duration, title, performer, _):
if isVoice {
return AudioPlaylistItemInfo(duration: Double(duration), labelInfo: .voice)
} else {
return AudioPlaylistItemInfo(duration: Double(duration), labelInfo: .music(title: title, performer: performer))
}
case let .Video(duration, _, flags):
if flags.contains(.instantRoundVideo) {
return AudioPlaylistItemInfo(duration: Double(duration), labelInfo: .video)
}
default:
break
}
}
return nil
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let file = content.file {
for attribute in file.attributes {
switch attribute {
case let .Audio(isVoice, duration, title, performer, _):
if isVoice {
return AudioPlaylistItemInfo(duration: Double(duration), labelInfo: .voice)
} else {
return AudioPlaylistItemInfo(duration: Double(duration), labelInfo: .music(title: title, performer: performer))
}
case let .Video(duration, _, flags):
if flags.contains(.instantRoundVideo) {
return AudioPlaylistItemInfo(duration: Double(duration), labelInfo: .video)
}
default:
break
}
}
return nil
}
}
case .HoleEntry:
break
}
return nil
}
init(entry: MessageHistoryEntry) {
self.entry = entry
}
func isEqual(to: AudioPlaylistItem) -> Bool {
if let other = to as? PeerMessageHistoryAudioPlaylistItem {
return self.entry == other.entry
} else {
return false
}
}
}
struct PeerMessageHistoryAudioPlaylistId: AudioPlaylistId {
let peerId: PeerId
func isEqual(to: AudioPlaylistId) -> Bool {
if let other = to as? PeerMessageHistoryAudioPlaylistId {
if self.peerId != other.peerId {
return false
}
return true
} else {
return false
}
}
}
func peerMessageAudioPlaylistAndItemIds(_ message: Message) -> (AudioPlaylistId, AudioPlaylistItemId)? {
return (PeerMessageHistoryAudioPlaylistId(peerId: message.id.peerId), PeerMessageHistoryAudioPlaylistItemId(id: message.id))
}
func peerMessageHistoryAudioPlaylist(account: Account, messageId: MessageId) -> AudioPlaylist {
return AudioPlaylist(id: PeerMessageHistoryAudioPlaylistId(peerId: messageId.peerId), navigate: { item, navigation in
if let item = item as? PeerMessageHistoryAudioPlaylistItem {
var tagMask: MessageTags?
switch item.entry {
case let .MessageEntry(message, _, _, _):
for media in message.media {
if let file = media as? TelegramMediaFile {
inner: for attribute in file.attributes {
switch attribute {
case let .Video(_, _, flags):
if flags.contains(.instantRoundVideo) {
tagMask = .voiceOrInstantVideo
break inner
}
case let .Audio(isVoice, _, _, _, _):
if isVoice {
tagMask = .voiceOrInstantVideo
} else {
tagMask = .music
}
break inner
default:
break
}
}
break
}
}
case .HoleEntry:
break
}
if let tagMask = tagMask {
return account.postbox.aroundMessageHistoryViewForLocation(.peer(item.entry.index.id.peerId), index: .message(item.entry.index), anchorIndex: .message(item.entry.index), count: 10, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, orderStatistics: [])
|> take(1)
|> map { (view, _, _) -> AudioPlaylistItem? in
var index = 0
for entry in view.entries {
if entry.index.id == item.entry.index.id {
switch navigation {
case .previous:
if index != 0 {
return PeerMessageHistoryAudioPlaylistItem(entry: view.entries[index - 1])
} else {
return PeerMessageHistoryAudioPlaylistItem(entry: view.entries.first!)
}
case .next:
if index + 1 < view.entries.count {
return PeerMessageHistoryAudioPlaylistItem(entry: view.entries[index + 1])
} else {
return nil//PeerMessageHistoryAudioPlaylistItem(entry: view.entries.last!)
}
}
}
index += 1
}
if !view.entries.isEmpty {
return PeerMessageHistoryAudioPlaylistItem(entry: view.entries.first!)
} else {
return nil
}
}
} else {
return .single(nil)
}
} else {
return account.postbox.messageAtId(messageId)
|> map { message -> AudioPlaylistItem? in
if let message = message {
return PeerMessageHistoryAudioPlaylistItem(entry: .MessageEntry(message, false, nil, nil))
} else {
return nil
}
}
}
})
}