Browse Source

dirty

master
schmicma 4 years ago
parent
commit
30e1726ed5
  1. 10
      kplayer.xcodeproj/project.pbxproj
  2. 1
      kplayer/video/SVideoModel.swift
  3. 110
      kplayer/video/SVideoPlayer.swift
  4. 7
      kplayer/video/VideoPlayerView.swift

10
kplayer.xcodeproj/project.pbxproj

@ -16,7 +16,6 @@
1C73633C00C18FDA2E9F0A2F /* KNetworkProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736DCD945ABAE984FF43EF /* KNetworkProtocol.swift */; };
1C73635138BBD2BB480A308F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C736777456388CA571DA17B /* MediaPlayer.framework */; };
1C7363C2E744C2318879127D /* FlexibleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736D50A22FC4553165199D /* FlexibleView.swift */; };
1C7363D4C34EBBD5C7AAD0A8 /* scratch.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1C7363E0DDA5854D55F8836E /* scratch.txt */; };
1C73640D928DE56D35175D39 /* UploadOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C736260E748CF136FF37EA7 /* UploadOperation.swift */; };
1C73646F87B495A47D7943C7 /* NetData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7369EC16B19B32B515169E /* NetData.swift */; };
1C736503B656C999E5E12081 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7365B06FA66294E99AC2D3 /* NetworkManager.swift */; };
@ -48,6 +47,7 @@
1C736A7B6221A1D50FB3904C /* ItemType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73631C96E6C860833052CA /* ItemType.swift */; };
1C736B4B0889BD35DC566124 /* nspersistentcontainer-defaults-swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7361F01841F546FA7AFD58 /* nspersistentcontainer-defaults-swift.swift */; };
1C736C8DAD6C2FBB9A2EA625 /* SearchItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C73654AB95A2D629833BEC5 /* SearchItemView.swift */; };
1C736C9821DA743C2E3F3B07 /* kplayer.txt in Resources */ = {isa = PBXBuildFile; fileRef = 1C7360F9649E40B7C2EAB581 /* kplayer.txt */; };
1C736D16E81BA1FB325200E0 /* HanekeFetchOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7360744ABACC3557D05760 /* HanekeFetchOperation.swift */; };
1C736D24891597F2728230EE /* ImageLoadOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7360A94DBECA685ED8602F /* ImageLoadOperation.swift */; };
1C736D24B49451141CD4B64D /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7369F53095B7A4D65679C2 /* DetailViewController.swift */; };
@ -94,6 +94,7 @@
1C7360744ABACC3557D05760 /* HanekeFetchOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HanekeFetchOperation.swift; sourceTree = "<group>"; };
1C7360A94DBECA685ED8602F /* ImageLoadOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageLoadOperation.swift; sourceTree = "<group>"; };
1C7360B6D0757D4FB6433E7B /* AsyncImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncImage.swift; sourceTree = "<group>"; };
1C7360F9649E40B7C2EAB581 /* kplayer.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = kplayer.txt; sourceTree = "<group>"; };
1C73611D226B48C24DB37535 /* MasterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterViewController.swift; sourceTree = "<group>"; };
1C73615FFA2AA98BD1C56CD4 /* links.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = links.html; sourceTree = "<group>"; };
1C7361F01841F546FA7AFD58 /* nspersistentcontainer-defaults-swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "nspersistentcontainer-defaults-swift.swift"; sourceTree = "<group>"; };
@ -104,7 +105,6 @@
1C736260E748CF136FF37EA7 /* UploadOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UploadOperation.swift; sourceTree = "<group>"; };
1C7362DE1D6BE634D7C2ACBF /* KPersistentContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KPersistentContainer.swift; sourceTree = "<group>"; };
1C73631C96E6C860833052CA /* ItemType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemType.swift; sourceTree = "<group>"; };
1C7363E0DDA5854D55F8836E /* scratch.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = scratch.txt; sourceTree = "<group>"; };
1C73645DBD6499A726D34973 /* links.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = links.html; sourceTree = "<group>"; };
1C73647019E6C2E822127BA3 /* DatabaseManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
1C7364709899FF62774B0199 /* VideoHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoHelper.swift; sourceTree = "<group>"; };
@ -133,7 +133,6 @@
1C736B794396F2E50387B8F2 /* stringutil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = stringutil.swift; sourceTree = "<group>"; };
1C736BC4450890C45F8FBC63 /* LayoutTools.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayoutTools.swift; sourceTree = "<group>"; };
1C736C94157754DE1C808173 /* KSettingsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KSettingsModel.swift; sourceTree = "<group>"; };
1C736CF935C2A6AB916BE494 /* scratch.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = scratch.txt; sourceTree = "<group>"; };
1C736D50A22FC4553165199D /* FlexibleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlexibleView.swift; sourceTree = "<group>"; };
1C736D9BB5498E7E8F11C754 /* HeaderCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderCell.swift; sourceTree = "<group>"; };
1C736DBB6986A8B62963FBB3 /* HtmlParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlParser.swift; sourceTree = "<group>"; };
@ -202,7 +201,6 @@
1C73625012D50E457D18A785 /* kplayer.js */,
1C73615FFA2AA98BD1C56CD4 /* links.html */,
1C73645DBD6499A726D34973 /* links.html */,
1C736CF935C2A6AB916BE494 /* scratch.txt */,
);
path = server;
sourceTree = "<group>";
@ -316,8 +314,8 @@
1C736059262A57AADE6AB761 /* Kirschkeks-256x256.png */,
8052F5B3AAC2535E5C08A529 /* Pods */,
1C73685B4BBFDAFBF08C032C /* readme.md */,
1C7363E0DDA5854D55F8836E /* scratch.txt */,
1C7369BED02028D8564E82D5 /* pathfinder.scpt */,
1C7360F9649E40B7C2EAB581 /* kplayer.txt */,
);
sourceTree = "<group>";
};
@ -470,7 +468,7 @@
1C736A5FA5BA53B2597F2ED7 /* Kirschkeks-256x256.png in Resources */,
1C73696E4C0353053BF98031 /* links.html in Resources */,
1C736FAE5D3E5D3BA3C1FAE5 /* links.html in Resources */,
1C7363D4C34EBBD5C7AAD0A8 /* scratch.txt in Resources */,
1C736C9821DA743C2E3F3B07 /* kplayer.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

1
kplayer/video/SVideoModel.swift

@ -22,6 +22,7 @@ class SVideoModel : ObservableObject {
@Published var paused = false
@Published var edit = false
@Published var dirty = false
@Published var loop = false
@Published var zoomed = false
@Published var favorite = false

110
kplayer/video/SVideoPlayer.swift

@ -23,6 +23,7 @@ struct SVideoPlayer: View, EditItemDelegate {
@State var savetext = "save"
@State var confirmationShown = false
@State var dirtyShown = false
@State var seekSmoothly = false
@State var upsidedown = false
@State var more = false
@ -30,6 +31,7 @@ struct SVideoPlayer: View, EditItemDelegate {
@State var smoothTime = -1.0
@State var smoothSeekTime = -1.0
@State var timeCounter = 0
@State var timeSlomoCounter = 0
@State var lastScale = 1.25
@State var xoffs = 0.0
@State var rotazero = -1000.0
@ -60,21 +62,29 @@ struct SVideoPlayer: View, EditItemDelegate {
HStack {
Group {
Button(action: {
model.baseItem.favorite = model.favorite
player.pause()
player.replaceCurrentItem(with: nil)
model.currentURL = nil
cleanup()
completionHandler!(model.edit)
if model.dirty {
dirtyShown = true
} else {
let withSave = model.edit
closePlayer(withSave: withSave)
}
}, label: {
Text("cancel")
})
.buttonStyle(BorderlessButtonStyle())
.buttonStyle(BorderlessButtonStyle()).confirmationDialog("Save?", isPresented: $dirtyShown) {
Button("save") {
closePlayer(withSave: true)
}
Button("cancel", role: .cancel) {
closePlayer(withSave: false)
}
}
KToggleButton(text: "more", binding: $more)
Button(action: {
model.favorite.toggle()
model.dirty = true
}, label: {
Image(systemName: "heart.fill")
})
@ -139,16 +149,6 @@ struct SVideoPlayer: View, EditItemDelegate {
.scaleEffect(model.scale)
.rotation3DEffect(.degrees(upsidedown ? 180 : 0), axis: (x: 1, y: 0, z: 0))
.offset(model.dragOffset).offset(x: xoffs, y: 0)
// .onTapGesture(count: 2) {
// print("Double tapped!")
// if model.paused {
// player.play()
// }
// else {
// player.pause()
// }
// model.paused = !model.paused
// }
.onTapGesture(count: 2) {
print("3 tapped!")
if model.scale == 1 {
@ -159,7 +159,6 @@ struct SVideoPlayer: View, EditItemDelegate {
model.dragOffset = CGSize.zero
}
}
.gesture(
DragGesture()
.onChanged { gesture in
@ -179,7 +178,6 @@ struct SVideoPlayer: View, EditItemDelegate {
let delta = val / self.lastScaleValue
self.lastScaleValue = val
self.model.scale = self.model.scale * delta
//... anything else e.g. clamping the newScale
}
.onEnded { val in
// without this the next gesture will be broken
@ -212,6 +210,10 @@ struct SVideoPlayer: View, EditItemDelegate {
KToggleButton(text: "flip", binding: $upsidedown).frame(height: 30)
Button(action: {
if model.speed == 1.0 && timeSlomoCounter == 0 {
model.speed = 0.5
timeSlomoCounter = 200
} else {
for s in steps {
if model.speed < s {
model.speed = s
@ -222,7 +224,9 @@ struct SVideoPlayer: View, EditItemDelegate {
}
}
}
}
player.rate = model.speed
}, label: {
Text("\(model.speed, specifier: "%.2f")")
})
@ -231,8 +235,7 @@ struct SVideoPlayer: View, EditItemDelegate {
Button(action: {
if model.paused {
player.play()
}
else {
} else {
player.pause()
}
model.paused = !model.paused
@ -242,6 +245,35 @@ struct SVideoPlayer: View, EditItemDelegate {
.frame(height: 30)
.foregroundColor(model.paused ? Color.yellow : Color.blue).buttonStyle(BorderlessButtonStyle())
Button(action: {}) {
Text("start")
}
.frame(height: 30).buttonStyle(BorderlessButtonStyle())
.simultaneousGesture(
LongPressGesture()
.onEnded { _ in
print("Loooong")
}
)
.highPriorityGesture(TapGesture()
.onEnded { _ in
seekTimeSmoothly(model.currentSnapshot.time)
})
Button(action: {}) {
Text("end")
}
.frame(height: 30).buttonStyle(BorderlessButtonStyle()).foregroundColor(model.currentSnapshot.length > 0 ? Color.yellow : Color.blue)
.simultaneousGesture(
LongPressGesture()
.onEnded { _ in
setEnd()
}
)
.highPriorityGesture(TapGesture()
.onEnded { _ in
seekTimeSmoothly(model.currentSnapshot.time + model.currentSnapshot.length)
})
}
.frame(width: 50, alignment: .top).offset(x: 0, y: 0), alignment: .topLeading)
} else {
@ -270,6 +302,9 @@ struct SVideoPlayer: View, EditItemDelegate {
if timeCounter >= 1 {
timeCounter -= 1
}
if timeSlomoCounter >= 1 {
timeSlomoCounter -= 1
}
if model.loop && model.currentSnapshot.length > 0 {
if time.seconds > model.currentSnapshot.time + model.currentSnapshot.length {
seekTime(model.currentSnapshot.time)
@ -339,6 +374,15 @@ struct SVideoPlayer: View, EditItemDelegate {
}
private func closePlayer(withSave: Bool) {
model.baseItem.favorite = model.favorite
player.pause()
player.replaceCurrentItem(with: nil)
model.currentURL = nil
cleanup()
completionHandler!(withSave)
}
func doSnapshot() {
let currentItem = player.currentItem!
let asset = currentItem.asset
@ -349,6 +393,7 @@ struct SVideoPlayer: View, EditItemDelegate {
let time = currentItem.currentTime()
let cgImage = try imgGenerator.copyCGImage(at: time, actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
model.dirty = true
showThumbnail(currentItem: model.baseItem, thumbnail: thumbnail, time: time)
@ -378,7 +423,7 @@ struct SVideoPlayer: View, EditItemDelegate {
} else {
gotoSnapshot(model.allItems[0])
}
timeCounter = 15
timeCounter = 50
print("jump")
}
}
@ -392,24 +437,30 @@ struct SVideoPlayer: View, EditItemDelegate {
}
if (start.y < 130) {
let delta = dragged.width / 1000.0
let delta = dragged.width / 500.0
// print(delta)
seekTimeSmoothly(smoothTime + delta)
return false
} else {
if model.scale != 1.0 {
return true
}
else {
let dragWidth = 20.0
if dragged.width > dragWidth {
seekTime(time + 4.0)
} else if dragged.width < -dragWidth {
seekTime(time - 5.0)
}
}
}
} else {
return true
}
}
if let time = getCurrentTime() {
// let sk = model.seeking
// model.seeking = false
// print("Start \(start.y) Drag \(dragged.width)))")
let dragWidth = 20.0
if !model.seeking {
if (start.y < 130) {
@ -459,8 +510,10 @@ struct SVideoPlayer: View, EditItemDelegate {
// player.seek(to: CMTime(seconds: time, preferredTimescale: CMTimeScale(10000)),
// toleranceBefore: CMTime(seconds: 0.3, preferredTimescale: CMTimeScale(10000)),
// toleranceAfter: CMTime(seconds: 1.0, preferredTimescale: CMTimeScale(10000))){ _ in
if !model.paused {
player.play()
player.rate = model.speed
}
self.model.seeking = false
}
@ -527,11 +580,13 @@ struct SVideoPlayer: View, EditItemDelegate {
func captureZoom() {
model.currentSnapshot.scale = model.scale
model.currentSnapshot.offset = CGPoint(x: model.dragOffset.width, y: model.dragOffset.height)
model.dirty = true
}
func setStart() {
if let time = getCurrentTime() {
model.currentSnapshot.time = time
model.dirty = true
}
}
@ -541,6 +596,7 @@ struct SVideoPlayer: View, EditItemDelegate {
if time > snapTime {
model.currentSnapshot.length = time - snapTime
}
model.dirty = true
}
}

7
kplayer/video/VideoPlayerView.swift

@ -136,7 +136,12 @@ struct VideoPlayerControlsView : View {
.padding(.trailing, 30)
}
// Current video time
Text("\(Utility.formatSecondsToHMS(model.videoPos * model.videoDuration))").foregroundColor(Color.white)
let postime = model.videoPos * model.videoDuration
let postext = Utility.formatSecondsToHMS(postime)
let tens = postime.isNaN ? 0 : Int((postime*10.0).truncatingRemainder(dividingBy: 10))
Text("\(postext):\(tens)").foregroundColor(Color.white)
// Slider for seeking / showing video progress
Slider(value: $model.videoPos, in: 0...1, onEditingChanged: sliderEditingChanged)
// Video duration

Loading…
Cancel
Save