Skip to content

Commit

Permalink
feat(Mobile): Better video download
Browse files Browse the repository at this point in the history
  • Loading branch information
macmade committed Dec 8, 2024
1 parent 750de4f commit f2be0d4
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 18 deletions.
14 changes: 13 additions & 1 deletion SDO-Mobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
052DCA792D060135003F7891 /* ImageInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052DCA782D060132003F7891 /* ImageInfoView.swift */; };
052DCA7B2D0603A7003F7891 /* ImageInfoDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 052DCA7A2D0603A5003F7891 /* ImageInfoDetailView.swift */; };
05957BDF2D060BD200E021AA /* VideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05957BDE2D060BCF00E021AA /* VideoView.swift */; };
05957BE42D06281200E021AA /* VideoDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05957BE32D06280E00E021AA /* VideoDownload.swift */; };
05CE14112D05D30300C757FD /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 05CE140B2D05D30300C757FD /* Preview Assets.xcassets */; };
05CE14122D05D30300C757FD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 05CE140D2D05D30300C757FD /* Assets.xcassets */; };
05CE14132D05D30300C757FD /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05CE140E2D05D30300C757FD /* ContentView.swift */; };
Expand All @@ -31,6 +32,7 @@
052DCA782D060132003F7891 /* ImageInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageInfoView.swift; sourceTree = "<group>"; };
052DCA7A2D0603A5003F7891 /* ImageInfoDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageInfoDetailView.swift; sourceTree = "<group>"; };
05957BDE2D060BCF00E021AA /* VideoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoView.swift; sourceTree = "<group>"; };
05957BE32D06280E00E021AA /* VideoDownload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDownload.swift; sourceTree = "<group>"; };
05CE13FA2D05D2BC00C757FD /* SDO.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SDO.app; sourceTree = BUILT_PRODUCTS_DIR; };
05CE140B2D05D30300C757FD /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
05CE140D2D05D30300C757FD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -107,6 +109,15 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
05957BE02D0627F900E021AA /* Utility */ = {
isa = PBXGroup;
children = (
05CE147E2D05E65B00C757FD /* PreviewData.swift */,
05957BE32D06280E00E021AA /* VideoDownload.swift */,
);
path = Utility;
sourceTree = "<group>";
};
05CE13F12D05D2BC00C757FD = {
isa = PBXGroup;
children = (
Expand All @@ -128,7 +139,6 @@
05CE140C2D05D30300C757FD /* Preview Content */ = {
isa = PBXGroup;
children = (
05CE147E2D05E65B00C757FD /* PreviewData.swift */,
05CE140B2D05D30300C757FD /* Preview Assets.xcassets */,
);
path = "Preview Content";
Expand All @@ -137,6 +147,7 @@
05CE14102D05D30300C757FD /* SDO-Mobile */ = {
isa = PBXGroup;
children = (
05957BE02D0627F900E021AA /* Utility */,
05CE144F2D05D51D00C757FD /* Views */,
05CE140D2D05D30300C757FD /* Assets.xcassets */,
05CE144D2D05D51900C757FD /* Info.plist */,
Expand Down Expand Up @@ -406,6 +417,7 @@
052DCA7B2D0603A7003F7891 /* ImageInfoDetailView.swift in Sources */,
05CE14132D05D30300C757FD /* ContentView.swift in Sources */,
05CE14142D05D30300C757FD /* SDOApp.swift in Sources */,
05957BE42D06281200E021AA /* VideoDownload.swift in Sources */,
05CE14782D05E14300C757FD /* ImageView.swift in Sources */,
05957BDF2D060BD200E021AA /* VideoView.swift in Sources */,
05CE14762D05DE6F00C757FD /* ImageData.swift in Sources */,
Expand Down
File renamed without changes.
113 changes: 113 additions & 0 deletions SDO-Mobile/Utility/VideoDownload.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2023, Jean-David Gadina - www.xs-labs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the Software), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/

import Foundation

public class VideoDownload
{
public var url: URL?

private let remoteURL: URL
private var completion: ( ( VideoDownload ) -> Void )?

private static var downloads: [ VideoDownload ] = []

public init( remoteURL: URL, completion: @escaping ( VideoDownload ) -> Void )
{
self.remoteURL = remoteURL
self.completion = completion

let session = URLSession( configuration: .ephemeral )
let request = URLRequest( url: remoteURL )
let task = session.downloadTask( with: request )
{
location, response, error in

guard let location = location,
let response = response as? HTTPURLResponse,
response.statusCode == 200
else
{
self.complete()

return
}

let copy = URL( fileURLWithPath: NSTemporaryDirectory() ).appendingPathComponent( NSUUID().uuidString ).appendingPathExtension( "mp4" )

do
{
try FileManager.default.copyItem( at: location, to: copy )
}
catch
{
self.complete()

return
}

DispatchQueue.main.async
{
self.url = copy

self.complete()
}
}

task.resume()
}

private func complete()
{
DispatchQueue.main.async
{
self.completion?( self )
VideoDownload.downloads.removeAll( where: { $0 === self } )

self.completion = nil
}
}

deinit
{
if let url = self.url
{
try? FileManager.default.removeItem( at: url )
}
}

public class func download( video: String, completion: @escaping ( VideoDownload ) -> Void )
{
guard let url = URL( string: "https://sdo.gsfc.nasa.gov/assets/img/latest/mpeg/\( video )" )
else
{
return
}

DispatchQueue.main.async
{
VideoDownload.downloads.append( VideoDownload( remoteURL: url, completion: completion ) )
}
}
}
2 changes: 1 addition & 1 deletion SDO-Mobile/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct ContentView: View
{
if self.images.isEmpty
{
LoadingView()
LoadingView( text: "Loading Latest Images from SDO\nPlease Wait" )
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion SDO-Mobile/Views/ImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ struct ImageView: View
}
.popover( isPresented: $isShowingVideoPopover, arrowEdge: .bottom )
{
VideoView( video: video ).padding()
VideoView( video: video )
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions SDO-Mobile/Views/LoadingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ import SwiftUI

struct LoadingView: View
{
public var text: String

var body: some View
{
VStack
{
ProgressView().scaleEffect( 1.5 ).padding()
Text( "Loading Latest Images from SDO\nPlease Wait" ).foregroundStyle( .secondary ).multilineTextAlignment( .center )
Text( self.text ).foregroundStyle( .secondary ).multilineTextAlignment( .center )
}
}
}

#Preview
{
LoadingView()
LoadingView( text: "Loading..." ).padding()
}
33 changes: 20 additions & 13 deletions SDO-Mobile/Views/VideoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,35 @@ import SwiftUI

struct VideoView: View
{
@State public var video: String
@State public var video: String
@State public var download: VideoDownload?

var body: some View
{
if let player = self.player
ZStack
{
VideoPlayer( player: player )
if let url = self.download?.url
{
VideoPlayer( player: self.player( url: url ) )
}
else
{
LoadingView( text: "Loading Video - Please Wait" )
}
}
else
.frame( maxWidth: .infinity, maxHeight: .infinity )
.background( .black )
.onAppear
{
Label( "Invalid video URL", systemImage: "video.slash.fill" )
VideoDownload.download( video: self.video )
{
self.download = $0
}
}
}

private var player: AVPlayer?
private func player( url: URL ) -> AVPlayer?
{
guard let url = URL( string: "https://sdo.gsfc.nasa.gov/assets/img/latest/mpeg/\( self.video )" )
else
{
return nil
}

let player = AVPlayer( url: url )

player.play()
Expand All @@ -59,5 +66,5 @@ struct VideoView: View

#Preview
{
VideoView( video: PreviewData.images.first!.video! ).padding()
VideoView( video: PreviewData.images.first!.video! )
}

0 comments on commit f2be0d4

Please sign in to comment.