Skip to content

Commit

Permalink
added option to play in IINA
Browse files Browse the repository at this point in the history
  • Loading branch information
Aayush9029 committed Oct 28, 2021
1 parent 8dbbd22 commit 549ff9c
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 150 deletions.
20 changes: 20 additions & 0 deletions NativeTwitch.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
C2A7BCF226462B030038CFB5 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2A7BCF126462B030038CFB5 /* ContentView.swift */; };
C2A7BCF426462B050038CFB5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C2A7BCF326462B050038CFB5 /* Assets.xcassets */; };
C2A7BCF726462B050038CFB5 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C2A7BCF626462B050038CFB5 /* Preview Assets.xcassets */; };
C2E360D7272A3F54005C6858 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E360D6272A3F54005C6858 /* Double+Extension.swift */; };
C2E360D9272A3F77005C6858 /* NSTextField+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E360D8272A3F77005C6858 /* NSTextField+Extension.swift */; };
C2E360DB272A3FBB005C6858 /* VisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E360DA272A3FBB005C6858 /* VisualEffectView.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -39,6 +42,9 @@
C2A7BCF926462B050038CFB5 /* NativeTwitch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NativeTwitch.entitlements; sourceTree = "<group>"; };
C2A7BD0226462B050038CFB5 /* NativeTwitchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeTwitchTests.swift; sourceTree = "<group>"; };
C2A7BD0426462B050038CFB5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C2E360D6272A3F54005C6858 /* Double+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+Extension.swift"; sourceTree = "<group>"; };
C2E360D8272A3F77005C6858 /* NSTextField+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTextField+Extension.swift"; sourceTree = "<group>"; };
C2E360DA272A3FBB005C6858 /* VisualEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualEffectView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -84,6 +90,7 @@
children = (
C2A7BCEF26462B030038CFB5 /* NativeTwitchApp.swift */,
C2A7BCF126462B030038CFB5 /* ContentView.swift */,
C2E360D5272A3F43005C6858 /* Extensions */,
C2A7BD1C26462B320038CFB5 /* View */,
C2948E1726E424F0001EABC0 /* View Model */,
C2A7BD1B26462B2C0038CFB5 /* Model */,
Expand Down Expand Up @@ -125,13 +132,23 @@
C2A7BD1C26462B320038CFB5 /* View */ = {
isa = PBXGroup;
children = (
C2E360DA272A3FBB005C6858 /* VisualEffectView.swift */,
C269947C2647251D00B3DCF7 /* SettingsView.swift */,
C26994802647255000B3DCF7 /* StreamRowView.swift */,
C271885626E273E2009C8002 /* LogText.swift */,
);
path = View;
sourceTree = "<group>";
};
C2E360D5272A3F43005C6858 /* Extensions */ = {
isa = PBXGroup;
children = (
C2E360D6272A3F54005C6858 /* Double+Extension.swift */,
C2E360D8272A3F77005C6858 /* NSTextField+Extension.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -213,9 +230,12 @@
C271885726E273E2009C8002 /* LogText.swift in Sources */,
C26FBE55264679F1006818AB /* TwitchDataViewModel.swift in Sources */,
C2A7BCF226462B030038CFB5 /* ContentView.swift in Sources */,
C2E360D7272A3F54005C6858 /* Double+Extension.swift in Sources */,
C2E360DB272A3FBB005C6858 /* VisualEffectView.swift in Sources */,
C2A7BCF026462B030038CFB5 /* NativeTwitchApp.swift in Sources */,
C269947D2647251D00B3DCF7 /* SettingsView.swift in Sources */,
C26994812647255000B3DCF7 /* StreamRowView.swift in Sources */,
C2E360D9272A3F77005C6858 /* NSTextField+Extension.swift in Sources */,
C2948E1926E424FC001EABC0 /* Stream.swift in Sources */,
C2948E1B26E4250A001EABC0 /* User.swift in Sources */,
);
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "blank-profile-picture-973460_960_720.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 7 additions & 42 deletions NativeTwitch/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ struct ContentView: View {
.font(.title)
.bold()
.foregroundColor(.gray.opacity(0.5))

}
if (twitchData.status == .streamLoaded && twitchData.getStreamData().count == 0) {
Text("All streams are offline :(")
Expand All @@ -45,31 +44,21 @@ struct ContentView: View {
VStack {
ScrollView(.vertical, showsIndicators: false){
ForEach(twitchData.getStreamData(), id: \.self) { stream in
StreamRowView(stream: stream, const: Constants(twitchClientID: twitchClientID, oauthToken: oauthToken, streamlinkLocation: streamlinkLocation), stream_logo: URL(string: "https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png")!)
StreamRowView(stream: stream, const: Constants(twitchClientID: twitchClientID, oauthToken: oauthToken, streamlinkLocation: streamlinkLocation))
.environmentObject(twitchData)
.onTapGesture(count: 2, perform: {
let shell_out = shell("ttvQT () { open -a \"quicktime player\" $(\(streamlinkLocation) twitch.tv/$@ best --stream-url) ;}; ttvQT \(stream.user_name)")
if shell_out.isEmpty{
twitchData.addToLogs(response: "\(streamlinkLocation):πŸŽ‰ Success πŸŽ‰")
}else{
twitchData.addToLogs(response: shell_out)
twitchData.addToLogs(response: "BIG FAIL 😩 @ \(streamlinkLocation)")
twitchData.addToLogs(response: shell("which streamlink"))
}
twitchData.watchStream(streamLinkLocation: streamlinkLocation, streamerUsername: stream.user_name)
})
.contextMenu(ContextMenu(menuItems: {
VStack {
Button("Play"){
let shell_out = shell("ttvQT () { open -a \"quicktime player\" $(\(streamlinkLocation) twitch.tv/$@ best --stream-url) ;}; ttvQT \(stream.user_name)")
if shell_out.isEmpty{
twitchData.addToLogs(response: "\(streamlinkLocation):πŸŽ‰ Success πŸŽ‰")
}else{
twitchData.addToLogs(response: shell_out)
twitchData.addToLogs(response: "BIG FAIL 😩 @ \(streamlinkLocation)")
twitchData.addToLogs(response: shell("which streamlink"))
twitchData.watchStream(streamLinkLocation: streamlinkLocation, streamerUsername: stream.user_name)
}
if !twitchData.iinaEnabled{
Button("Play using IINA"){
twitchData.watchStream(streamLinkLocation: streamlinkLocation, streamerUsername: stream.user_name, customIINAEnabled: true)
}
}

Divider()
Button("Open chat"){
NSWorkspace.shared.open(stream.getChatURL())
Expand All @@ -92,27 +81,3 @@ struct ContentView: View {
}


extension ContentView{
func shell(_ command: String) -> String {
let task = Process()
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.arguments = ["-c", command]
task.launchPath = "/bin/zsh"
task.launch()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!

return output
}

}

extension NSTextField{
open override var focusRingType: NSFocusRingType{
get{.none}
set{}
}
}
32 changes: 32 additions & 0 deletions NativeTwitch/Extensions/Double+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Double+Extension.swift
// NativeTwitch
//
// Created by Aayush Pokharel on 2021-10-27.
//

import Foundation

extension Double {
var shortStringRepresentation: String {
if self.isNaN {
return "NaN"
}
if self.isInfinite {
return "\(self < 0.0 ? "-" : "+")Infinity"
}
let units = ["", "k", "M"]
var interval = self
var i = 0
while i < units.count - 1 {
if abs(interval) < 1000.0 {
break
}
i += 1
interval /= 1000.0
}
// + 2 to have one digit after the comma, + 1 to not have any.
// Remove the * and the number of digits argument to display all the digits after the comma.
return "\(String(format: "%0.*g", Int(log10(abs(interval))) + 2, interval))\(units[i])"
}
}
15 changes: 15 additions & 0 deletions NativeTwitch/Extensions/NSTextField+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// NSTextField+Extension.swift
// NativeTwitch
//
// Created by Aayush Pokharel on 2021-10-27.
//

import SwiftUI

extension NSTextField{
open override var focusRingType: NSFocusRingType{
get{.none}
set{}
}
}
3 changes: 3 additions & 0 deletions NativeTwitch/Model/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@ enum AppStorageStrings: String{
case oauthToken = "oauthToken"
case streamlinkLocation = "streamlinkLocation"
case showingInfo = "showingInfo"
case iinaLocation = "IINA location (optional)"
case iinaEnabled = "Enable IINA"

}
31 changes: 5 additions & 26 deletions NativeTwitch/NativeTwitchApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ struct NativeTwitchApp: App {
WindowGroup {
ContentView()
.environmentObject(twitchData)
.frame(width: 300, height: 420)
.frame(width: 320, height: 420)
}
.windowStyle(HiddenTitleBarWindowStyle())
.windowStyle(.hiddenTitleBar)
.commands {
CommandMenu("Actions") {
VStack{
Expand All @@ -44,34 +44,13 @@ struct NativeTwitchApp: App {
}
}
Settings {
SettingsView(showingLogs: $showingLogs).background(VisualEffectView(material: NSVisualEffectView.Material.sidebar, blendingMode: NSVisualEffectView.BlendingMode.behindWindow))
SettingsView(showingLogs: $showingLogs)
.environmentObject(twitchData)
.frame(width: 300, height: showingLogs ? 500: 270)
.background(VisualEffectView(material: NSVisualEffectView.Material.sidebar, blendingMode: NSVisualEffectView.BlendingMode.behindWindow))
.frame(width: 320, height: showingLogs ? 650: 400)
.fixedSize()
}

}
}



struct VisualEffectView: NSViewRepresentable
{
let material: NSVisualEffectView.Material
let blendingMode: NSVisualEffectView.BlendingMode

func makeNSView(context: Context) -> NSVisualEffectView
{
let visualEffectView = NSVisualEffectView()
visualEffectView.material = material
visualEffectView.blendingMode = blendingMode
visualEffectView.state = NSVisualEffectView.State.active
return visualEffectView
}

func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context)
{
visualEffectView.material = material
visualEffectView.blendingMode = blendingMode
}
}
58 changes: 57 additions & 1 deletion NativeTwitch/View Model/TwitchDataViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class TwitchDataViewModel: ObservableObject{
@AppStorage(AppStorageStrings.clientID.rawValue) var twitchClientID = ""
@AppStorage(AppStorageStrings.oauthToken.rawValue) var oauthToken = ""
@AppStorage(AppStorageStrings.streamlinkLocation.rawValue) var streamlinkLocation = ""

@AppStorage(AppStorageStrings.iinaEnabled.rawValue) var iinaEnabled = false

@Published var status: StatusStates

var user: User
Expand Down Expand Up @@ -155,4 +156,59 @@ class TwitchDataViewModel: ObservableObject{
return self.streams
}

func watchStream(streamLinkLocation: String, streamerUsername: String, customIINAEnabled: Bool = false){
if (iinaEnabled || customIINAEnabled){

// There is no output to validate (if it worked with quicktime and you have IINA installed it should work with IINA.
let _ = shell("ttvQT () { open -a iina $(\(streamlinkLocation) twitch.tv/$@ best --stream-url) ;}; ttvQT \(streamerUsername)")
addToLogs(response: "\(streamLinkLocation):πŸŽ‰ Success πŸŽ‰")
return
}else{
let shell_out = shell("ttvQT () { open -a \"quicktime player\" $(\(streamlinkLocation) twitch.tv/$@ best --stream-url) ;}; ttvQT \(streamerUsername)")
if shell_out.isEmpty{ addToLogs(response: "\(streamLinkLocation):πŸŽ‰ Success πŸŽ‰"); return } else{
addToLogs(response: shell_out); addToLogs(response: "BIG FAIL 😩 @ \(streamLinkLocation)")
}
}
addToLogs(response: shell("which streamlink"))
}


func copyLogsToClipboard(redacted: Bool = true){
var logsText = ""
for log in logs {
logsText += log
logsText += "\n"
}
if redacted {
logsText = logsText.replacingOccurrences(of: user.client_id, with: "********CLIENTID*****")
logsText = logsText.replacingOccurrences(of: user.oauthToken, with: "********OAUTHTOKEN*****")
logsText = logsText.replacingOccurrences(of: user.name, with: "*******USERNAME********")
logsText = logsText.replacingOccurrences(of: user.user_id, with: "*******USER_ID********")
}

let pasteBoard = NSPasteboard.general
pasteBoard.clearContents()
pasteBoard.setString(logsText, forType: .string)

}
}


extension TwitchDataViewModel{
private func copyToClipBoard(textToCopy: String) {
}
func shell(_ command: String) -> String {
let task = Process()
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.arguments = ["-c", command]
task.launchPath = "/bin/zsh"
task.launch()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!

return output
}
}
Loading

0 comments on commit 549ff9c

Please sign in to comment.