From 853a827f3594e7f04a708493bccdef51b3bbefc0 Mon Sep 17 00:00:00 2001
From: Komal <157946119+komal-rs@users.noreply.github.com>
Date: Mon, 8 Apr 2024 22:52:57 +0530
Subject: [PATCH] cpu usage improvements (#186)

* cpu usage improvements

* cargo fix
---
 .gitignore                         |   5 +-
 src/page/post_view/video_iter.rs   |   2 +-
 src/page/post_view/video_loader.rs | 132 ++++++++++++++++-------------
 3 files changed, 77 insertions(+), 62 deletions(-)

diff --git a/.gitignore b/.gitignore
index 394a48ea..aa48780b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,7 @@ playwright/.cache/
 redb-kv.db
 
 # dotenv
-.env
\ No newline at end of file
+.env
+
+# ide config
+.idea/
\ No newline at end of file
diff --git a/src/page/post_view/video_iter.rs b/src/page/post_view/video_iter.rs
index 8637feb6..d7077e77 100644
--- a/src/page/post_view/video_iter.rs
+++ b/src/page/post_view/video_iter.rs
@@ -33,7 +33,7 @@ impl Default for FetchCursor {
 impl FetchCursor {
     pub fn advance(&mut self) {
         self.start += self.limit;
-        self.limit = 50;
+        self.limit = 25;
     }
 }
 
diff --git a/src/page/post_view/video_loader.rs b/src/page/post_view/video_loader.rs
index b881c1b4..5b6c8a9d 100644
--- a/src/page/post_view/video_loader.rs
+++ b/src/page/post_view/video_loader.rs
@@ -1,4 +1,11 @@
-use super::{overlay::VideoDetailsOverlay, PostViewCtx};
+use std::cmp::Ordering;
+
+use leptos::{html::Video, *};
+use leptos_use::use_event_listener;
+use serde_json::json;
+use wasm_bindgen::JsCast;
+
+use crate::utils::event_streaming::send_event;
 use crate::{
     canister::{
         individual_user_template::PostViewDetailsFromFrontend,
@@ -12,12 +19,8 @@ use crate::{
     },
     utils::event_streaming::send_event_warehouse,
 };
-use leptos::{html::Video, *};
-use leptos_use::{use_event_listener, watch_debounced};
 
-use crate::utils::event_streaming::send_event;
-use serde_json::json;
-use wasm_bindgen::JsCast;
+use super::{overlay::VideoDetailsOverlay, PostViewCtx};
 
 #[component]
 pub fn BgView(idx: usize, children: Children) -> impl IntoView {
@@ -120,74 +123,85 @@ pub fn VideoView(idx: usize, muted: RwSignal<bool>) -> impl IntoView {
         Some(())
     });
 
-    let watched_percentage = create_rw_signal(0_u8);
-    let watched_count = create_rw_signal(0_u8);
+    // Video views send to canister
+    // 1. When video is paused (as in scrolled away) -> partial video view
+    // 2. When video is 95% done -> full view
+
+    let post = Signal::derive(move || video_queue.with(|q| q.get(idx).cloned()));
+
+    let send_view_detail_action =
+        create_action(move |(percentage_watched, watch_count): &(u8, u8)| {
+            let percentage_watched = *percentage_watched;
+            let watch_count = *watch_count;
+
+            async move {
+                let canisters = unauth_canisters();
+
+                let payload = match percentage_watched.cmp(&95) {
+                    Ordering::Less => {
+                        PostViewDetailsFromFrontend::WatchedPartially { percentage_watched }
+                    }
+                    _ => PostViewDetailsFromFrontend::WatchedMultipleTimes {
+                        percentage_watched,
+                        watch_count,
+                    },
+                };
+
+                let post_id = post.get_untracked().as_ref().map(|p| p.post_id).unwrap();
+                let canister_id = post
+                    .get_untracked()
+                    .as_ref()
+                    .map(|p| p.canister_id)
+                    .unwrap();
+                let send_view_res = canisters
+                    .individual_user(canister_id)
+                    .update_post_add_view_details(post_id, payload)
+                    .await;
+
+                if let Err(err) = send_view_res {
+                    log::warn!("failed to send view details: {:?}", err);
+                }
+                Some(())
+            }
+        });
+
+    let video_views_watch_multiple = create_rw_signal(false);
 
-    let video_previous_current_time = store_value(0.0);
-    let _ = use_event_listener(container_ref, ev::timeupdate, move |_event| {
+    let _ = use_event_listener(container_ref, ev::pause, move |_evt| {
         let Some(video) = container_ref() else {
             return;
         };
 
         let duration = video.duration();
         let current_time = video.current_time();
-
-        if current_time < video_previous_current_time() {
-            watched_count.update(|wc| *wc += 1);
+        if current_time < 0.5 {
+            return;
         }
-        watched_percentage.update(|watched_percentage| {
-            *watched_percentage = (100.0 * (current_time / duration)) as u8;
-        });
 
-        video_previous_current_time.update_value(|v| *v = current_time);
+        let percentage_watched = ((current_time / duration) * 100.0) as u8;
+        send_view_detail_action.dispatch((percentage_watched, 0_u8));
     });
 
-    let post = Signal::derive(move || video_queue.with(|q| q.get(idx).cloned()));
-
-    let send_view_detail_action = create_action(move |()| async move {
-        let canisters = unauth_canisters();
-        let current_watched_percentage = watched_percentage.get_untracked();
-        let current_watched_count = watched_count.get_untracked();
-        let payload = match current_watched_count {
-            0 => PostViewDetailsFromFrontend::WatchedPartially {
-                percentage_watched: current_watched_percentage,
-            },
-            _ => PostViewDetailsFromFrontend::WatchedMultipleTimes {
-                percentage_watched: current_watched_percentage,
-                watch_count: current_watched_count,
-            },
+    let _ = use_event_listener(container_ref, ev::timeupdate, move |_evt| {
+        let Some(video) = container_ref() else {
+            return;
         };
-        watched_count.update(|wc| *wc = 0);
-        watched_percentage.update(|watched_percentage| *watched_percentage = 0);
-        let post_id = post.get_untracked().as_ref().map(|p| p.post_id).unwrap();
-        let canister_id = post
-            .get_untracked()
-            .as_ref()
-            .map(|p| p.canister_id)
-            .unwrap();
-        let send_view_res = canisters
-            .individual_user(canister_id)
-            .update_post_add_view_details(post_id, payload)
-            .await;
-
-        if let Err(err) = send_view_res {
-            log::warn!("failed to send view details: {:?}", err);
+
+        let duration = video.duration();
+        let current_time = video.current_time();
+        let percentage_watched = ((current_time / duration) * 100.0) as u8;
+
+        if current_time < 0.95 * duration {
+            video_views_watch_multiple.set(false);
         }
-    });
 
-    let send_view_details_guard = create_memo(move |_| {
-        current_idx() != idx && (watched_percentage() != 0 || watched_count() != 0)
+        if percentage_watched >= 95 && !video_views_watch_multiple.get() {
+            send_view_detail_action.dispatch((percentage_watched, 0_u8));
+
+            video_views_watch_multiple.set(true);
+        }
     });
 
-    let _ = watch_debounced(
-        watched_percentage,
-        move |_, _, _| {
-            if send_view_details_guard() {
-                send_view_detail_action.dispatch(());
-            }
-        },
-        2000.0,
-    );
     #[cfg(all(feature = "hydrate", feature = "ga4"))]
     {
         let profile_and_canister_details: AuthProfileCanisterResource = expect_context();
@@ -264,8 +278,6 @@ pub fn VideoView(idx: usize, muted: RwSignal<bool>) -> impl IntoView {
             }
 
             if current_time >= 3.0 {
-                // Video is halfway done, take action here
-
                 send_event(
                     "video_viewed",
                     &json!({