Skip to content
Merged

V3 #24

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
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ struct JoinGroup: View {
print("Scanned code: \(code)")


if code.contains("vitty.app/join") {
if code.contains("vitty://join") {
if let url = URL(string: code) {
handleDeepLink(url)
}
Expand Down
71 changes: 28 additions & 43 deletions VITTY/VITTY/Connect/View/Circles/Components/QrCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct QRCodeModalView: View {
.foregroundColor(.white)
}

// QR Code Display

if isGeneratingCode {
Rectangle()
.fill(Color.gray.opacity(0.3))
Expand All @@ -54,7 +54,7 @@ struct QRCodeModalView: View {
}
)
} else if !joinCode.isEmpty {
if let qrImage = generateQRCode(from: createInvitationLink()) {
if let qrImage = generateQRCode(from: createDeepLink()) {
Image(uiImage: qrImage)
.interpolation(.none)
.resizable()
Expand Down Expand Up @@ -134,28 +134,29 @@ struct QRCodeModalView: View {
.multilineTextAlignment(.center)
.padding(.horizontal)

// Action Buttons

HStack(spacing: 12) {

Button(action: {
if joinCode.isEmpty {
generateJoinCode()
} else {
showingShareSheet = true
}
}) {
HStack {
Image(systemName: joinCode.isEmpty ? "qrcode" : "square.and.arrow.up")
Text(joinCode.isEmpty ? "Generate QR Code" : "Share Invitation")
if joinCode.isEmpty{
Button(action: {
if joinCode.isEmpty {
generateJoinCode()
}
}) {
HStack {
Image(systemName:"qrcode" )
Text( "Generate QR Code")
}
.font(.custom("Poppins-SemiBold", size: 14))
.foregroundColor(Color("Background"))
.padding(.horizontal, 16)
.padding(.vertical, 8)
.background(Color("Accent"))
.cornerRadius(8)
}
.font(.custom("Poppins-SemiBold", size: 14))
.foregroundColor(Color("Background"))
.padding(.horizontal, 16)
.padding(.vertical, 8)
.background(Color("Accent"))
.cornerRadius(8)
.disabled(isGeneratingCode)
}
.disabled(isGeneratingCode)


}
}
.frame(maxWidth: 300)
Expand All @@ -167,12 +168,7 @@ struct QRCodeModalView: View {
Spacer()
}
.background(Color.black.opacity(0.5).edgesIgnoringSafeArea(.all))
.sheet(isPresented: $showingShareSheet) {
ShareSheetQr(items: [
createInvitationLink(),
"Join my circle '\(circleName)' on VITTY! Use code: \(joinCode)"
])
}

.alert("Error", isPresented: $showError) {
Button("OK") { }
} message: {
Expand Down Expand Up @@ -225,14 +221,13 @@ struct QRCodeModalView: View {
print("Join code copied to clipboard")
}

private func createInvitationLink() -> String {
let baseURL = "https://vitty.app/join"


private func createDeepLink() -> String {
guard let encodedCircleName = circleName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
return "\(baseURL)?code=\(joinCode)"
return "vitty://join?code=\(joinCode)"
}
return "\(baseURL)?code=\(joinCode)&circleName=\(encodedCircleName)"
//vitty://join?code=Ow2tWaHExs&circleName=newircircle
return "vitty://join?code=\(joinCode)&circleName=\(encodedCircleName)"
}

private func generateQRCode(from string: String) -> UIImage? {
Expand All @@ -254,13 +249,3 @@ struct QRCodeModalView: View {
}
}

struct ShareSheetQr: UIViewControllerRepresentable {
let items: [Any]

func makeUIViewController(context: Context) -> UIActivityViewController {
let controller = UIActivityViewController(activityItems: items, applicationActivities: nil)
return controller
}

func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}
27 changes: 25 additions & 2 deletions VITTY/VITTY/Connect/View/Circles/View/Circles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
//
import SwiftUI

import SwiftUI

struct CirclesView: View {
@Binding var isCreatingGroup: Bool
@State private var searchText = ""
@Environment(CommunityPageViewModel.self) private var communityPageViewModel
@Environment(AuthViewModel.self) private var authViewModel



@EnvironmentObject private var navigationCoordinator: NavigationCoordinator

var body: some View {
NavigationStack {
VStack(spacing: 12) {
Expand Down Expand Up @@ -52,7 +57,7 @@ struct CirclesView: View {
VStack(spacing: 10) {
ForEach(filteredCircles, id: \.circleID) { circle in

NavigationLink(destination: InsideCircle(circleName: circle.circleName, circle_id:circle.circleID, circle_join_code: circle.circleJoinCode,circle_role: circle.circleRole)) {
NavigationLink(destination: InsideCircle(circleName: circle.circleName, circle_id: circle.circleID, circle_join_code: circle.circleJoinCode, circle_role: circle.circleRole)) {
CirclesRow(circle: circle)
}
.buttonStyle(PlainButtonStyle())
Expand All @@ -71,6 +76,24 @@ struct CirclesView: View {
loading: true
)
}
.onReceive(NotificationCenter.default.publisher(for: Notification.Name("CircleJoinedSuccessfully"))) { _ in

communityPageViewModel.fetchCircleData(
from: "\(APIConstants.base_url)circles",
token: authViewModel.loggedInBackendUser?.token ?? "",
loading: true
)
}

.onAppear {

if let pendingInvite = navigationCoordinator.pendingCircleInvite {

print("CirclesView appeared with pending invite: \(pendingInvite.code)")


}
}
}
}
}
4 changes: 3 additions & 1 deletion VITTY/VITTY/Connect/View/Circles/View/InsideCircle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -509,12 +509,13 @@ struct InsideCircle: View {
LeaveCircleAlert(circleName: "\(circleName)", onCancel: {
showLeaveAlert = false
}, onLeave: {
let url = "\(APIConstants.base_url)circles/\(circle_id)/leave"
let url = "\(APIConstants.base_url)circles/leave/\(circle_id)"
let token = authViewModel.loggedInBackendUser?.token ?? ""

communityPageViewModel.leaveCircle(from: url, token: token)

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
communityPageViewModel.fetchCircleData(from:"\(APIConstants.base_url)circles" , token: token)
showLeaveAlert = false
presentationMode.wrappedValue.dismiss()
}
Expand All @@ -532,6 +533,7 @@ struct InsideCircle: View {

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
showDeleteAlert = false

presentationMode.wrappedValue.dismiss()
}
})
Expand Down
14 changes: 14 additions & 0 deletions VITTY/VITTY/Connect/View/ConnectPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct ConnectPage: View {
@State private var showCircleMenu = false
@Environment(\.dismiss) private var dismiss

@EnvironmentObject private var navigationCoordinator: NavigationCoordinator
@Binding var isCreatingGroup : Bool

@State private var isAddFriendsViewPresented = false
Expand Down Expand Up @@ -143,8 +144,20 @@ struct ConnectPage: View {
case .groupRequests:
CircleRequestsView()
}
}.onChange(of: navigationCoordinator.shouldNavigateToCircles) { _, shouldNavigate in
if shouldNavigate {
selectedTab = 0
}
communityPageViewModel.fetchCircleData(
from: "\(APIConstants.base_url)circles",
token: authViewModel.loggedInBackendUser?.token ?? "",
loading: true
)
}
.onAppear {
if navigationCoordinator.shouldNavigateToCircles {
selectedTab = 0
}
let shouldShowLoading = !hasLoadedInitialData


Expand All @@ -153,6 +166,7 @@ struct ConnectPage: View {
loading: shouldShowLoading
)


if communityPageViewModel.friends.isEmpty || !hasLoadedInitialData {
communityPageViewModel.fetchFriendsData(
from: "\(APIConstants.base_url)friends/\(authViewModel.loggedInBackendUser?.username ?? "")/",
Expand Down
7 changes: 4 additions & 3 deletions VITTY/VITTY/Connect/ViewModel/CommunityPageViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,6 @@ class CommunityPageViewModel {
}
}
}
}
}
}

//MARK : Circle Leave
func fetchCircleLeave(from url: String, token: String, loading: Bool = false) {
Expand Down Expand Up @@ -310,13 +307,17 @@ class CommunityPageViewModel {
switch response.result {
case .success:
self.logger.info("Successfully left circle")


case .failure(let error):
self.logger.error("Error leaving circle: \(error)")
self.errorCircleMembers = true
}
}


}

}

//MARK: Delete Circle
Expand Down
14 changes: 13 additions & 1 deletion VITTY/VITTY/Home/View/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ struct HomeView: View {
@State private var showProfileSidebar: Bool = false
@State private var isCreatingGroup = false
@StateObject private var tipManager = CustomTipManager()


@EnvironmentObject private var navigationCoordinator: NavigationCoordinator

var body: some View {
NavigationStack {
Expand Down Expand Up @@ -39,6 +42,16 @@ struct HomeView: View {
.onChange(of: selectedPage) { _, newValue in
handleTabChange(newValue)
}
// NEW: Listen for deep link navigation
.onReceive(NotificationCenter.default.publisher(for: Notification.Name("NavigateToCircles"))) { _ in
selectedPage = 2 // Navigate to Connects tab
}
// NEW: Handle navigation coordinator changes
.onChange(of: navigationCoordinator.shouldNavigateToCircles) { _, shouldNavigate in
if shouldNavigate {
selectedPage = 2
}
}
}
}

Expand Down Expand Up @@ -138,7 +151,6 @@ struct HomeView: View {
}

private func handleTabChange(_ newTab: Int) {

print("Switched to tab: \(newTab)")
}
}
35 changes: 23 additions & 12 deletions VITTY/VITTY/Settings/View/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,13 @@ struct SettingsView: View {
try await deleteUserFromServer(username: username)

await MainActor.run {
cleanupLocalData()
authViewModel.signOut()
showDeleteUserAlert = false
isDeletingUser = false

Task {
await cleanupLocalData()
authViewModel.signOut()
showDeleteUserAlert = false
isDeletingUser = false
}
}
} catch {
await MainActor.run {
Expand Down Expand Up @@ -237,18 +240,26 @@ struct SettingsView: View {
}
}

private func cleanupLocalData() {
private func cleanupLocalData() async {
do {
try modelContext.delete(model: TimeTable.self)
try modelContext.delete(model: Remainder.self)
try modelContext.delete(model: CreateNoteModel.self)
try modelContext.delete(model: UploadedFile.self)
try modelContext.save()
print("Successfully cleaned up local data")

await Task.detached { [modelContext] in
do {
try modelContext.delete(model: TimeTable.self)
try modelContext.delete(model: Remainder.self)
try modelContext.delete(model: CreateNoteModel.self)
try modelContext.delete(model: UploadedFile.self)
try modelContext.save()
print("Successfully cleaned up local data")
} catch {
print("Failed to clean up local data: \(error)")
}
}.value
} catch {
print("Failed to clean up local data: \(error)")
print("Failed to clear local data: \(error)")
}
}



private func copyLecturesToSaturday(from day: String) {
Expand Down
Loading
Loading