You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
8.6 KiB
343 lines
8.6 KiB
//
|
|
// Created by Marco Schmickler on 25.05.15.
|
|
// Copyright (c) 2015 Marco Schmickler. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
import Combine
|
|
import CoreData
|
|
|
|
/**
|
|
Repräsentiert ein Item eines der festgelegten Typen.
|
|
*/
|
|
class MediaItem: CustomDebugStringConvertible, ObservableObject, Identifiable {
|
|
|
|
/**
|
|
Wird durch name, path und root identifiziert.
|
|
*/
|
|
var name: String
|
|
var path: String
|
|
var root: String
|
|
|
|
var children: [MediaItem]
|
|
var parent: MediaItem?
|
|
var type: ItemType
|
|
|
|
/**
|
|
Position innerhalb der Children
|
|
*/
|
|
var index = 0
|
|
var indexId = 0
|
|
|
|
/**
|
|
true, wenn die Children geladen sind
|
|
*/
|
|
var loaded = false
|
|
|
|
// abgeleitet
|
|
var sortName = ""
|
|
|
|
// Nutzinhalt
|
|
@Published
|
|
var image: UIImage?
|
|
|
|
@Published
|
|
var thumbImage: UIImage?
|
|
|
|
// let didChange = PassthroughSubject<MediaItem,Never>()
|
|
|
|
@Published
|
|
var time: TimeInterval = 0.0
|
|
//
|
|
// {
|
|
// willSet {
|
|
// // print(newValue)
|
|
// // didChange.send(self)
|
|
// self.objectWillChange.send()
|
|
// }
|
|
// }
|
|
|
|
@Published
|
|
var length: TimeInterval = 0.0
|
|
|
|
@Published
|
|
var rating = 0
|
|
|
|
@Published
|
|
var loop = true
|
|
|
|
var thumbUrl: String?
|
|
var externalURL: String?
|
|
var localURL: URL?
|
|
|
|
var local = false
|
|
var external = false
|
|
var leaf = false
|
|
var cancelled = false
|
|
|
|
var favorite = false
|
|
|
|
var compilation = false
|
|
|
|
var objectID : NSManagedObjectID?
|
|
|
|
@Published
|
|
var scale = 0.0
|
|
@Published
|
|
var offset = CGPoint()
|
|
|
|
var size = CGSize()
|
|
|
|
var tags = [String]()
|
|
|
|
var cookies = ""
|
|
|
|
convenience init(model: MediaModel) {
|
|
self.init(name: model.name, path: model.path, root: model.root, type: model.type)
|
|
|
|
self.time = model.time
|
|
self.length = model.length
|
|
self.loop = model.loop
|
|
self.thumbUrl = LocalManager.sharedInstance.fixDocumentURL(model.thumbURL)
|
|
self.externalURL = LocalManager.sharedInstance.fixDocumentURL(model.externalURL)
|
|
self.scale = model.scale
|
|
self.offset = model.offset
|
|
self.size = model.size
|
|
self.favorite = model.favorite
|
|
self.loaded = true
|
|
self.local = true
|
|
self.indexId = model.indexId
|
|
self.tags = model.tags
|
|
|
|
for m in model.children {
|
|
let item = MediaItem(model: m)
|
|
item.index = children.count
|
|
item.parent = self
|
|
item.loaded = true
|
|
item.local = true
|
|
children.append(item)
|
|
}
|
|
}
|
|
|
|
func toMediaModel() -> MediaModel {
|
|
var c = [MediaModel]()
|
|
|
|
for m in children {
|
|
let mm = m.toMediaModel()
|
|
c.append(mm)
|
|
}
|
|
var model: MediaModel = MediaModel(name: name, path: path, root: root, children: c, type: type)
|
|
|
|
model.time = time
|
|
model.loop = loop
|
|
model.length = length
|
|
model.thumbURL = thumbUrl
|
|
model.externalURL = externalURL
|
|
model.size = size
|
|
model.offset = offset
|
|
model.scale = scale
|
|
model.favorite = favorite
|
|
model.indexId = indexId
|
|
model.tags = tags
|
|
|
|
return model
|
|
}
|
|
|
|
func toJSON() -> String {
|
|
let jsonEncoder = JSONEncoder()
|
|
let jsonData = try! jsonEncoder.encode(toMediaModel())
|
|
let json = String(data: jsonData, encoding: String.Encoding.utf8)
|
|
return json!
|
|
}
|
|
|
|
init(name: String, path: String, root: String, type: ItemType) {
|
|
self.name = name
|
|
let trim = CharacterSet(charactersIn: "/ ")
|
|
self.root = "/" + root.trimmingCharacters(in: trim)
|
|
self.path = path.trimmingCharacters(in: trim)
|
|
self.type = type
|
|
|
|
children = [MediaItem]()
|
|
|
|
sortName = computeSortName(name)
|
|
}
|
|
|
|
fileprivate func computeSortName(_ sname: String) -> String {
|
|
var lsortName = sname.replacingOccurrences(of: "full", with: "")
|
|
let fullNameArr = lsortName.split {
|
|
$0 == "_"
|
|
}.map {
|
|
String($0)
|
|
}
|
|
|
|
if !fullNameArr.isEmpty {
|
|
lsortName = fullNameArr[0]
|
|
}
|
|
|
|
while lsortName.count < 6 {
|
|
lsortName = "0" + lsortName
|
|
}
|
|
|
|
return lsortName
|
|
}
|
|
|
|
/**
|
|
Ordner, in dem die Snapshots eines Videos abgelegt sind.
|
|
Absoluter Pfad mit Slash am Ende.
|
|
*/
|
|
var snapshotDirPathForVideo: String {
|
|
let len = "/srv/samba/ren".count
|
|
let rootPostfix = (root as NSString).substring(from: len)
|
|
let tpath = "/srv/samba/ren/thumb\(rootPostfix)/\(path)\(name)"
|
|
let enc = tpath.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
|
|
|
|
return enc + "/"
|
|
}
|
|
|
|
/**
|
|
Absolute URL, unter der das Thumbnail des Items abgerufen werden kann.
|
|
*/
|
|
var thumbUrlAbsolute: String {
|
|
if thumbUrl == nil {
|
|
return ""
|
|
}
|
|
if thumbUrl!.starts(with: "file:") {
|
|
return thumbUrl!
|
|
}
|
|
|
|
let enc = thumbUrl!.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
|
|
return NetworkManager.sharedInstance.baseurl + "/service/download/srv/samba" + enc.substringStartingFrom(10)
|
|
}
|
|
|
|
var nameWithoutExtension: String {
|
|
name.replacingOccurrences(of: ".mp4", with: "")
|
|
}
|
|
|
|
/**
|
|
Absolute URL, unter der das Image des Items abgerufen werden kann.
|
|
*/
|
|
var imageUrlAbsolute: String {
|
|
if thumbUrl!.starts(with: "file:") {
|
|
return thumbUrl!
|
|
}
|
|
|
|
var imageUrl = thumbUrl!.replacingOccurrences(of: "_thumb.", with: ".")
|
|
imageUrl = imageUrl.replacingOccurrences(of: "?preview=true", with: "")
|
|
imageUrl = imageUrl.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
|
|
|
|
return NetworkManager.sharedInstance.vidurl + imageUrl.substringStartingFrom(10)
|
|
}
|
|
|
|
var playerURL: URL? {
|
|
if let ext = externalURL {
|
|
return URL(string: ext)
|
|
}
|
|
|
|
if local {
|
|
var file = FileHelper.getDocumentsDirectory()
|
|
if external {
|
|
file = URL(string: LocalManager.sharedInstance.externalURL)!
|
|
}
|
|
|
|
if (path != "") {
|
|
file = file.appendingPathComponent(path)
|
|
}
|
|
file = file.appendingPathComponent(name)
|
|
return file
|
|
}
|
|
|
|
let enc = name.replacingOccurrences(of: " ", with: "%20")
|
|
|
|
var encoded : String
|
|
|
|
if encodedDir!.count >= 10 {
|
|
let index = encodedDir!.index(encodedDir!.startIndex, offsetBy: 10)
|
|
encoded = String(encodedDir![index...])
|
|
}
|
|
else {
|
|
encoded = encodedDir!
|
|
}
|
|
|
|
let s = NetworkManager.sharedInstance.vidurl + encoded
|
|
|
|
if s.endsWith("/") {
|
|
return URL(string: s + enc)
|
|
}
|
|
else {
|
|
return URL(string: s + "/" + enc)
|
|
}
|
|
}
|
|
|
|
/**
|
|
Absoluter Pfad des Items.
|
|
*/
|
|
var fullPath: String {
|
|
let fpath = "\(root)/\(path)/\(name)"
|
|
let enc = fpath.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
|
|
return enc
|
|
}
|
|
|
|
var debugDescription: String {
|
|
return "\(type): \(root) \(path) \(name) (\(index)) Child count \(children.count)"
|
|
}
|
|
|
|
var encodedDir: String? {
|
|
let dir = "\(root)/\(path)"
|
|
|
|
return dir.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)
|
|
}
|
|
|
|
func superRoot() -> MediaItem {
|
|
if let p = parent {
|
|
return p.superRoot()
|
|
}
|
|
|
|
return self
|
|
}
|
|
|
|
func sort() {
|
|
children.sort(by: {
|
|
$0.sortName < $1.sortName
|
|
})
|
|
|
|
var j = 0
|
|
for i in children {
|
|
i.index = j
|
|
j += 1
|
|
}
|
|
}
|
|
|
|
func isWeb() -> Bool {
|
|
type == ItemType.WEB
|
|
}
|
|
|
|
func isPic() -> Bool {
|
|
type == ItemType.PICS || type == ItemType.PICFOLDER
|
|
}
|
|
|
|
func isVideo() -> Bool {
|
|
type == ItemType.VIDEOFOLDER || type == ItemType.VIDEO || type == ItemType.SNAPSHOT
|
|
}
|
|
|
|
func isDetails() -> Bool {
|
|
type == ItemType.VIDEOFOLDER || type == ItemType.PICFOLDER || type == ItemType.WEB || type == ItemType.TAG
|
|
// isWeb() || isPic() || isVideo()
|
|
}
|
|
|
|
func isFolder() -> Bool {
|
|
type == ItemType.REMOTEROOT || type == ItemType.FOLDER || type == ItemType.WEBROOT || type == ItemType.FAVROOT || type == ItemType.TAGROOT
|
|
}
|
|
|
|
func clone() -> MediaItem {
|
|
let m = MediaItem(model: toMediaModel())
|
|
m.local = local
|
|
m.compilation = compilation
|
|
|
|
for c in m.children {
|
|
c.local = local
|
|
}
|
|
|
|
return m
|
|
}
|
|
}
|