diff --git a/kplayer/core/KSettings.swift b/kplayer/core/KSettings.swift index 1a62059..1836854 100644 --- a/kplayer/core/KSettings.swift +++ b/kplayer/core/KSettings.swift @@ -12,6 +12,9 @@ class KSettings: ObservableObject { @Published var autoloop = false + @Published + var slow = false + @Published var zoomed = false @@ -26,10 +29,11 @@ class KSettings: ObservableObject { scale = model.scale autoloop = model.autoloop zoomed = model.zoomed + slow = model.slow } func toModel() -> KSettingsModel { - KSettingsModel(scale: scale, autoloop: autoloop, zoomed: zoomed) + KSettingsModel(scale: scale, autoloop: autoloop, zoomed: zoomed, slow: slow) } func toJSON() -> String { diff --git a/kplayer/core/KSettingsModel.swift b/kplayer/core/KSettingsModel.swift index d776de7..9dbbcff 100644 --- a/kplayer/core/KSettingsModel.swift +++ b/kplayer/core/KSettingsModel.swift @@ -9,4 +9,5 @@ struct KSettingsModel: Codable { var scale = Float(0.5) var autoloop = false var zoomed = false + var slow = false } diff --git a/kplayer/core/MediaItem.swift b/kplayer/core/MediaItem.swift index ad3f68c..6c836ee 100644 --- a/kplayer/core/MediaItem.swift +++ b/kplayer/core/MediaItem.swift @@ -173,7 +173,12 @@ class MediaItem: CustomDebugStringConvertible, ObservableObject, Identifiable { } if !fullNameArr.isEmpty { - lsortName = fullNameArr[0] + if fullNameArr[0] == "PB" { + lsortName = fullNameArr[1] + } + else { + lsortName = fullNameArr[0] + } } while lsortName.count < 6 { diff --git a/kplayer/detail/DetailViewController+Show.swift b/kplayer/detail/DetailViewController+Show.swift index 6c6ace5..7fc4ba8 100644 --- a/kplayer/detail/DetailViewController+Show.swift +++ b/kplayer/detail/DetailViewController+Show.swift @@ -126,7 +126,7 @@ extension DetailViewController { let model = SVideoModel(allItems: children, currentSnapshot: se, baseItem: baseItem) model.edit = delegate!.settings().edit - model.loop = delegate!.settings().autoloop + model.slow = delegate!.settings().slow model.zoomed = delegate!.settings().zoomed let player = SVideoPlayer(completionHandler: { saved in diff --git a/kplayer/master/KSettingsView.swift b/kplayer/master/KSettingsView.swift index 750a227..98600a8 100644 --- a/kplayer/master/KSettingsView.swift +++ b/kplayer/master/KSettingsView.swift @@ -27,6 +27,9 @@ struct KSettingsView: View { Toggle(isOn: $kSettings.edit, label: { Text("Edit") }) + Toggle(isOn: $kSettings.slow, label: { + Text("Slow") + }) Toggle(isOn: $kSettings.automaticallyWaitsToMinimizeStalling, label: { Text("Stalling") }) diff --git a/kplayer/photo/SPhotoView.swift b/kplayer/photo/SPhotoView.swift index b602cea..963f811 100644 --- a/kplayer/photo/SPhotoView.swift +++ b/kplayer/photo/SPhotoView.swift @@ -33,6 +33,7 @@ struct SPhotoView: View { @State var lastDragOffset: CGSize = CGSize.zero @State var lastDrag: CGSize = CGSize.zero @State var skip = false + @State var startindex = -1 @State var animateX = 0 @State var dampen = 0.05 @@ -54,7 +55,7 @@ struct SPhotoView: View { Text("...") } } - .frame(height: geo.size.height).frame(width: geo.size.width) + .frame(height: geo.size.height).frame(width: geo.size.width, alignment: .leading) .scaleEffect(model.scale).offset(model.dragOffset).modifier(KAnimate(dragOffset: model.dragOffset, spring: model.spring)) .onTapGesture(count: 2) { print("3 tapped!") @@ -72,14 +73,18 @@ struct SPhotoView: View { let dragged = gesture.translation let multi = (model.spring) ? 2.0 : 3.0 - if gesture.startLocation.y < 100 && gesture.startLocation.x < 400 { - if dragged.width > 50 && model.index < model.allItems.count - 1 && !skip { - model.index += 1 - skip = true + if startindex < 0 { + startindex = model.index + } + + if gesture.startLocation.y < 200 { //&& gesture.startLocation.x < 400 { + model.index = startindex + Int(dragged.width / 30.0) + print(dragged.width) + if model.index >= model.allItems.count { + model.index = model.allItems.count - 1 } - if dragged.width < -50 && model.index > 0 && !skip { - model.index -= 1 - skip = true + if model.index < 0 { + model.index = 0 } } else { if (dragged.height * multi) + lastDragOffset.height > -1000 { @@ -90,6 +95,7 @@ struct SPhotoView: View { lastDrag = dragged } .onEnded { gesture in + startindex = -1 lastDragOffset = model.dragOffset dampen = 0.05 skip = false diff --git a/kplayer/server/kplayer.js b/kplayer/server/kplayer.js index a670c1b..2ad8c56 100644 --- a/kplayer/server/kplayer.js +++ b/kplayer/server/kplayer.js @@ -115,6 +115,77 @@ app.get('/listdirs/*', function (req, res) { res.end(JSON.stringify(result)) }) +app.get('/listvideos/*', function (req, res) { + var address = decodeURIComponent(req.path.substr(11)) + console.log("listdirs " + address); + + if (!req.path.startsWith("/listfiles/srv/samba/ren/")) { + res.end("Access denied") + return + } + var result = []; + + try { + var files = getFiles(address) + + files.forEach(function(file){ + var filename = path.resolve(address, file.name) + + console.log(filename) + + if (filename.endsWith(".mp4")) + result.push(filename) + if (filename.endsWith(".m4v")) + result.push(filename) + }) + } + catch { + + } + + res.end(JSON.stringify(result)) +}) + +/* +@RequestMapping (method = RequestMethod.GET, value = "/listvideos/**") + @ResponseBody List listvideos(HttpServletRequest request, HttpServletResponse response) { + String address = (String) request.getAttribute( + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); + + address = address["/service/listvideos".length()..-1] + println "listvideos " + address; + String filter = null + + if (address.indexOf("*") > 0) { + def param = address.split(Pattern.quote("*")) + address = param[0] + filter = param[1].toLowerCase() + + println "filter !" + filter + "!" + } + + + def b = [] + + new File(address).eachFileRecurse() { file -> + if (filter && !file.name.toLowerCase().contains(filter)) { + // ignore + } + else { + if (!file.name.startsWith(".")) { + if (file.name.toLowerCase().endsWith("mp4")) b << file.absolutePath + + if (file.name.toLowerCase().endsWith("m4v")) b << file.absolutePath + } + } + } + + return b + } + +* */ + + var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads') diff --git a/kplayer/video/SVideoModel.swift b/kplayer/video/SVideoModel.swift index e940a84..900a97b 100644 --- a/kplayer/video/SVideoModel.swift +++ b/kplayer/video/SVideoModel.swift @@ -24,6 +24,7 @@ class SVideoModel : ObservableObject { @Published var edit = false @Published var dirty = false @Published var loop = false + @Published var slow = false @Published var zoomed = false @Published var favorite = false diff --git a/kplayer/video/SVideoPlayer.swift b/kplayer/video/SVideoPlayer.swift index 6d74028..609caba 100644 --- a/kplayer/video/SVideoPlayer.swift +++ b/kplayer/video/SVideoPlayer.swift @@ -28,7 +28,7 @@ struct SVideoPlayer: View, EditItemDelegate { @State var upsidedown = false @State var more = false @State var tilt = false - @State var slow = false + @State var jump = false @State var smoothTime = -1.0 @State var smoothSeekTime = -1.0 @State var timeCounter = 0 @@ -121,7 +121,9 @@ struct SVideoPlayer: View, EditItemDelegate { Text(model.currentSnapshot.name).foregroundColor(Color.blue) - Text("(\(model.codec) \(model.height), \(model.nominalFrameRate), \(model.bitRate)m)").foregroundColor(Color.blue) + Text(""" + (\(model.codec) \(model.height), \(model.nominalFrameRate), \(model.bitRate)m)\n\(model.scale, specifier: "%.2f")x (\(model.dragOffset.width, specifier: "%.0f"),\(model.dragOffset.height, specifier: "%.0f")) + """).foregroundColor(Color.blue) ScrollView(.horizontal, showsIndicators: false) { HStack { @@ -130,7 +132,7 @@ struct SVideoPlayer: View, EditItemDelegate { gotoSnapshot(item) }) { AsyncImage(item: item, placeholder: { Text("Loading ...") }, - image: { Image(uiImage: $0).resizable() }) + image: { Image(uiImage: $0).resizable() }).border(.yellow, width: (item===model.currentSnapshot) ? 1 : 0) .overlay(Image(systemName: "repeat.circle").offset(x: 20, y: -20).opacity((item.length > 0.0) ? 1 : 0)) } } @@ -216,8 +218,9 @@ struct SVideoPlayer: View, EditItemDelegate { .frame(height: 30) .foregroundColor(tilt ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle()) - KToggleButton(text: "slow", binding: $slow).frame(height: 30) + KToggleButton(text: "slow", binding: $model.slow).frame(height: 30) KToggleButton(text: "zoom", binding: $model.zoomed).frame(height: 30) + KToggleButton(text: "jump", binding: $jump).frame(height: 30) KToggleButton(text: "loop", binding: $model.loop).frame(height: 30) // .fullScreenCover(isPresented: $model.loop) { // SVideoLoopPlayer(completionHandler: { @@ -447,9 +450,8 @@ struct SVideoPlayer: View, EditItemDelegate { smoothTime = time } - if (start.y < 130) { + if (start.y < 170) { let delta = (dragged.width + dragged.height) / 400.0 - print(start.y) seekTimeSmoothly(smoothTime + delta) return false @@ -458,12 +460,10 @@ struct SVideoPlayer: View, EditItemDelegate { return true } else { - let dragWidth = 20.0 - if dragged.width > dragWidth { - seekTime(time + 4.0) - } else if dragged.width < -dragWidth { - seekTime(time - 5.0) - } + let delta = (dragged.width + dragged.height) / 400.0 + seekTimeSmoothly(smoothTime + delta) + + return false } } } else { @@ -471,7 +471,7 @@ struct SVideoPlayer: View, EditItemDelegate { } } - if dragged.height > 100 { + if dragged.height > 100 && jump { if timeCounter == 0 { if let i = model.allItems.index(where: { m in m === model.currentSnapshot }) { if i + 1 < model.allItems.count { @@ -489,19 +489,20 @@ struct SVideoPlayer: View, EditItemDelegate { if let time = getCurrentTime() { let dragWidth = 20.0 if !model.seeking { - if (start.y < 130 || slow) { - if model.scale > 1.0 && !slow { - return true - } + if model.scale > 1.0 && start.y > 200 { + return true + } + + if (model.slow) { if dragged.width > dragWidth { seekTime(time + 5.0) } else if dragged.width < -dragWidth { seekTime(time - 8.0) } } else { - if dragged.width > dragWidth { + if dragged.width > dragWidth * 2 { seekTime(time + 30.0) - } else if dragged.width < -dragWidth { + } else if dragged.width < -dragWidth * 2 { seekTime(time - 30.0) } }