Compare commits
1 commit
e680978f2d
...
228a9c96e3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
228a9c96e3 |
10 changed files with 267 additions and 200 deletions
|
|
@ -1,5 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
using Godot;
|
|
||||||
using SpacetimeDB;
|
|
||||||
using SpacetimeDB.Types;
|
|
||||||
|
|
||||||
public partial class ChatInput : LineEdit
|
|
||||||
{
|
|
||||||
public override void _EnterTree()
|
|
||||||
{
|
|
||||||
TextSubmitted += OnMessageInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the node enters the scene tree for the first time.
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
DbConnection conn = Spacetime.Instance.Connection;
|
|
||||||
RegisterSubscriptions(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnMessageInput(string text)
|
|
||||||
{
|
|
||||||
Spacetime.Instance.Connection.Reducers.SendMessage(text);
|
|
||||||
Text = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterSubscriptions(DbConnection conn)
|
|
||||||
{
|
|
||||||
conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Our `OnSendMessageEvent` callback: print a warning if the reducer failed.
|
|
||||||
void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text)
|
|
||||||
{
|
|
||||||
var e = ctx.Event;
|
|
||||||
if (e.CallerIdentity == Spacetime.Instance.Identity && e.Status is Status.Failed(var error))
|
|
||||||
{
|
|
||||||
GD.PrintErr($"Failed to send message {text}: {error}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
uid://115ssbk8epio
|
|
||||||
|
|
@ -1,87 +1,20 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using SpacetimeDB;
|
|
||||||
using SpacetimeDB.Types;
|
|
||||||
|
|
||||||
public partial class ChatLog : RichTextLabel
|
public partial class ChatLog : RichTextLabel
|
||||||
{
|
{
|
||||||
const string SystemColor = "#747474";
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
|
||||||
public override void _EnterTree()
|
|
||||||
{
|
|
||||||
ClearLog();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
DbConnection conn = Spacetime.Instance.Connection;
|
|
||||||
RegisterSubscriptions(conn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string UserNameOrIdentity(User user)
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
return user != null ? user.Name ?? user.Identity.ToString()[..8] : "unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushMessage(string name, string message, string color)
|
public void PushMessage(string name, string message, string color)
|
||||||
{
|
{
|
||||||
string entry = $"[color={color}]{name}:[/color] {message}";
|
string entry = $"[color={color}]{name}:[/color] {message}";
|
||||||
this.Text += $"{entry}\n";
|
this.Text += $"{entry}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearLog()
|
|
||||||
{
|
|
||||||
Text = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterSubscriptions(DbConnection conn)
|
|
||||||
{
|
|
||||||
conn.Db.User.OnInsert += User_OnInsert;
|
|
||||||
conn.Db.User.OnUpdate += User_OnUpdate;
|
|
||||||
|
|
||||||
conn.Db.Message.OnInsert += Message_OnInsert;
|
|
||||||
}
|
|
||||||
|
|
||||||
void User_OnInsert(EventContext ctx, User insertedValue)
|
|
||||||
{
|
|
||||||
if (ctx.Event is Event<Reducer>.SubscribeApplied)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PushMessage("System", $"{UserNameOrIdentity(insertedValue)} connected", SystemColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
|
|
||||||
{
|
|
||||||
if (oldValue.Name != newValue.Name)
|
|
||||||
{
|
|
||||||
PushMessage(
|
|
||||||
"System",
|
|
||||||
$"{UserNameOrIdentity(oldValue)} renamed to {UserNameOrIdentity(newValue)}",
|
|
||||||
SystemColor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (oldValue.Online != newValue.Online)
|
|
||||||
{
|
|
||||||
if (newValue.Online)
|
|
||||||
{
|
|
||||||
PushMessage("System", $"{UserNameOrIdentity(newValue)} connected", SystemColor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PushMessage("System", $"{UserNameOrIdentity(newValue)} disconnected", SystemColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Message_OnInsert(EventContext ctx, Message insertedValue)
|
|
||||||
{
|
|
||||||
User sender = ctx.Db.User.Identity.Find(insertedValue.Sender);
|
|
||||||
string color = sender.Identity.Equals(Spacetime.Instance.Identity) ? "blue" : "red";
|
|
||||||
if (ctx.Event is Event<Reducer>.SubscribeApplied)
|
|
||||||
{
|
|
||||||
PushMessage(UserNameOrIdentity(sender), insertedValue.Text, color);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PushMessage(UserNameOrIdentity(sender), insertedValue.Text, color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
using Godot;
|
|
||||||
using SpacetimeDB;
|
|
||||||
using SpacetimeDB.Types;
|
|
||||||
|
|
||||||
public partial class ChatOptions : HBoxContainer
|
|
||||||
{
|
|
||||||
public LineEdit Username { get; private set; }
|
|
||||||
public ColorPickerButton ColorPicker { get; private set; }
|
|
||||||
|
|
||||||
public override void _EnterTree()
|
|
||||||
{
|
|
||||||
Username = GetNode<LineEdit>("Username");
|
|
||||||
ColorPicker = GetNode<ColorPickerButton>("ColorPicker");
|
|
||||||
|
|
||||||
Username.TextSubmitted += OnUsernameInput;
|
|
||||||
Username.FocusExited += ResetUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
DbConnection conn = Spacetime.Instance.Connection;
|
|
||||||
RegisterSubscriptions(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
string UserNameOrIdentity(User user)
|
|
||||||
{
|
|
||||||
return user != null ? user.Name ?? user.Identity.ToString()[..8] : "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetUsername()
|
|
||||||
{
|
|
||||||
Username.Text = UserNameOrIdentity(Spacetime.Instance.Me);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnUsernameInput(string text)
|
|
||||||
{
|
|
||||||
Spacetime.Instance.Connection.Reducers.SetName(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterSubscriptions(DbConnection conn)
|
|
||||||
{
|
|
||||||
conn.Reducers.OnSetName += Reducer_OnSetNameEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Our `OnSetNameEvent` callback: print a warning if the reducer failed.
|
|
||||||
void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name)
|
|
||||||
{
|
|
||||||
var e = ctx.Event;
|
|
||||||
if (e.CallerIdentity != Spacetime.Instance.Identity)
|
|
||||||
{
|
|
||||||
// Not me
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (e.Status is Status.Failed(var error))
|
|
||||||
{
|
|
||||||
GD.PrintErr($"Failed to change name to {name}: {error}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
uid://tff5u6blrc1d
|
|
||||||
|
|
@ -1,16 +1,136 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using SpacetimeDB;
|
||||||
|
using SpacetimeDB.Types;
|
||||||
|
|
||||||
public partial class ChatWindow : VBoxContainer
|
public partial class ChatWindow : VBoxContainer
|
||||||
{
|
{
|
||||||
private ChatOptions _options;
|
const string SystemColor = "#747474";
|
||||||
|
|
||||||
|
private LineEdit _userNameInput;
|
||||||
private ChatLog _log;
|
private ChatLog _log;
|
||||||
private LineEdit _input;
|
private LineEdit _input;
|
||||||
|
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _EnterTree()
|
public override void _EnterTree()
|
||||||
{
|
{
|
||||||
_options = GetNode<ChatOptions>("Options");
|
_userNameInput = GetNode<LineEdit>("Options/Username");
|
||||||
_log = GetNode<ChatLog>("ChatLog");
|
_log = GetNode<ChatLog>("ChatLog");
|
||||||
_input = GetNode<ChatInput>("ChatInput");
|
_input = GetNode<LineEdit>("ChatInput");
|
||||||
|
|
||||||
|
_log.Text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string UserNameOrIdentity(User user)
|
||||||
|
{
|
||||||
|
return user != null ? user.Name ?? user.Identity.ToString()[..8] : "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
DbConnection conn = Spacetime.Instance.Connection;
|
||||||
|
|
||||||
|
_userNameInput.TextSubmitted += OnUsernameInput;
|
||||||
|
_userNameInput.FocusExited += ResetUsername;
|
||||||
|
_input.TextSubmitted += OnMessageInput;
|
||||||
|
|
||||||
|
conn.Db.User.OnInsert += User_OnInsert;
|
||||||
|
conn.Db.User.OnUpdate += User_OnUpdate;
|
||||||
|
|
||||||
|
conn.Db.Message.OnInsert += Message_OnInsert;
|
||||||
|
|
||||||
|
conn.Reducers.OnSetName += Reducer_OnSetNameEvent;
|
||||||
|
conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetUsername()
|
||||||
|
{
|
||||||
|
_userNameInput.Text = UserNameOrIdentity(Spacetime.Instance.Me);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUsernameInput(string text)
|
||||||
|
{
|
||||||
|
Spacetime.Instance.Connection.Reducers.SetName(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMessageInput(string text)
|
||||||
|
{
|
||||||
|
Spacetime.Instance.Connection.Reducers.SendMessage(text);
|
||||||
|
_input.Text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void User_OnInsert(EventContext ctx, User insertedValue)
|
||||||
|
{
|
||||||
|
if (ctx.Event is Event<Reducer>.SubscribeApplied)
|
||||||
|
{
|
||||||
|
if (insertedValue.Identity == Spacetime.Instance.Identity)
|
||||||
|
{
|
||||||
|
ResetUsername();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_log.PushMessage("System", $"{UserNameOrIdentity(insertedValue)} connected", SystemColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
|
||||||
|
{
|
||||||
|
if (oldValue.Name != newValue.Name)
|
||||||
|
{
|
||||||
|
_log.PushMessage("System", $"{UserNameOrIdentity(oldValue)} renamed to {UserNameOrIdentity(newValue)}", SystemColor);
|
||||||
|
}
|
||||||
|
if (oldValue.Online != newValue.Online)
|
||||||
|
{
|
||||||
|
if (newValue.Online)
|
||||||
|
{
|
||||||
|
_log.PushMessage("System", $"{UserNameOrIdentity(newValue)} connected", SystemColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_log.PushMessage("System", $"{UserNameOrIdentity(newValue)} disconnected", SystemColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Message_OnInsert(EventContext ctx, Message insertedValue)
|
||||||
|
{
|
||||||
|
User sender = ctx.Db.User.Identity.Find(insertedValue.Sender);
|
||||||
|
string color = sender.Identity.Equals(Spacetime.Instance.Identity) ? "blue" : "red";
|
||||||
|
if (ctx.Event is Event<Reducer>.SubscribeApplied)
|
||||||
|
{
|
||||||
|
_log.PushMessage(UserNameOrIdentity(sender), insertedValue.Text, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_log.PushMessage(UserNameOrIdentity(sender), insertedValue.Text, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Our `OnSetNameEvent` callback: print a warning if the reducer failed.
|
||||||
|
void Reducer_OnSetNameEvent(ReducerEventContext ctx, string name)
|
||||||
|
{
|
||||||
|
var e = ctx.Event;
|
||||||
|
if (e.CallerIdentity != Spacetime.Instance.Identity)
|
||||||
|
{
|
||||||
|
// Not me
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.Status is Status.Failed(var error))
|
||||||
|
{
|
||||||
|
GD.PrintErr($"Failed to change name to {name}: {error}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Our `OnSendMessageEvent` callback: print a warning if the reducer failed.
|
||||||
|
void Reducer_OnSendMessageEvent(ReducerEventContext ctx, string text)
|
||||||
|
{
|
||||||
|
var e = ctx.Event;
|
||||||
|
if (e.CallerIdentity == Spacetime.Instance.Identity && e.Status is Status.Failed(var error))
|
||||||
|
{
|
||||||
|
GD.PrintErr($"Failed to send message {text}: {error}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
[gd_scene load_steps=5 format=3 uid="uid://cqmy41vtnqd6f"]
|
[gd_scene load_steps=3 format=3 uid="uid://cqmy41vtnqd6f"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://c3s41dv7hv4md" path="res://chat/ChatWindow.cs" id="1_d8jvm"]
|
[ext_resource type="Script" uid="uid://c3s41dv7hv4md" path="res://chat/ChatWindow.cs" id="1_d8jvm"]
|
||||||
[ext_resource type="Script" uid="uid://cgn6wa7td0ekp" path="res://chat/ChatLog.cs" id="2_fkxbv"]
|
[ext_resource type="Script" uid="uid://cgn6wa7td0ekp" path="res://chat/ChatLog.cs" id="2_fkxbv"]
|
||||||
[ext_resource type="Script" uid="uid://tff5u6blrc1d" path="res://chat/ChatOptions.cs" id="2_lvlsn"]
|
|
||||||
[ext_resource type="Script" uid="uid://115ssbk8epio" path="res://chat/ChatInput.cs" id="4_yd183"]
|
|
||||||
|
|
||||||
[node name="Chat Window" type="VBoxContainer"]
|
[node name="Chat Window" type="VBoxContainer"]
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
|
|
@ -16,7 +14,6 @@ script = ExtResource("1_d8jvm")
|
||||||
[node name="Options" type="HBoxContainer" parent="."]
|
[node name="Options" type="HBoxContainer" parent="."]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
alignment = 2
|
alignment = 2
|
||||||
script = ExtResource("2_lvlsn")
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="Options"]
|
[node name="Label" type="Label" parent="Options"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
@ -26,7 +23,7 @@ text = "Username:"
|
||||||
custom_minimum_size = Vector2(120, 0)
|
custom_minimum_size = Vector2(120, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="ColorPicker" type="ColorPickerButton" parent="Options"]
|
[node name="ColorPickerButton" type="ColorPickerButton" parent="Options"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Color"
|
text = "Color"
|
||||||
|
|
||||||
|
|
@ -41,4 +38,3 @@ script = ExtResource("2_fkxbv")
|
||||||
|
|
||||||
[node name="ChatInput" type="LineEdit" parent="."]
|
[node name="ChatInput" type="LineEdit" parent="."]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
script = ExtResource("4_yd183")
|
|
||||||
|
|
|
||||||
123
client/spacetime/Program.cs
Normal file
123
client/spacetime/Program.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
// using SpacetimeDB;
|
||||||
|
// using SpacetimeDB.Types;
|
||||||
|
// using System;
|
||||||
|
// using System.Collections.Concurrent;
|
||||||
|
//
|
||||||
|
// // our local client SpacetimeDB identity
|
||||||
|
// Identity? local_identity = null;
|
||||||
|
//
|
||||||
|
// // declare a thread safe queue to store commands
|
||||||
|
// var input_queue = new ConcurrentQueue<(string Command, string Args)>();
|
||||||
|
//
|
||||||
|
// void Main()
|
||||||
|
// {
|
||||||
|
// // Initialize the `AuthToken` module
|
||||||
|
// AuthToken.Init(".spacetime_csharp_quickstart");
|
||||||
|
// // Builds and connects to the database
|
||||||
|
// DbConnection? conn = null;
|
||||||
|
// conn = ConnectToDB();
|
||||||
|
// // Registers to run in response to database events.
|
||||||
|
// RegisterCallbacks(conn);
|
||||||
|
// // Declare a threadsafe cancel token to cancel the process loop
|
||||||
|
// var cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
// // Spawn a thread to call process updates and process commands
|
||||||
|
// var thread = new Thread(() => ProcessThread(conn, cancellationTokenSource.Token));
|
||||||
|
// thread.Start();
|
||||||
|
// // Handles CLI input
|
||||||
|
// InputLoop();
|
||||||
|
// // This signals the ProcessThread to stop
|
||||||
|
// cancellationTokenSource.Cancel();
|
||||||
|
// thread.Join();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// The URI of the SpacetimeDB instance hosting our chat database and module.
|
||||||
|
// const string HOST = "http://localhost:3000";
|
||||||
|
//
|
||||||
|
// /// The database name we chose when we published our module.
|
||||||
|
// const string DB_NAME = "quickstart-chat";
|
||||||
|
//
|
||||||
|
// /// Load credentials from a file and connect to the database.
|
||||||
|
// DbConnection ConnectToDB()
|
||||||
|
// {
|
||||||
|
// DbConnection? conn = null;
|
||||||
|
// conn = DbConnection.Builder()
|
||||||
|
// .WithUri(HOST)
|
||||||
|
// .WithModuleName(DB_NAME)
|
||||||
|
// .WithToken(AuthToken.Token)
|
||||||
|
// .OnConnect(OnConnected)
|
||||||
|
// .OnConnectError(OnConnectError)
|
||||||
|
// .OnDisconnect(OnDisconnected)
|
||||||
|
// .Build();
|
||||||
|
// return conn;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Our `OnConnected` callback: save our credentials to a file.
|
||||||
|
// void OnConnected(DbConnection conn, Identity identity, string authToken)
|
||||||
|
// {
|
||||||
|
// local_identity = identity;
|
||||||
|
// AuthToken.SaveToken(authToken);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Our `OnConnectError` callback: print the error, then exit the process.
|
||||||
|
// void OnConnectError(Exception e)
|
||||||
|
// {
|
||||||
|
// Console.Write($"Error while connecting: {e}");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Our `OnDisconnect` callback: print a note, then exit the process.
|
||||||
|
// void OnDisconnected(DbConnection conn, Exception? e)
|
||||||
|
// {
|
||||||
|
// if (e != null)
|
||||||
|
// {
|
||||||
|
// Console.Write($"Disconnected abnormally: {e}");
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Console.Write($"Disconnected normally.");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Register all the callbacks our app will use to respond to database events.
|
||||||
|
// void RegisterCallbacks(DbConnection conn)
|
||||||
|
// {
|
||||||
|
// conn.Db.User.OnInsert += User_OnInsert;
|
||||||
|
// conn.Db.User.OnUpdate += User_OnUpdate;
|
||||||
|
//
|
||||||
|
// conn.Db.Message.OnInsert += Message_OnInsert;
|
||||||
|
//
|
||||||
|
// conn.Reducers.OnSetName += Reducer_OnSetNameEvent;
|
||||||
|
// conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// If the user has no set name, use the first 8 characters from their identity.
|
||||||
|
// string UserNameOrIdentity(User user) => user.Name ?? user.Identity.ToString()[..8];
|
||||||
|
//
|
||||||
|
// /// Our `User.OnInsert` callback: if the user is online, print a notification.
|
||||||
|
// void User_OnInsert(EventContext ctx, User insertedValue)
|
||||||
|
// {
|
||||||
|
// if (insertedValue.Online)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"{UserNameOrIdentity(insertedValue)} is online");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /// Our `User.OnUpdate` callback:
|
||||||
|
// /// print a notification about name and status changes.
|
||||||
|
// void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
|
||||||
|
// {
|
||||||
|
// if (oldValue.Name != newValue.Name)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"{UserNameOrIdentity(oldValue)} renamed to {newValue.Name}");
|
||||||
|
// }
|
||||||
|
// if (oldValue.Online != newValue.Online)
|
||||||
|
// {
|
||||||
|
// if (newValue.Online)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"{UserNameOrIdentity(newValue)} connected.");
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"{UserNameOrIdentity(newValue)} disconnected.");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
1
client/spacetime/Program.cs.uid
Normal file
1
client/spacetime/Program.cs.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dtnd8t4orjlip
|
||||||
Loading…
Add table
Reference in a new issue