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

Code Cleanup & Restructure Code #49

Merged
merged 3 commits into from
Mar 18, 2024
Merged
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
19 changes: 13 additions & 6 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ authors:
- family-names: "Schmiedmayer"
given-names: "Paul"
orcid: "https://orcid.org/0000-0002-8607-9148"
- family-names: "Ravi"
given-names: "Vishnu"
orcid: "https://orcid.org/0000-0003-0359-1275"
- family-names: "Aalami"
given-names: "Oliver"
orcid: "https://orcid.org/0000-0002-7799-2429"
- family-names: "Jörke"
given-names: "Matthew"
orcid: "https://orcid.org/0000-0003-2972-462X"
- family-names: "Jimenez"
given-names: "Bryant"
- family-names: "Hur"
given-names: "Evelyn"
- family-names: "Tran"
given-names: "Caroline"
- family-names: "Song"
given-names: "Evelyn"
- family-names: "Naik"
given-names: "Dhruv"
title: "Prisma"
6 changes: 6 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ Prisma Contributors
=================================

* [Paul Schmiedmayer](https://github.com/PSchmiedmayer)
* [Matthew Jörke](https://github.com/mjoerke)
* [Bryant Jimenez](https://github.com/bryant-jimenez)
* [Evelyn Hur](https://github.com/evelyn-hur)
* [Caroline Tran](https://github.com/carolinentran)
* [Evelyn Song](https://github.com/EvelynBunnyDev)
* [Dhruv Naik](https://github.com/dhruvna1k)
* [Andreas Bauer](https://github.com/Supereg)
* [Philipp Zagar](https://github.com/philippzagar)
* [Nikolai Madlener](https://github.com/NikolaiMadlener)
113 changes: 64 additions & 49 deletions Prisma.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "2744d3b6cb9385cb089a3b7f85f47cd50be0044a6d049ff1f93f530ab4329df2",
"originHash" : "0234cf36595d6a5fc4bf3c54942b170bdbefd26ef609a4d8a651f17037d3face",
"pins" : [
{
"identity" : "abseil-cpp-binary",
Expand Down Expand Up @@ -132,8 +132,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/ResearchKit",
"state" : {
"revision" : "64512d0a0a5cc3e9d5b3fc5217c54f11d0dc044c",
"version" : "2.2.28"
"revision" : "6b28cdf0d06c3d6e96b5585369968b85deac96e0",
"version" : "2.2.29"
}
},
{
Expand Down Expand Up @@ -199,15 +199,6 @@
"version" : "0.5.3"
}
},
{
"identity" : "spezimockwebservice",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziMockWebService.git",
"state" : {
"revision" : "b18067d3499e630bbd995ef05a296ef8fdd42528",
"version" : "1.0.0"
}
},
{
"identity" : "spezionboarding",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -258,8 +249,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41",
"version" : "1.3.0"
"revision" : "46989693916f56d1186bd59ac15124caef896560",
"version" : "1.3.1"
}
},
{
Expand Down
11 changes: 5 additions & 6 deletions Prisma/Account/AccountSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import SwiftUI


struct AccountSheet: View {
@Environment(\.dismiss) var dismiss

@Environment(\.dismiss) private var dismiss
@Environment(Account.self) private var account
@Environment(\.accountRequired) var accountRequired
@Environment(\.accountRequired) private var accountRequired

@State var isInSetup = false
@State var overviewIsEditing = false
@State private var isInSetup = false
@State private var overviewIsEditing = false


var body: some View {
Expand Down Expand Up @@ -57,7 +56,7 @@ struct AccountSheet: View {
}
}
}

var closeButton: some ToolbarContent {
ToolbarItem(placement: .cancellationAction) {
Button("CLOSE") {
Expand Down
89 changes: 48 additions & 41 deletions Prisma/Chat/ChatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,79 @@
//

import Firebase
import Foundation
import SpeziAccount
import SwiftUI
import WebKit


struct ChatView: View {
@Binding var presentingAccount: Bool
@State private var token: String?


private var url: URL? {
guard let token else {
return nil
}

return Constants.hostname.appending(queryItems: [URLQueryItem(name: token, value: token)])
}


var body: some View {
NavigationStack {
GeometryReader { geometry in
// Fetch JWT token asynchronously
if let token = token {
if let url = URL(string: "http://localhost:3000?token=\(token)") { // this needs to be sent to the frontend
Group {
if let url {
WebView(url: url)
.navigationTitle("Chat")
.frame(
width: geometry.size.width,
height: geometry.size.height
)
} else {
Text("Invalid URL")
VStack(spacing: 16) {
ProgressView()
Text("Loading Chat View")
.foregroundStyle(.secondary)
.font(.caption)
}
}
} else {
ProgressView()
}
.frame(
width: geometry.size.width,
height: geometry.size.height
)
}
/*
.onChange(of: account.signedIn) {
guard account.signedIn else {
return
}

Task {
try await self.signInWithFirebase()
}
}
*/
.task {
do {
try await self.getFirebaseIDToken()
} catch {
print("Firebase Auth failed \(error)")
.navigationTitle("Chat")
.task {
await self.getFirebaseIDToken()
}
.toolbar {
if AccountButton.shouldDisplay {
AccountButton(isPresented: $presentingAccount)
}
}
}
}
}


init(presentingAccount: Binding<Bool>) {
self._presentingAccount = presentingAccount
}
}

extension ChatView {
func getFirebaseIDToken() async throws {
token = try await Auth.auth().currentUser?.getIDToken()
print("token is:", token ?? "")


private func getFirebaseIDToken() async {
guard !ProcessInfo.processInfo.isPreviewSimulator else {
try? await Task.sleep(for: .seconds(1.0))
token = "TOKEN"
return
}

do {
token = try await Auth.auth().currentUser?.getIDToken()
} catch {
print("Firebase Auth failed \(error)")
}
}
}


#if DEBUG
struct ChatView_Previews: PreviewProvider {
static var previews: some View {
ChatView(presentingAccount: .constant(false))
}
#Preview {
ChatView(presentingAccount: .constant(false))
}
#endif
15 changes: 13 additions & 2 deletions Prisma/Chat/WebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,28 @@
import SwiftUI
import WebKit


struct WebView: UIViewRepresentable {
var url: URL



func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.scrollView.isScrollEnabled = true
return webView
}

func updateUIView(_ uiView: WKWebView, context: Context) {
let request = URLRequest(url: url)
uiView.load(request)
}
}


#Preview {
guard let stanfordURL = URL(string: "https://stanford.edu") else {
fatalError("Could not construct URL.")
}

return WebView(url: stanfordURL)
}
131 changes: 131 additions & 0 deletions Prisma/Helper/Date+ConstructTimeIndex.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// This source file is part of the Stanford Prisma Application based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import Foundation


extension Date {
static func constructTimeIndex(startDate: Date, endDate: Date) -> [String: Any?] {
let calendar = Calendar.current
// extract the calendar components from the startDate and the endDate
let startComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: startDate)
let endComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second, .timeZone], from: endDate)
let isRange = startDate != endDate

// initialize a dictionary for timeIndex and populate with info extracted above
var timeIndex: [String: Any?] = [
"range": isRange,
"timezone": startComponents.timeZone?.identifier,
"datetime.start": startDate.toISOFormat(),
"datetime.end": endDate.toISOFormat()
]

// passing the timeIndex dictionary by reference so the changes persist
addTimeIndexComponents(&timeIndex, dateComponents: startComponents, suffix: ".start")
addTimeIndexComponents(&timeIndex, dateComponents: endComponents, suffix: ".end")
addTimeIndexRangeComponents(&timeIndex, startComponents: startComponents, endComponents: endComponents)

return timeIndex
}


// populate timeIndex dict with individual components from DateComponents (startComponents for this case)
// "inout" parameter means the argument is passed by reference (dict is modified inside the funct and changes persist)
private static func addTimeIndexComponents(_ timeIndex: inout [String: Any?], dateComponents: DateComponents, suffix: String) {
timeIndex["year" + suffix] = dateComponents.year
timeIndex["month" + suffix] = dateComponents.month
timeIndex["day" + suffix] = dateComponents.day
timeIndex["hour" + suffix] = dateComponents.hour
timeIndex["minute" + suffix] = dateComponents.minute
timeIndex["second" + suffix] = dateComponents.second
timeIndex["dayMinute" + suffix] = calculateDayMinute(hour: dateComponents.hour, minute: dateComponents.minute)
timeIndex["fifteenMinBucket" + suffix] = calculate15MinBucket(hour: dateComponents.hour, minute: dateComponents.minute)
}

// if the start/end time shows that we have a time RANGE and not a time STAMP
// then add the range-related components to the timeIndex
private static func addTimeIndexRangeComponents(
_ timeIndex: inout [String: Any?],
startComponents: DateComponents,
endComponents: DateComponents
) {
timeIndex["year.range"] = getRange(
start: startComponents.year,
end: endComponents.year,
maxValue: Int.max
)
timeIndex["month.range"] = getRange(
start: startComponents.month,
end: endComponents.month,
maxValue: 12,
startValue: 1 // months are 1-indexed
)
timeIndex["day.range"] = getRange(
start: startComponents.day,
end: endComponents.day,
maxValue: daysInMonth(month: startComponents.month, year: startComponents.year),
startValue: 1 // days are 1-indexed
)
timeIndex["hour.range"] = getRange(
start: startComponents.hour,
end: endComponents.hour,
maxValue: 23
)
timeIndex["dayMinute.range"] = getRange(
start: calculateDayMinute(hour: startComponents.hour, minute: startComponents.minute),
end: calculateDayMinute(hour: endComponents.hour, minute: endComponents.minute),
maxValue: 1439
)
timeIndex["fifteenMinBucket.range"] = getRange(
start: calculate15MinBucket(hour: startComponents.hour, minute: startComponents.minute),
end: calculate15MinBucket(hour: endComponents.hour, minute: endComponents.minute),
maxValue: 95
)

// Minute and second ranges are not likely to be accurate since they often will fill the whole range.
// We will also never query on individual minutes or seconds worth of data.
}

// swiftlint:disable discouraged_optional_collection
// passed the start and end bounds, returns the range in whichever unit passed in
private static func getRange(start: Int?, end: Int?, maxValue: Int?, startValue: Int = 0) -> [Int]? {
guard let startInt = start, let endInt = end, let maxValueInt = maxValue else {
return nil
}

if startInt <= endInt {
return Array(startInt...endInt)
} else {
return Array(startInt...maxValueInt) + Array(startValue...endInt)
}
}

private static func daysInMonth(month: Int?, year: Int?) -> Int? {
let dateComponents = DateComponents(year: year, month: month)
let calendar = Calendar.current
guard let date = calendar.date(from: dateComponents),
let range = calendar.range(of: .day, in: .month, for: date) else {
return nil // Provide a default value in case of nil
}
return range.count
}

private static func calculateDayMinute(hour: Int?, minute: Int?) -> Int? {
guard let hour = hour, let minute = minute else {
return nil
}
return hour * 60 + minute
}

private static func calculate15MinBucket(hour: Int?, minute: Int?) -> Int? {
guard let hour = hour, let minute = minute else {
return nil
}
return hour * 4 + minute / 15
}
}
Loading
Loading