fix: multiple bugs
* Hard-refresh saves coords before disconnect * Position persisted between sessions * Scaling isn't assumed on initial, it waits for calculations to finish
This commit is contained in:
parent
a96581cbf0
commit
98f38c9714
3 changed files with 99 additions and 8 deletions
|
|
@ -8,16 +8,31 @@ use chattyness_error::AppError;
|
|||
|
||||
/// Join a channel as an authenticated user.
|
||||
///
|
||||
/// Creates a channel_members entry with default position (400, 300).
|
||||
/// Restores the user's last position if they were previously in the same scene,
|
||||
/// otherwise uses the default position (400, 300).
|
||||
/// Note: channel_id is actually scene_id in this system (scenes are used directly as channels).
|
||||
pub async fn join_channel<'e>(
|
||||
executor: impl PgExecutor<'e>,
|
||||
channel_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> Result<ChannelMember, AppError> {
|
||||
// Note: channel_id is actually scene_id in this system
|
||||
let member = sqlx::query_as::<_, ChannelMember>(
|
||||
r#"
|
||||
INSERT INTO realm.channel_members (channel_id, user_id, position)
|
||||
VALUES ($1, $2, ST_SetSRID(ST_MakePoint(400, 300), 0))
|
||||
SELECT $1, $2, COALESCE(
|
||||
-- Try to restore last position if user was in the same scene
|
||||
-- Note: channel_id = scene_id in this system
|
||||
(SELECT m.last_position
|
||||
FROM realm.memberships m
|
||||
JOIN realm.scenes s ON s.id = $1
|
||||
WHERE m.user_id = $2
|
||||
AND m.realm_id = s.realm_id
|
||||
AND m.last_scene_id = $1
|
||||
AND m.last_position IS NOT NULL),
|
||||
-- Default position
|
||||
ST_SetSRID(ST_MakePoint(400, 300), 0)
|
||||
)
|
||||
ON CONFLICT (channel_id, user_id) DO UPDATE
|
||||
SET joined_at = now()
|
||||
RETURNING
|
||||
|
|
@ -67,13 +82,40 @@ pub async fn ensure_active_avatar<'e>(
|
|||
}
|
||||
|
||||
/// Leave a channel.
|
||||
///
|
||||
/// Saves the user's current position to memberships.last_position before removing them.
|
||||
/// Note: channel_id is actually scene_id in this system (scenes are used directly as channels).
|
||||
pub async fn leave_channel<'e>(
|
||||
executor: impl PgExecutor<'e>,
|
||||
channel_id: Uuid,
|
||||
user_id: Uuid,
|
||||
) -> Result<(), AppError> {
|
||||
// Use data-modifying CTEs with RETURNING to ensure all CTEs execute
|
||||
// Note: channel_id is actually scene_id in this system
|
||||
sqlx::query(
|
||||
r#"DELETE FROM realm.channel_members WHERE channel_id = $1 AND user_id = $2"#,
|
||||
r#"
|
||||
WITH member_info AS (
|
||||
SELECT cm.position, cm.channel_id as scene_id, s.realm_id
|
||||
FROM realm.channel_members cm
|
||||
JOIN realm.scenes s ON cm.channel_id = s.id
|
||||
WHERE cm.channel_id = $1 AND cm.user_id = $2
|
||||
),
|
||||
save_position AS (
|
||||
UPDATE realm.memberships m
|
||||
SET last_position = mi.position,
|
||||
last_scene_id = mi.scene_id,
|
||||
last_visited_at = now()
|
||||
FROM member_info mi
|
||||
WHERE m.realm_id = mi.realm_id AND m.user_id = $2
|
||||
RETURNING m.user_id
|
||||
),
|
||||
do_delete AS (
|
||||
DELETE FROM realm.channel_members
|
||||
WHERE channel_id = $1 AND user_id = $2
|
||||
RETURNING user_id
|
||||
)
|
||||
SELECT COUNT(*) FROM save_position, do_delete
|
||||
"#,
|
||||
)
|
||||
.bind(channel_id)
|
||||
.bind(user_id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue