diff --git a/src/public.rs b/src/public.rs index eea7ae3..6f9816c 100644 --- a/src/public.rs +++ b/src/public.rs @@ -301,13 +301,10 @@ async fn portal_media_view( ) -> cot::Result { let media_id = media.id.unwrap(); let delivery = crate::uploads::media_delivery_paths(&media.file_type, &media.file_path); - let url = storage - .public_url( - &delivery.media_path, - format!("/client/{client_token}/media/{media_id}"), - ) - .await - .map_err(crate::uploads::storage_error)?; + // Always route full-size opens through our handler so the view is counted + // even with R2 storage (the handler records the event, then redirects to the + // signed URL). Thumbnails are still served directly and are not counted. + let url = format!("/client/{client_token}/media/{media_id}"); let thumbnail_fallback = format!("/client/{client_token}/media/{media_id}/thumbnail"); let thumbnail_url = if storage.is_r2() && storage