Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.1.1 (3) #12

Open
wants to merge 16 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: bd3025cc71699ad0300e7ce21de6683a7ce4a10a

COCOAPODS: 1.10.1
COCOAPODS: 1.11.2
22 changes: 14 additions & 8 deletions ios.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
365045EF26D5B03900AD6214 /* MchadTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 365045EE26D5B03900AD6214 /* MchadTypes.swift */; };
36C224DB26D197CD00982BB1 /* FilterViewSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C224DA26D197CD00982BB1 /* FilterViewSwiftUI.swift */; };
36CB58DE26C57F5F0002B8AF /* Superchat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36CB58DD26C57F5F0002B8AF /* Superchat.swift */; };
36DA10A02755C2600093E393 /* LtlAPIServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36DA109F2755C2600093E393 /* LtlAPIServices.swift */; };
36DA10A12755C2600093E393 /* LtlAPIServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36DA109F2755C2600093E393 /* LtlAPIServices.swift */; };
36E6C1FA26A71DF600C2B08C /* HoloDexResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36EF35F026A64C370005E6FC /* HoloDexResponse.swift */; };
36E6C1FB26A71DF600C2B08C /* TranslatedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36EF35F226A64C370005E6FC /* TranslatedMessage.swift */; };
36E6C1FC26A71DF600C2B08C /* YouTubeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36EF35FE26A64C370005E6FC /* YouTubeService.swift */; };
Expand Down Expand Up @@ -125,6 +127,7 @@
3652A47E26C20E7C003DA76B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizeable.strings; sourceTree = "<group>"; };
36C224DA26D197CD00982BB1 /* FilterViewSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewSwiftUI.swift; sourceTree = "<group>"; };
36CB58DD26C57F5F0002B8AF /* Superchat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Superchat.swift; sourceTree = "<group>"; };
36DA109F2755C2600093E393 /* LtlAPIServices.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LtlAPIServices.swift; sourceTree = "<group>"; };
36EF35EC26A64C370005E6FC /* Language.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Language.swift; sourceTree = "<group>"; };
36EF35ED26A64C370005E6FC /* Organizations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Organizations.swift; sourceTree = "<group>"; };
36EF35EE26A64C370005E6FC /* InjectedMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InjectedMessage.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -282,6 +285,7 @@
36EF35FC26A64C370005E6FC /* Services */ = {
isa = PBXGroup;
children = (
36DA109F2755C2600093E393 /* LtlAPIServices.swift */,
36EF35FD26A64C370005E6FC /* HoloDexServices.swift */,
36EF35FE26A64C370005E6FC /* YouTubeService.swift */,
36EF35FF26A64C370005E6FC /* AppServices.swift */,
Expand Down Expand Up @@ -693,6 +697,7 @@
36E6C1FB26A71DF600C2B08C /* TranslatedMessage.swift in Sources */,
3600776326A73653004CB44B /* StreamView.swift in Sources */,
36E6C1FF26A71DF600C2B08C /* AppStep.swift in Sources */,
36DA10A12755C2600093E393 /* LtlAPIServices.swift in Sources */,
36E6C1FE26A71DF600C2B08C /* DisplayableMessage.swift in Sources */,
36E6C1FC26A71DF600C2B08C /* YouTubeService.swift in Sources */,
36FD3ED326978CC200EAAF51 /* ChatCell.swift in Sources */,
Expand Down Expand Up @@ -739,6 +744,7 @@
36EF361026A64C370005E6FC /* AppServices.swift in Sources */,
6636808B261983B500125A76 /* ChatCell.swift in Sources */,
36EF360526A64C370005E6FC /* HoloDexResponse.swift in Sources */,
36DA10A02755C2600093E393 /* LtlAPIServices.swift in Sources */,
665774AE260C6ECE00072F30 /* HomeView.swift in Sources */,
36EF360926A64C370005E6FC /* BaseView.swift in Sources */,
36EF360F26A64C370005E6FC /* YouTubeService.swift in Sources */,
Expand Down Expand Up @@ -842,7 +848,7 @@
CODE_SIGN_ENTITLEMENTS = "yt-extension/yt-extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 6S4L29QT59;
DEVELOPMENT_TEAM = RJNC97Y8QD;
INFOPLIST_FILE = "yt-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -851,7 +857,7 @@
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = "app.livetl.ios.yt-extension";
PRODUCT_BUNDLE_IDENTIFIER = "app.livetl-dev.ios.yt-extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
Expand All @@ -866,7 +872,7 @@
CODE_SIGN_ENTITLEMENTS = "yt-extension/yt-extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 6S4L29QT59;
DEVELOPMENT_TEAM = RJNC97Y8QD;
INFOPLIST_FILE = "yt-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -875,7 +881,7 @@
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = "app.livetl.ios.yt-extension";
PRODUCT_BUNDLE_IDENTIFIER = "app.livetl-dev.ios.yt-extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
Expand Down Expand Up @@ -1012,15 +1018,15 @@
CODE_SIGN_ENTITLEMENTS = ios/ios.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 6S4L29QT59;
DEVELOPMENT_TEAM = RJNC97Y8QD;
INFOPLIST_FILE = ios/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = app.livetl.ios;
PRODUCT_BUNDLE_IDENTIFIER = "app.livetl-dev.ios";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand All @@ -1040,15 +1046,15 @@
CODE_SIGN_ENTITLEMENTS = ios/ios.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 6S4L29QT59;
DEVELOPMENT_TEAM = RJNC97Y8QD;
INFOPLIST_FILE = ios/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = app.livetl.ios;
PRODUCT_BUNDLE_IDENTIFIER = "app.livetl-dev.ios";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_VERSION = 5.0;
Expand Down
35 changes: 29 additions & 6 deletions ios/Core/Models/HomeModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,46 @@ protocol HomeModelOutput {
class HomeModel: BaseModel {
let refresh = BehaviorRelay<Void>(value: ())

private let streamers = BehaviorRelay<HoloDexResponse?>(value: nil)
private var streamers = BehaviorRelay<HoloDexResponse?>(value: nil)
private let liveStreamers = BehaviorRelay<HoloDexResponse?>(value: nil)
private let upStreamers = BehaviorRelay<HoloDexResponse?>(value: nil)
private let pastStreamers = BehaviorRelay<HoloDexResponse?>(value: nil)
private let refreshState = BehaviorRelay<Bool>(value: false)

override init(_ services: AppServices) {
super.init(services)

refresh.subscribe(onNext: { _ in self.loadStreamers(services.settings.orgFilter) }).disposed(by: bag)
streamers.compactMap { $0 }.distinctUntilChanged()
liveStreamers.compactMap { $0 }//.distinctUntilChanged()
.map { _ in false }
.bind(to: refreshState)
.disposed(by: bag)
}

func loadStreamers(_ org: Organization) {
refreshState.accept(true)
services.holodex.streamers(org.description)
services.holodex.streamers(org.description, status: "live")
.asObservable()
.bind(to: liveStreamers)
.disposed(by: bag)
services.holodex.streamers(org.description, status: "upcoming")
.asObservable()
.bind(to: upStreamers)
.disposed(by: bag)
services.holodex.streamers(org.description, status: "past")
.asObservable()
.bind(to: pastStreamers)
.disposed(by: bag)

Observable.combineLatest(liveStreamers, upStreamers, pastStreamers)
.asObservable()
.map({ live, upcoming, past -> HoloDexResponse in
var combined: [HoloDexResponse.Streamer] = []
combined.append(contentsOf: live?.items ?? [])
combined.append(contentsOf: upcoming?.items ?? [])
combined.append(contentsOf: past?.items ?? [])
return HoloDexResponse(items: combined)
})
.bind(to: streamers)
.disposed(by: bag)
}
Expand Down Expand Up @@ -88,7 +111,7 @@ extension HomeModel: HomeModelOutput {

func video(for section: Int, and index: Int) -> String {
let r = streamers.value!.sections()
//return "x1EZYh8aGwA"
//return "sVCp2PhQBaE"
return r[section].items[index].id
}
func thumbnail(for section: Int, and index: Int) -> URL? {
Expand Down Expand Up @@ -123,14 +146,14 @@ extension HoloDexResponse {

let l = items.filter { $0.status == .live }.sorted { $0.start_scheduled > $1.start_scheduled }
let u = items.filter { $0.status == .upcoming }.sorted { $0.start_scheduled < $1.start_scheduled }
let e = items.filter { $0.status == .past }.sorted { $0.start_scheduled > $1.start_scheduled }
let e = items.filter { $0.status == .past && $0.start_scheduled <= Date() }.sorted { $0.start_scheduled > $1.start_scheduled }

var rtr: [StreamerItemModel] = []

if !l.isEmpty { rtr.append(StreamerItemModel(title: Bundle.main.localizedString(forKey: "Live", value: "Live", table: "Localizeable"), items: l)) }
if !u.isEmpty { rtr.append(StreamerItemModel(title: Bundle.main.localizedString(forKey: "Upcoming", value: "Upcoming", table: "Localizeable"), items: u)) }
if !e.isEmpty { rtr.append(StreamerItemModel(title: Bundle.main.localizedString(forKey: "Ended", value: "Ended", table: "Localizeable"), items: e))}
rtr.append(StreamerItemModel(title: Bundle.main.localizedString(forKey: "Stream data provided by Holodex. Results capped at 50.", value: "Stream data provided by Holodex. Results capped at 50.", table: "Localizeable"), items: []))
rtr.append(StreamerItemModel(title: Bundle.main.localizedString(forKey: "Stream data provided by Holodex.", value: "Stream data provided by Holodex.", table: "Localizeable"), items: []))

return rtr
}
Expand Down
103 changes: 79 additions & 24 deletions ios/Core/Models/StreamModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class StreamModel: BaseModel {

private let chatURLRelay = BehaviorRelay<URL?>(value: nil)
private let mchadRoomRelay = BehaviorRelay<MchadRoom?>(value: nil)
private let mchadScriptRelay = BehaviorRelay<[MchadScript?]>(value: [])
private let mchadScriptRelay = BehaviorRelay<([TranslatedMessage], MchadRoom?)?>(value: ([], nil))
private let metadataRelay = BehaviorRelay<HoloDexResponse?>(value: nil)

private let replayRelay = BehaviorRelay<Bool>(value: false)
Expand Down Expand Up @@ -98,12 +98,17 @@ class StreamModel: BaseModel {
.map { $0.sorted { $0.sortTimestamp > $1.sortTimestamp } }
.bind(to: chatRelay)
.disposed(by: bag)

playerRelay.compactMap { $0 }
.map { (id: $0.identifier, duration: $0.duration) }
.subscribe(onNext: loadChat)
.disposed(by: bag)

playerRelay.compactMap { $0 }
.map { (id: $0.identifier, duration: $0.duration) }
.subscribe(onNext: loadMchadRooms)
.disposed(by: bag)

chatView.navigationDelegate = self
chatURLRelay.compactMap { $0 }
.map { URLRequest(url: $0) }
Expand All @@ -113,6 +118,15 @@ class StreamModel: BaseModel {
.map { $0.absoluteString.contains("live_chat_replay") }
.bind(to: replayRelay)
.disposed(by: bag)
mchadRoomRelay.compactMap { $0 }
.subscribe(onNext: { room in self.loadMchadArchiveScript(room) })
.disposed(by: bag)
mchadScriptRelay.compactMap { $0 }
.subscribe(onNext: { script, room in
self.appendMchadScriptTls(script, room: room)
})
.disposed(by: bag)

do {
let path = Bundle.main.path(forResource: "WindowInjector", ofType: "js") ?? ""
let js = try String(contentsOfFile: path, encoding: .utf8)
Expand Down Expand Up @@ -156,37 +170,76 @@ class StreamModel: BaseModel {
.bind(to: metadataRelay)
.disposed(by: bag)
}

private func loadChat(_ id: String, duration: Double) {
let request = services.youtube.getYTChatURL(id, videoDuration: duration)
private func loadMchadRooms(_ id: String, duration: Double) {
let request = services.mchad.getMchadRoom(id: id, duration: duration)
.asObservable()
.materialize()

let mchad = services.mchad.getMchadRoom(id: id, duration: duration)
request.map { $0.element }
.bind(to: mchadRoomRelay)
.disposed(by: bag)
request.map { $0.error }
.bind(to: errorRelay)
.disposed(by: bag)
}

private func loadMchadArchiveScript(_ room: MchadRoom) {
let request = services.mchad.getMchadArchiveTls(room)
.asObservable()
.materialize()

mchadRoomRelay.compactMap { $0 }
.subscribe(onNext: { room in
self.services.mchad.getMchadArchiveTls(id, room: room)
.asObservable()
.materialize()
.subscribe(onNext: { messages in
if messages.element != nil {
self.translatedRelay.accept(messages.element as! [DisplayableMessage])
}
})
.disposed(by: self.bag)
})
request.map { $0.element }
.bind(to: mchadScriptRelay)
.disposed(by: bag)
request.map { $0.error }
.subscribe(onError: { error in print(error) })
.disposed(by: bag)
}

private func appendMchadScriptTls(_ script: [TranslatedMessage], room: MchadRoom?) {
var mutableScript = script
var mchadOffset: Double = 0.0

// mchad.map { $0.element?.first }
// .bind(to: mchadRoomRelay)
// .disposed(by: bag)
// mchad.map { $0.error }
// .bind(to: errorRelay)
// .disposed(by: bag)
for displayableMessage in script {
if displayableMessage.message.first == Message.text("--- Stream Starts ---") {
mchadOffset = displayableMessage.showTimestamp
break
}
}

replayEventRelay.compactMap { $0.current }
.sample(Observable<Int>.interval(.milliseconds(500), scheduler: MainScheduler.instance), defaultValue: 0.0)
.subscribe(onNext: { time in
var currentRelay = self.translatedRelay.value
let tmpScript = mutableScript.filter { $0.showTimestamp - mchadOffset <= time * 1000 }
mutableScript.removeFirst(tmpScript.endIndex)
for message in tmpScript {
for lang in message.languages {
if self.services.settings.languages.map({ $0.tag }).contains(lang) ||
self.services.settings.languages.map({ $0.description.lowercased().hasPrefix(lang) }).contains(Bool(true)) ||
self.services.settings.languages.map({ $0.tag.lowercased().hasPrefix(lang) }).contains(Bool(true)),
!self.services.settings.neverUsers.contains(message.displayAuthor)
{
var mutableMessage = message
mutableMessage.timestamp = Date()
currentRelay.append(mutableMessage)
}
}
}

if !tmpScript.isEmpty {
self.translatedRelay.accept(currentRelay)
}
})
.disposed(by: bag)
}

private func loadChat(_ id: String, duration: Double) {
let request = services.youtube.getYTChatURL(id, videoDuration: duration)
.asObservable()
.materialize()

request.map { $0.element }
.bind(to: chatURLRelay)
.disposed(by: bag)
Expand Down Expand Up @@ -348,9 +401,11 @@ extension StreamModel: StreamModelInput {
func load(_ id: String) {
loadVideoPlayer(id)
}

func loadPreviewChat(_ id: String, duration: Double) {
loadChat(id, duration: duration)
}

func getMetadata(_ id: String) {
getVideoMeta(id)
}
Expand Down
15 changes: 12 additions & 3 deletions ios/Core/Routing/AppFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import UIKit
import RxCocoa
import RxFlow
import Kingfisher

class AppFlow: Flow {
var root: Presentable {
Expand All @@ -24,6 +25,7 @@ class AppFlow: Flow {
switch step {
case .home : return toHome()
case .view(let id) : return toStreamView(id)
case .streamDone : return streamViewDone()
case .settings : return toSettings()
case .settingsDone : return settingsDone()
case .toConsent(let showAlert): return toConsent(showAlert)
Expand All @@ -35,14 +37,21 @@ class AppFlow: Flow {

private func toHome() -> FlowContributors {
let controller = HomeView(stepper, services)
rootViewController.setViewControllers([controller], animated: true)

rootViewController.pushViewController(controller, animated: true)
//rootViewController.setViewControllers([controller], animated: true)

return .none
}
private func toStreamView(_ id: String) -> FlowContributors {
let controller = StreamView(stepper, services)
controller.load(id)
rootViewController.setViewControllers([controller], animated: true)
KingfisherManager.shared.cache.clearMemoryCache()
rootViewController.pushViewController(controller, animated: true)

return .none
}
private func streamViewDone() -> FlowContributors {
rootViewController.popViewController(animated: true)

return .none
}
Expand Down
1 change: 1 addition & 0 deletions ios/Core/Routing/AppStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import RxFlow
enum AppStep: Step {
case home
case view(_ id: String)
case streamDone
case settings, settingsDone
case filter, filterDone
case toConsent(_ showAlert: Bool), consentDone
Expand Down
Loading