consolidate more tables
This commit is contained in:
@@ -135,15 +135,11 @@ pub fn on_disconnect(ctx: &ReducerContext) {
|
||||
|
||||
sync_server_member_info(&ctx.db, ctx.sender());
|
||||
|
||||
if let Some(vs) = ctx.db.voice_state().identity().find(ctx.sender()) {
|
||||
ctx.db.voice_state().delete(vs);
|
||||
}
|
||||
|
||||
if let Some(ta) = ctx.db.typing_activity().identity().find(ctx.sender()) {
|
||||
ctx.db.typing_activity().delete(ta);
|
||||
}
|
||||
|
||||
clear_signaling_for_user(&ctx.db, ctx.sender());
|
||||
clear_user_presence(&ctx.db, ctx.sender());
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
|
||||
+41
-69
@@ -8,13 +8,13 @@ pub fn set_typing(ctx: &ReducerContext, channel_id: u64, typing: bool) {
|
||||
ctx.db.typing_activity().identity().update(TypingActivity {
|
||||
identity: ctx.sender(),
|
||||
channel_id,
|
||||
is_typing: typing,
|
||||
typing: typing,
|
||||
});
|
||||
} else {
|
||||
ctx.db.typing_activity().insert(TypingActivity {
|
||||
identity: ctx.sender(),
|
||||
channel_id,
|
||||
is_typing: typing,
|
||||
typing: typing,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -465,23 +465,6 @@ pub fn extend_subscription(ctx: &ReducerContext, channel_id: u64, earliest_seq_i
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn set_talking(ctx: &ReducerContext, talking: bool, channel_id: u64) {
|
||||
if let Some(_) = ctx.db.voice_activity().identity().find(ctx.sender()) {
|
||||
ctx.db.voice_activity().identity().update(VoiceActivity {
|
||||
identity: ctx.sender(),
|
||||
channel_id,
|
||||
is_talking: talking,
|
||||
});
|
||||
} else {
|
||||
ctx.db.voice_activity().insert(VoiceActivity {
|
||||
identity: ctx.sender(),
|
||||
channel_id,
|
||||
is_talking: talking,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn create_server(ctx: &ReducerContext, name: String) {
|
||||
validate_name(&name).expect("Invalid name");
|
||||
@@ -660,44 +643,42 @@ pub fn join_voice(ctx: &ReducerContext, channel_id: u64) {
|
||||
panic!("Invalid voice channel");
|
||||
}
|
||||
|
||||
if let Some(existing) = ctx.db.voice_state().identity().find(ctx.sender()) {
|
||||
if existing.channel_id != channel_id {
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
if state.channel_id != channel_id {
|
||||
clear_signaling_for_user(&ctx.db, ctx.sender());
|
||||
ctx.db.voice_state().identity().update(VoiceState {
|
||||
identity: ctx.sender(),
|
||||
channel_id,
|
||||
is_sharing_screen: false,
|
||||
is_muted: false,
|
||||
is_deafened: false,
|
||||
});
|
||||
state.channel_id = channel_id;
|
||||
state.is_sharing_screen = false;
|
||||
state.is_talking = false;
|
||||
state.watching = None;
|
||||
ctx.db.user_state().identity().update(state);
|
||||
}
|
||||
} else {
|
||||
ctx.db.voice_state().insert(VoiceState {
|
||||
ctx.db.user_state().insert(UserState {
|
||||
identity: ctx.sender(),
|
||||
channel_id,
|
||||
is_sharing_screen: false,
|
||||
is_muted: false,
|
||||
is_deafened: false,
|
||||
is_talking: false,
|
||||
watching: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn set_sharing_screen(ctx: &ReducerContext, sharing: bool) {
|
||||
if let Some(mut state) = ctx.db.voice_state().identity().find(ctx.sender()) {
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
state.is_sharing_screen = sharing;
|
||||
ctx.db.voice_state().identity().update(state);
|
||||
ctx.db.user_state().identity().update(state);
|
||||
|
||||
if !sharing {
|
||||
let watching: Vec<_> = ctx
|
||||
.db
|
||||
.watching()
|
||||
.watchee()
|
||||
.filter(ctx.sender())
|
||||
.map(|w| w.id)
|
||||
// Clean up watching state for people watching ME
|
||||
let watchers: Vec<_> = ctx.db.user_state().iter()
|
||||
.filter(|s| s.watching == Some(ctx.sender()))
|
||||
.collect();
|
||||
for id in watching {
|
||||
ctx.db.watching().id().delete(id);
|
||||
for mut w in watchers {
|
||||
w.watching = None;
|
||||
ctx.db.user_state().identity().update(w);
|
||||
}
|
||||
|
||||
let signals: Vec<_> = ctx
|
||||
@@ -717,60 +698,51 @@ pub fn set_sharing_screen(ctx: &ReducerContext, sharing: bool) {
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn set_mute(ctx: &ReducerContext, muted: bool) {
|
||||
if let Some(mut state) = ctx.db.voice_state().identity().find(ctx.sender()) {
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
state.is_muted = muted;
|
||||
ctx.db.voice_state().identity().update(state);
|
||||
ctx.db.user_state().identity().update(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn set_deafen(ctx: &ReducerContext, deafened: bool) {
|
||||
if let Some(mut state) = ctx.db.voice_state().identity().find(ctx.sender()) {
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
state.is_deafened = deafened;
|
||||
ctx.db.voice_state().identity().update(state);
|
||||
ctx.db.user_state().identity().update(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn start_watching(ctx: &ReducerContext, watchee: Identity, channel_id: u64) {
|
||||
pub fn set_talking(ctx: &ReducerContext, talking: bool) {
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
state.is_talking = talking;
|
||||
ctx.db.user_state().identity().update(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn start_watching(ctx: &ReducerContext, watchee: Identity) {
|
||||
if ctx.sender() == watchee {
|
||||
return;
|
||||
}
|
||||
|
||||
for w in ctx.db.watching().watcher().filter(ctx.sender()) {
|
||||
if w.watchee == watchee {
|
||||
return;
|
||||
}
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
state.watching = Some(watchee);
|
||||
ctx.db.user_state().identity().update(state);
|
||||
}
|
||||
ctx.db.watching().insert(Watching {
|
||||
id: 0,
|
||||
watcher: ctx.sender(),
|
||||
watchee,
|
||||
channel_id,
|
||||
});
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn stop_watching(ctx: &ReducerContext, watchee: Identity) {
|
||||
let to_delete: Vec<_> = ctx
|
||||
.db
|
||||
.watching()
|
||||
.watcher()
|
||||
.filter(ctx.sender())
|
||||
.filter(|w| w.watchee == watchee)
|
||||
.map(|w| w.id)
|
||||
.collect();
|
||||
for id in to_delete {
|
||||
ctx.db.watching().id().delete(id);
|
||||
pub fn stop_watching(ctx: &ReducerContext) {
|
||||
if let Some(mut state) = ctx.db.user_state().identity().find(ctx.sender()) {
|
||||
state.watching = None;
|
||||
ctx.db.user_state().identity().update(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn leave_voice(ctx: &ReducerContext) {
|
||||
if let Some(_) = ctx.db.voice_state().identity().find(ctx.sender()) {
|
||||
ctx.db.voice_state().identity().delete(ctx.sender());
|
||||
}
|
||||
clear_signaling_for_user(&ctx.db, ctx.sender());
|
||||
clear_user_presence(&ctx.db, ctx.sender());
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
|
||||
@@ -87,9 +87,9 @@ pub struct DirectMessage {
|
||||
#[index(btree)]
|
||||
pub is_open_recipient: bool,
|
||||
}
|
||||
|
||||
#[spacetimedb::table(accessor = voice_state, public)]
|
||||
pub struct VoiceState {
|
||||
#[spacetimedb::table(accessor = user_state)]
|
||||
#[derive(Clone)]
|
||||
pub struct UserState {
|
||||
#[primary_key]
|
||||
pub identity: Identity,
|
||||
#[index(btree)]
|
||||
@@ -97,28 +97,8 @@ pub struct VoiceState {
|
||||
pub is_sharing_screen: bool,
|
||||
pub is_muted: bool,
|
||||
pub is_deafened: bool,
|
||||
}
|
||||
|
||||
#[spacetimedb::table(accessor = voice_activity, public)]
|
||||
pub struct VoiceActivity {
|
||||
#[primary_key]
|
||||
pub identity: Identity,
|
||||
#[index(btree)]
|
||||
pub channel_id: u64,
|
||||
pub is_talking: bool,
|
||||
}
|
||||
|
||||
#[spacetimedb::table(accessor = watching, public)]
|
||||
pub struct Watching {
|
||||
#[primary_key]
|
||||
#[auto_inc]
|
||||
pub id: u64,
|
||||
#[index(btree)]
|
||||
pub watcher: Identity,
|
||||
#[index(btree)]
|
||||
pub watchee: Identity,
|
||||
#[index(btree)]
|
||||
pub channel_id: u64,
|
||||
pub watching: Option<Identity>,
|
||||
}
|
||||
|
||||
#[derive(spacetimedb::SpacetimeType, Clone, Copy, Debug, PartialEq)]
|
||||
@@ -128,6 +108,7 @@ pub enum SignalKind {
|
||||
IceCandidate,
|
||||
}
|
||||
|
||||
|
||||
#[derive(spacetimedb::SpacetimeType, Clone, Copy, Debug, PartialEq)]
|
||||
pub enum MediaType {
|
||||
Voice,
|
||||
@@ -226,14 +207,17 @@ pub struct Image {
|
||||
}
|
||||
|
||||
#[spacetimedb::table(accessor = typing_activity, public)]
|
||||
#[derive(Clone)]
|
||||
pub struct TypingActivity {
|
||||
#[primary_key]
|
||||
#[index(btree)]
|
||||
pub identity: Identity,
|
||||
#[index(btree)]
|
||||
pub channel_id: u64,
|
||||
pub is_typing: bool,
|
||||
pub typing: bool,
|
||||
}
|
||||
|
||||
|
||||
#[spacetimedb::table(accessor = recent_message)]
|
||||
pub struct RecentMessage {
|
||||
#[primary_key]
|
||||
|
||||
@@ -265,20 +265,6 @@ pub fn get_visible_image_ids_read_only(db: &LocalReadOnly, identity: Identity) -
|
||||
}
|
||||
|
||||
pub fn clear_signaling_for_user(db: &Local, identity: Identity) {
|
||||
if let Some(va) = db.voice_activity().identity().find(identity) {
|
||||
db.voice_activity().delete(va);
|
||||
}
|
||||
|
||||
let watchers: Vec<_> = db.watching().watcher().filter(identity).collect();
|
||||
for row in watchers {
|
||||
db.watching().delete(row);
|
||||
}
|
||||
|
||||
let watchees: Vec<_> = db.watching().watchee().filter(identity).collect();
|
||||
for row in watchees {
|
||||
db.watching().delete(row);
|
||||
}
|
||||
|
||||
for row in db
|
||||
.webrtc_signal()
|
||||
.sender()
|
||||
@@ -297,6 +283,13 @@ pub fn clear_signaling_for_user(db: &Local, identity: Identity) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_user_presence(db: &Local, identity: Identity) {
|
||||
if let Some(state) = db.user_state().identity().find(identity) {
|
||||
db.user_state().delete(state);
|
||||
}
|
||||
clear_signaling_for_user(db, identity);
|
||||
}
|
||||
|
||||
pub fn auto_join_community_server(db: &Local, identity: Identity) {
|
||||
let community_server = db.server().name().filter(&"Zep".to_string()).next();
|
||||
if let Some(s) = community_server {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::tables::*;
|
||||
use crate::utils::*;
|
||||
use spacetimedb::{Identity, Query, Timestamp, ViewContext};
|
||||
use spacetimedb::{Identity, Query, Table, Timestamp, ViewContext};
|
||||
|
||||
#[derive(spacetimedb::SpacetimeType)]
|
||||
pub struct VisibleImageRow {
|
||||
@@ -27,6 +27,40 @@ pub struct VisibleMessageRow {
|
||||
pub is_encrypted: bool,
|
||||
}
|
||||
|
||||
#[spacetimedb::view(accessor = visible_typing_activity, public)]
|
||||
pub fn visible_typing_activity(ctx: &ViewContext) -> Vec<TypingActivity> {
|
||||
let identity = ctx.sender();
|
||||
let mut results = Vec::new();
|
||||
|
||||
// 1. Server channels
|
||||
for member in ctx.db.server_member().identity().filter(identity) {
|
||||
if let Some(s) = ctx.db.server().id().find(member.server_id) {
|
||||
for chan_meta in s.channels {
|
||||
for activity in ctx.db.typing_activity().channel_id().filter(chan_meta.id) {
|
||||
results.push(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. DM channels
|
||||
let mut dm_channel_ids = Vec::new();
|
||||
for dm in ctx.db.direct_message().sender().filter(identity) {
|
||||
dm_channel_ids.push(dm.channel_id);
|
||||
}
|
||||
for dm in ctx.db.direct_message().recipient().filter(identity) {
|
||||
dm_channel_ids.push(dm.channel_id);
|
||||
}
|
||||
|
||||
for channel_id in dm_channel_ids {
|
||||
for activity in ctx.db.typing_activity().channel_id().filter(channel_id) {
|
||||
results.push(activity);
|
||||
}
|
||||
}
|
||||
|
||||
results
|
||||
}
|
||||
|
||||
#[derive(spacetimedb::SpacetimeType)]
|
||||
pub struct MyChannelSubscriptionRow {
|
||||
pub identity: Identity,
|
||||
@@ -226,6 +260,42 @@ pub fn visible_images(ctx: &ViewContext) -> Vec<VisibleImageRow> {
|
||||
results
|
||||
}
|
||||
|
||||
#[spacetimedb::view(accessor = visible_user_states, public)]
|
||||
pub fn visible_user_states(ctx: &ViewContext) -> Vec<UserState> {
|
||||
let identity = ctx.sender();
|
||||
let mut results = std::collections::HashMap::new();
|
||||
|
||||
// 1. My own state
|
||||
if let Some(my_state) = ctx.db.user_state().identity().find(identity) {
|
||||
results.insert(my_state.identity, my_state.clone());
|
||||
}
|
||||
|
||||
// 2. States in my servers
|
||||
for member in ctx.db.server_member().identity().filter(identity) {
|
||||
if let Some(s) = ctx.db.server().id().find(member.server_id) {
|
||||
for chan_meta in s.channels {
|
||||
for state in ctx.db.user_state().channel_id().filter(chan_meta.id) {
|
||||
results.insert(state.identity, state.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. States in my DMs
|
||||
for dm in ctx.db.direct_message().sender().filter(identity) {
|
||||
for state in ctx.db.user_state().channel_id().filter(dm.channel_id) {
|
||||
results.insert(state.identity, state.clone());
|
||||
}
|
||||
}
|
||||
for dm in ctx.db.direct_message().recipient().filter(identity) {
|
||||
for state in ctx.db.user_state().channel_id().filter(dm.channel_id) {
|
||||
results.insert(state.identity, state.clone());
|
||||
}
|
||||
}
|
||||
|
||||
results.into_values().collect()
|
||||
}
|
||||
|
||||
#[spacetimedb::view(accessor = visible_webrtc_signals, public)]
|
||||
pub fn visible_webrtc_signals(ctx: &ViewContext) -> Vec<WebRTCSignal> {
|
||||
let identity = ctx.sender();
|
||||
|
||||
Reference in New Issue
Block a user