Skip to content

Commit

Permalink
refactor: Realtime V2 (#214)
Browse files Browse the repository at this point in the history
* feat: add EventType to Realtime Message

* refactor: rename Message to RealtimeMessage

* feat: add callback manager

* feat: implement onMessage handler

* refactor realtime based on Kotlin library

* wip

* Fix Realtime connection

* Add Sendable conformances and make classes thread safe

* Rename v2 types

* Fix Realtime tests

* Fix leaks

* add _Presence type

* block task until subscribed

* wip

* Make Realtime and Channel Actors

* wip slack clone example

* Fix tests

* Rename Realtime to RealtimeClientV2

* fix: pending heartbeat check

* Remove AuthTokenProvider

* wip

* Remove Combine

* Remove OSLog as it doesn't support non-Apple platform

* Import FoundationNetworking

* Integrate SupabaseLogger

* Fix Realtime access token and improve slack clone example

* wip

* Test

* test: realtime connect and subscribe

* Import Dispatch

* Remove NSEC_PER_SEC since non-Darwin don't have it

* Trying to fix build on Linux

* ci: use Xcode 15.2

* Comment out failing test

* Add local supabase instance for SlackClone

* Add visionOS support for SlackClone example

* Add migration guide
  • Loading branch information
grdsdev authored Jan 22, 2024
1 parent 7288685 commit 4a11b64
Show file tree
Hide file tree
Showing 67 changed files with 4,358 additions and 527 deletions.
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Use an official Swift runtime as a base image
FROM swift:latest

# Set the working directory to /app
WORKDIR /app

# Copy the entire content of the local directory to the container
COPY . .

# Build the Swift package
RUN swift build

# Run tests
CMD ["swift", "test"]

372 changes: 212 additions & 160 deletions Examples/Examples.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1520"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "79D884C62B3C18830009EA4A"
BuildableName = "SlackClone.app"
BlueprintName = "SlackClone"
ReferencedContainer = "container:Examples.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "79D884C62B3C18830009EA4A"
BuildableName = "SlackClone.app"
BlueprintName = "SlackClone"
ReferencedContainer = "container:Examples.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "79D884C62B3C18830009EA4A"
BuildableName = "SlackClone.app"
BlueprintName = "SlackClone"
ReferencedContainer = "container:Examples.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
127 changes: 0 additions & 127 deletions Examples/RealtimeSample/ContentView.swift

This file was deleted.

27 changes: 0 additions & 27 deletions Examples/RealtimeSample/RealtimeSampleApp.swift

This file was deleted.

55 changes: 55 additions & 0 deletions Examples/SlackClone/AppView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// AppView.swift
// SlackClone
//
// Created by Guilherme Souza on 27/12/23.
//

import Supabase
import SwiftUI

@Observable
@MainActor
final class AppViewModel {
var session: Session?
var selectedChannel: Channel?

init() {
Task { [weak self] in
for await (event, session) in await supabase.auth.authStateChanges {
guard [.signedIn, .signedOut, .initialSession].contains(event) else { return }
self?.session = session

if session == nil {
for subscription in await supabase.realtimeV2.subscriptions.values {
await subscription.unsubscribe()
}
}
}
}
}
}

@MainActor
struct AppView: View {
@Bindable var model: AppViewModel

@ViewBuilder
var body: some View {
if model.session != nil {
NavigationSplitView {
ChannelListView(channel: $model.selectedChannel)
} detail: {
if let channel = model.selectedChannel {
MessagesView(channel: channel).id(channel.id)
}
}
} else {
AuthView()
}
}
}

#Preview {
AppView(model: AppViewModel())
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"idiom" : "mac",
"scale" : "1x",
Expand Down
68 changes: 68 additions & 0 deletions Examples/SlackClone/AuthView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// AuthView.swift
// SlackClone
//
// Created by Guilherme Souza on 27/12/23.
//

import SwiftUI

@Observable
@MainActor
final class AuthViewModel {
var email = ""
var toast: ToastState?

func signInButtonTapped() {
Task {
do {
try await supabase.auth.signInWithOTP(
email: email,
redirectTo: URL(string: "slackclone://sign-in")
)
toast = ToastState(status: .success, title: "Check your inbox.")
} catch {
toast = ToastState(status: .error, title: "Error", description: error.localizedDescription)
}
}
}

func handle(_ url: URL) {
Task {
do {
try await supabase.auth.session(from: url)
} catch {
toast = ToastState(status: .error, title: "Error", description: error.localizedDescription)
}
}
}
}

@MainActor
struct AuthView: View {
@Bindable var model = AuthViewModel()

var body: some View {
VStack {
VStack {
TextField("Email", text: $model.email)
#if os(iOS)
.textInputAutocapitalization(.never)
.keyboardType(.emailAddress)
#endif
.textContentType(.emailAddress)
.autocorrectionDisabled()
}
Button("Sign in with Magic Link") {
model.signInButtonTapped()
}
}
.padding()
.toast(state: $model.toast)
.onOpenURL { model.handle($0) }
}
}

#Preview {
AuthView()
}
Loading

0 comments on commit 4a11b64

Please sign in to comment.