Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ios player v2 #1901

Merged
merged 7 commits into from
Feb 22, 2024
Merged

Ios player v2 #1901

merged 7 commits into from
Feb 22, 2024

Conversation

nick-delirium
Copy link
Contributor

@nick-delirium nick-delirium commented Feb 22, 2024

Summary by CodeRabbit

  • New Features
    • Enhanced user interaction with historical data by introducing snapshot viewing capability in the mobile player.
    • Enabled efficient data handling and storage by adding support for unpacking and processing tarball files.
    • Improved content accessibility with dynamic video and snapshot mode switching based on session data.
  • Enhancements
    • Improved mobile player styling and scaling for a better user experience.
    • Enhanced performance tracking with additional warnings and frustrations logging for user experience optimization.
  • Bug Fixes
    • Ensured smoother data processing by fixing syntax issues in unpacking logic.
  • Documentation
    • Added and updated comments for clearer code comprehension and maintenance.

Copy link

coderabbitai bot commented Feb 22, 2024

Warning

Rate Limit Exceeded

@nick-delirium has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 13 minutes and 42 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.
Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.
Please see our FAQ for further information.

Commits Files that changed from the base of the PR and between 77b1c69 and 02b174e.

Walkthrough

The recent updates focus on enhancing the mobile player's functionality in a web application. Key improvements include handling video and snapshot modes, unpacking tarball files, and updating UI components for a better mobile experience. The introduction of PlayerMode allows for conditional rendering and functionality, while new utility functions and classes manage tar files and snapshots efficiently. These changes aim to provide a smoother and more versatile user experience across different playback modes.

Changes

Files Summary
.../MobilePlayer/ReplayWindow.tsx Introduced PlayerMode, added imageRef, new useEffect hooks, updated component logic, and added styling functions.
.../common/common.d.ts, .../common/tarball.ts Added module and function for handling tar files with js-untar.
.../common/types.ts, .../common/unpack.ts Added videoURL property and updated unpack function.
.../mobile/IOSMessageManager.ts, .../mobile/IOSPlayer.ts Enhanced mobile player with PlayerMode, snapshot management, and updated event handling.
.../mobile/managers/SnapshotManager.ts Introduced SnapshotManager for snapshot handling.
.../web/MessageLoader.ts, .../web/network/loadFiles.ts Added tarball loading functionality and updated file fetching methods.

🐰✨
In the land of code and sun,
Changes big and small, all done.
With snapshots, tar, and video play,
Our mobile player finds its way.
So hop along, my friends, let's see,
A world of code, where we're free.
🌟🐇

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

socket-security bot commented Feb 22, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@commitlint/config-conventional@17.8.1 None 0 9.61 kB escapedcat
npm/@evilmartians/lefthook@1.6.1 environment, shell 0 61.2 MB mrexox
npm/@react-native/eslint-config@0.72.2 Transitive: environment, filesystem, unsafe +16 5.49 MB react-native-bot
npm/@release-it/conventional-changelog@5.1.1 filesystem +1 113 kB webpro
npm/@types/jest@28.1.8 None 0 73.6 kB types
npm/@types/react-native@0.70.0 None +3 571 kB types
npm/@types/react@17.0.75 None +2 182 kB types

🚮 Removed packages: npm/@alloc/quick-lru@5.2.0, npm/@ant-design/colors@7.0.2, npm/@ant-design/cssinjs@1.18.4, npm/@ant-design/icons-svg@4.4.2, npm/@ant-design/icons@5.3.0, npm/@ant-design/react-slick@1.0.2, npm/@apideck/better-ajv-errors@0.3.6, npm/@babel/cli@7.23.9, npm/@babel/helper-define-polyfill-provider@0.1.5, npm/@babel/node@7.23.9, npm/@babel/plugin-proposal-decorators@7.23.9, npm/@babel/plugin-proposal-private-methods@7.18.6, npm/@babel/plugin-syntax-decorators@7.23.3, npm/@babel/plugin-transform-react-constant-elements@7.23.3, npm/@base2/pretty-print-object@1.0.1, npm/@cnakazawa/watch@1.0.4, npm/@colors/colors@1.5.0, npm/@csstools/selector-specificity@2.2.0, npm/@ctrl/tinycolor@3.6.1, npm/@cypress/request@3.0.1, npm/@cypress/xvfb@1.2.4, npm/@design-systems/utils@2.12.0, npm/@devtools-ds/object-inspector@1.2.1, npm/@devtools-ds/object-parser@1.2.1, npm/@devtools-ds/themes@1.2.1, npm/@devtools-ds/tree@1.2.1, npm/@discoveryjs/json-ext@0.5.7, npm/@emotion/babel-plugin@11.11.0, npm/@emotion/cache@11.11.0, npm/@emotion/hash@0.8.0, npm/@emotion/memoize@0.8.1, npm/@emotion/react@11.11.3, npm/@emotion/serialize@1.1.3, npm/@emotion/sheet@1.2.2, npm/@emotion/unitless@0.7.5, npm/@emotion/use-insertion-effect-with-fallbacks@1.0.1, npm/@emotion/utils@1.2.1, npm/@emotion/weak-memoize@0.3.1, npm/@floating-ui/core@1.6.0, npm/@floating-ui/dom@1.6.3, npm/@floating-ui/react-dom-interactions@0.10.3, npm/@floating-ui/react-dom@1.3.0, npm/@floating-ui/utils@0.2.1, npm/@fluentui/react-component-event-listener@0.63.1, npm/@fluentui/react-component-ref@0.63.1, npm/@gar/promisify@1.1.3, npm/@iarna/cli@2.1.0, npm/@isaacs/cliui@8.0.2, npm/@jest/console@29.7.0, npm/@jest/core@29.7.0, npm/@jest/environment@29.7.0, npm/@jest/expect-utils@29.7.0, npm/@jest/expect@29.7.0, npm/@jest/fake-timers@29.7.0, npm/@jest/globals@29.7.0, npm/@jest/reporters@29.7.0, npm/@jest/source-map@26.6.2, npm/@jest/test-result@29.7.0, npm/@jest/test-sequencer@29.7.0, npm/@jest/transform@26.6.2, npm/@leichtgewicht/ip-codec@2.0.4, npm/@mdx-js/mdx@1.6.22, npm/@mdx-js/react@1.6.22, npm/@mdx-js/util@1.6.22, npm/@mrmlnc/readdir-enhanced@2.2.1, npm/@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3, npm/@nodelib/fs.stat@1.1.3, npm/@npmcli/agent@2.2.0, npm/@npmcli/fs@1.1.1, npm/@npmcli/move-file@1.1.2, npm/@openreplay/sourcemap-uploader@3.0.8, npm/@pkgjs/parseargs@0.11.0, npm/@pmmmwh/react-refresh-webpack-plugin@0.5.11, npm/@polka/url@1.0.0-next.23, npm/@popperjs/core@2.11.8, npm/@rc-component/color-picker@1.5.2, npm/@rc-component/context@1.4.0, npm/@rc-component/mini-decimal@1.1.0, npm/@rc-component/mutate-observer@1.1.0, npm/@rc-component/portal@1.1.2, npm/@rc-component/tour@1.12.3, npm/@rc-component/trigger@1.18.3, npm/@react-dnd/asap@5.0.2, npm/@react-dnd/invariant@4.0.2, npm/@react-dnd/shallowequal@4.0.2, npm/@rollup/plugin-node-resolve@11.2.1, npm/@rollup/plugin-replace@2.4.2, npm/@semantic-ui-react/event-stack@3.1.3, npm/@sentry/browser@5.30.0, npm/@sentry/core@5.30.0, npm/@sentry/hub@5.30.0, npm/@sentry/minimal@5.30.0, npm/@sentry/types@5.30.0, npm/@sentry/utils@5.30.0, npm/@sinonjs/commons@3.0.1, npm/@sinonjs/fake-timers@10.3.0, npm/@storybook/addon-actions@6.5.16, npm/@storybook/addon-backgrounds@6.5.16, npm/@storybook/addon-controls@6.5.16, npm/@storybook/addon-docs@6.5.16, npm/@storybook/addon-essentials@6.5.16, npm/@storybook/addon-interactions@6.5.16, npm/@storybook/addon-links@6.5.16, npm/@storybook/addon-measure@6.5.16, npm/@storybook/addon-outline@6.5.16, npm/@storybook/addon-toolbars@6.5.16, npm/@storybook/addon-viewport@6.5.16, npm/@storybook/addons@6.5.16, npm/@storybook/api@6.5.16, npm/@storybook/builder-webpack4@6.5.16, npm/@storybook/builder-webpack5@6.5.16, npm/@storybook/channel-postmessage@6.5.16, npm/@storybook/channel-websocket@6.5.16, npm/@storybook/channels@6.5.16, npm/@storybook/client-api@6.5.16, npm/@storybook/client-logger@6.5.16, npm/@storybook/components@6.5.16, npm/@storybook/core-client@6.5.16, npm/@storybook/core-common@6.5.16, npm/@storybook/core@6.5.16

View full report↗︎

Copy link

socket-security bot commented Feb 22, 2024

🚨 Potential security issues detected. Learn more about Socket for GitHub ↗︎

To accept the risk, merge this PR and you will not be notified again.

Alert Package NoteSource
Install scripts npm/@evilmartians/lefthook@1.6.1
  • Install script: postinstall
  • Source: node postinstall.js

View full report↗︎

Next steps

What is an install script?

Install scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.

Packages should not be running non-essential scripts during install and there are often solutions to problems people solve with install scripts that can be run at publish time instead.

Take a deeper look at the dependency

Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev.

Remove the package

If you happen to install a dependency that Socket reports as Known Malware you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency.

Mark a package as acceptable risk

To ignore an alert, reply with a comment starting with @SocketSecurity ignore followed by a space separated list of ecosystem/package-name@version specifiers. e.g. @SocketSecurity ignore npm/foo@1.0.0 or ignore all packages with @SocketSecurity ignore-all

  • @SocketSecurity ignore npm/@evilmartians/lefthook@1.6.1

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3cea5d7 and a8a23bb.
Files ignored due to path filters (2)
  • frontend/package.json is excluded by: !**/*.json
  • frontend/yarn.lock is excluded by: !**/*.lock
Files selected for processing (10)
  • frontend/app/components/Session/Player/MobilePlayer/ReplayWindow.tsx (2 hunks)
  • frontend/app/player/common/common.d.ts (1 hunks)
  • frontend/app/player/common/tarball.ts (1 hunks)
  • frontend/app/player/common/types.ts (1 hunks)
  • frontend/app/player/common/unpack.ts (1 hunks)
  • frontend/app/player/mobile/IOSMessageManager.ts (11 hunks)
  • frontend/app/player/mobile/IOSPlayer.ts (1 hunks)
  • frontend/app/player/mobile/managers/SnapshotManager.ts (1 hunks)
  • frontend/app/player/web/MessageLoader.ts (5 hunks)
  • frontend/app/player/web/network/loadFiles.ts (2 hunks)
Additional comments: 12
frontend/app/player/common/common.d.ts (1)
  • 2-10: The TypeScript definitions for the 'js-untar' module are correctly implemented, providing clear interfaces and function declarations for working with tar files.
frontend/app/player/common/types.ts (1)
  • 42-42: The addition of the videoURL property to the SessionFilesInfo interface is correctly implemented, enhancing the interface to include multiple video URLs.
frontend/app/player/mobile/IOSMessageManager.ts (10)
  • 2-2: Importing TarFile from "js-untar" introduces a dependency on the js-untar library for handling tar files. Ensure that this library is included in the project's dependencies and is compatible with the project's existing infrastructure.
  • 20-20: The addition of SnapshotManager from 'Player/mobile/managers/SnapshotManager' is crucial for managing snapshots. Verify that SnapshotManager is implemented correctly and efficiently handles snapshot data, especially in terms of memory management and performance.
  • 31-37: The expansion of performanceWarnings to include new warnings like 'lowDiskSpace' and 'isLowPowerModeEnabled' is a good practice for covering more performance-related issues. Ensure that these new warnings are properly documented and that their handling is consistent across the application.
  • 77-77: Adding currentSnapshot to the State interface with a type of TarFile | null is a significant change. It's important to ensure that all parts of the application that interact with the State object are updated to consider this new property. Additionally, consider if there are any nullability concerns or edge cases that need to be handled when currentSnapshot is null.
  • 133-140: The updates to the updateLists method to handle exceptions and frustrations differently show an attempt to refine the logic for updating lists. However, ensure that the method's error handling is robust, especially in cases where exceptions or frustrations might be undefined or have unexpected values.
  • 166-170: The onFileReadSuccess method's logic for updating state based on file read success is crucial for the application's data flow. Ensure that the method correctly handles all possible states and that the transition from waiting for files to having them processed is seamless and error-free.
  • 216-221: The handling of snapshots in the move method with the introduction of currentSnapshot state update is a significant feature. Ensure that the logic for determining when to update currentSnapshot is accurate and that it does not introduce performance issues, especially in scenarios with frequent timeline movements.
  • 237-250: The handling of iOS performance events in the distributeMessage method is well-structured. However, ensure that the mapping between message names and performance stats is comprehensive and that all relevant performance events are captured and processed correctly.
  • 285-285: The setMessagesLoading method's approach to updating the loading state and readiness of the screen is straightforward. However, ensure that the interplay between messagesLoading and cssLoading is clear and that there are no edge cases where the screen might incorrectly display its state.
  • 288-290: The setSize method correctly updates the screen scaling and state. Ensure that this method is called appropriately throughout the application to maintain a consistent and responsive UI, especially on iOS devices with varying screen sizes.

@@ -92,6 +109,7 @@ export default class IOSMessageManager implements IMessageManager {
private lastMessageTime: number = 0;
private touchManager: TouchManager;
private lists: Lists;
public snapshotManager: SnapshotManager;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introduction of snapshotManager as a public property of IOSMessageManager class indicates a design decision to allow external access to snapshot management functionalities. Ensure that this aligns with the class's responsibility and does not expose internal mechanisms unnecessarily. Consider encapsulating snapshot management within methods if direct access to snapshotManager is not required externally.

Consider encapsulating snapshot management functionalities within methods of IOSMessageManager to avoid direct external access to snapshotManager, enhancing encapsulation and potentially simplifying future refactoring.

}
this.state.update(newState);
};

public onFileReadFailed = (...e: any[]) => {
logger.error(e);
this.state.update({error: true});
this.state.update({ error: true });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onFileReadFailed method correctly updates the state to reflect an error condition. However, ensure that all possible error information is logged or handled appropriately to aid in debugging and user feedback.

Consider enhancing error logging in the onFileReadFailed method by including more detailed information about the failure, which could be beneficial for debugging purposes.

Comment on lines +3 to +22
const unpackTar = (data: Uint8Array): Promise<TarFile[]> => {
const isTar = true
// tarball ustar starts from 257, 75 73 74 61 72, but this is getting lost here for some reason
// so we rely on try catch
// data[257] === 0x75 &&
// data[258] === 0x73 &&
// data[259] === 0x74 &&
// data[260] === 0x61 &&
// data[261] === 0x72 &&
// data[262] === 0x00;

if (isTar) {
const now = performance.now();
return untar(data.buffer).then((files) => {
console.debug('Tar unpack time', Math.floor(performance.now() - now) + 'ms');
return files;
});
} else {
return Promise.reject('Not a tarball file');
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unpackTar function uses a hardcoded isTar boolean and includes comments about tarball identification that are not utilized. Consider removing these redundant parts or implementing actual validation logic for tarballs. Additionally, ensure that the performance measurement and promise-based structure are maintained for efficiency and clarity.

- const isTar = true
- // tarball ustar starts from 257, 75 73 74 61 72, but this is getting lost here for some reason
- // so we rely on try catch
-   // data[257] === 0x75 &&
-   // data[258] === 0x73 &&
-   // data[259] === 0x74 &&
-   // data[260] === 0x61 &&
-   // data[261] === 0x72 &&
-   // data[262] === 0x00;
+ // Implement actual validation logic for tarballs or clarify why it's omitted.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const unpackTar = (data: Uint8Array): Promise<TarFile[]> => {
const isTar = true
// tarball ustar starts from 257, 75 73 74 61 72, but this is getting lost here for some reason
// so we rely on try catch
// data[257] === 0x75 &&
// data[258] === 0x73 &&
// data[259] === 0x74 &&
// data[260] === 0x61 &&
// data[261] === 0x72 &&
// data[262] === 0x00;
if (isTar) {
const now = performance.now();
return untar(data.buffer).then((files) => {
console.debug('Tar unpack time', Math.floor(performance.now() - now) + 'ms');
return files;
});
} else {
return Promise.reject('Not a tarball file');
}
const unpackTar = (data: Uint8Array): Promise<TarFile[]> => {
// Implement actual validation logic for tarballs or clarify why it's omitted.
if (isTar) {
const now = performance.now();
return untar(data.buffer).then((files) => {
console.debug('Tar unpack time', Math.floor(performance.now() - now) + 'ms');
return files;
});
} else {
return Promise.reject('Not a tarball file');
}

Comment on lines +14 to +26
public mapToSnapshots(files: TarFile[]) {
const filenameRegexp = /(\d+)_1_(\d+)\.jpeg$/;
const firstPair = files[0].name.match(filenameRegexp)
const sessionStart = firstPair ? parseInt(firstPair[1], 10) : 0
files.forEach(file => {
const [_, _2, imageTimestamp] = file
.name
.match(filenameRegexp)
?.map(n => parseInt(n, 10)) ?? [0, 0, 0]
const messageTime = imageTimestamp - sessionStart
this.snapshots[messageTime] = file
this.append({ time: messageTime })
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the mapToSnapshots method, there's an issue with destructuring the file object directly instead of its name property. This could lead to incorrect parsing of filenames. Ensure that the filename is correctly extracted from the file object before applying the regular expression match.

- const [_, _2, imageTimestamp] = file
+ const [_, _2, imageTimestamp] = file.name

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
public mapToSnapshots(files: TarFile[]) {
const filenameRegexp = /(\d+)_1_(\d+)\.jpeg$/;
const firstPair = files[0].name.match(filenameRegexp)
const sessionStart = firstPair ? parseInt(firstPair[1], 10) : 0
files.forEach(file => {
const [_, _2, imageTimestamp] = file
.name
.match(filenameRegexp)
?.map(n => parseInt(n, 10)) ?? [0, 0, 0]
const messageTime = imageTimestamp - sessionStart
this.snapshots[messageTime] = file
this.append({ time: messageTime })
})
public mapToSnapshots(files: TarFile[]) {
const filenameRegexp = /(\d+)_1_(\d+)\.jpeg$/;
const firstPair = files[0].name.match(filenameRegexp)
const sessionStart = firstPair ? parseInt(firstPair[1], 10) : 0
files.forEach(file => {
const [_, _2, imageTimestamp] = file.name
.match(filenameRegexp)
?.map(n => parseInt(n, 10)) ?? [0, 0, 0]
const messageTime = imageTimestamp - sessionStart
this.snapshots[messageTime] = file
this.append({ time: messageTime })
})

Copy link

codecov bot commented Feb 22, 2024

Codecov Report

Attention: 161 lines in your changes are missing coverage. Please review.

Comparison is base (3ada6ae) 27.26% compared to head (77b1c69) 13.31%.
Report is 44 commits behind head on dev.

❗ Current head 77b1c69 differs from pull request most recent head 02b174e. Consider uploading reports for the commit 02b174e to get more accurate results

Files Patch % Lines
frontend/app/player/mobile/IOSPlayer.ts 0.00% 47 Missing and 3 partials ⚠️
frontend/app/player/mobile/IOSMessageManager.ts 0.00% 33 Missing and 1 partial ⚠️
frontend/app/player/web/MessageLoader.ts 0.00% 23 Missing and 1 partial ⚠️
...tend/app/player/mobile/managers/SnapshotManager.ts 0.00% 17 Missing and 1 partial ⚠️
frontend/app/player/common/unpack.ts 0.00% 12 Missing ⚠️
frontend/app/player/common/tarball.ts 0.00% 11 Missing ⚠️
frontend/app/player/web/network/loadFiles.ts 0.00% 10 Missing ⚠️
frontend/app/player/web/Screen/Screen.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##              dev    #1901       +/-   ##
===========================================
- Coverage   27.26%   13.31%   -13.95%     
===========================================
  Files          67      179      +112     
  Lines        5429    12799     +7370     
  Branches     1366     2732     +1366     
===========================================
+ Hits         1480     1704      +224     
- Misses       3543    10270     +6727     
- Partials      406      825      +419     
Flag Coverage Δ
tracker 27.10% <ø> (-0.16%) ⬇️
ui 3.05% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 6

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between a8a23bb and ce64e62.
Files selected for processing (4)
  • frontend/app/components/Session/Player/MobilePlayer/ReplayWindow.tsx (1 hunks)
  • frontend/app/player/mobile/IOSPlayer.ts (1 hunks)
  • frontend/app/player/web/MessageLoader.ts (5 hunks)
  • frontend/app/player/web/network/loadFiles.ts (2 hunks)
Files skipped from review as they are similar to previous changes (2)
  • frontend/app/player/web/MessageLoader.ts
  • frontend/app/player/web/network/loadFiles.ts
Additional comments: 6
frontend/app/player/mobile/IOSPlayer.ts (4)
  • 9-11: The introduction of the PlayerMode enum with VIDEO and SNAPS values is a good practice for managing different player modes. This approach enhances readability and maintainability by using meaningful constants instead of hard-coded strings.
  • 78-98: The updateLists method's logic for transforming event names and handling exceptions is a good example of data transformation in the application layer. However, ensure that the transformation rules (e.g., 'Click' to 'Touch') are documented and validated against all possible event types to avoid unexpected behavior.
  • 104-104: The updateOverlayStyle method correctly delegates the style update to the screen object. This encapsulation of screen-related operations within the screen object adheres to the Single Responsibility Principle.
  • 118-132: The scaling methods (scale and customScale) provide flexibility in adjusting the player size. It's important to ensure that these methods are called appropriately in response to relevant events (e.g., window resize, orientation change) to maintain the correct player size.
frontend/app/components/Session/Player/MobilePlayer/ReplayWindow.tsx (2)
  • 1-1: Importing the PlayerMode enum from 'Player' is a good practice for consistency and maintainability. It ensures that the component uses the same definitions as the rest of the application.
  • 142-158: The styling functions mobileLoadingBarStyle and mobileIconStyle are a clean way to separate styling logic from the component structure. This approach enhances the readability of the component and makes it easier to update styles in the future.

public screen: Screen
protected messageManager: IOSMessageManager
protected readonly messageLoader: MessageLoader
mode: null,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mode property is initialized as null in the INITIAL_STATE. It's important to ensure that all usages of mode properly handle the null case to avoid runtime errors. Consider initializing mode with a default value if applicable.

- mode: null,
+ mode: PlayerMode.VIDEO, // or another appropriate default value

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
mode: null,
mode: PlayerMode.VIDEO, // or another appropriate default value

Comment on lines 31 to 59
const hasTar = session.videoURL.some((url) => url.includes('.tar.'));
const screen = new Screen(true, ScaleMode.Embed);
const messageManager = new IOSMessageManager(session, wpState, screen, uiErrorHandler);
const messageLoader = new MessageLoader(
session,
wpState,
messageManager,
false,
uiErrorHandler
)
);
super(wpState, messageManager);
this.screen = screen
this.messageManager = messageManager
this.messageLoader = messageLoader

void messageLoader.loadFiles()
const endTime = session.duration?.valueOf() || 0
this.screen = screen;
this.messageManager = messageManager;
this.messageLoader = messageLoader;

if (hasTar) {
messageLoader
.loadTarball(session.videoURL.find((url) => url.includes('.tar.'))!)
.then((files) => {
if (files) {
this.wpState.update({ mode: PlayerMode.SNAPS });
this.messageManager.snapshotManager.mapToSnapshots(files);
this.play();
}
})
.catch((e) => {
this.wpState.update({ mode: PlayerMode.VIDEO });
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor logic to determine the mode based on the presence of a .tar. URL is clear and concise. However, ensure that the .catch block in the promise chain properly logs the error or notifies the user, as it currently only switches the mode without any error handling.

.catch((e) => {
+ Log.error(e); // Ensure to log the error or handle it appropriately
  this.wpState.update({ mode: PlayerMode.VIDEO });
});

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const hasTar = session.videoURL.some((url) => url.includes('.tar.'));
const screen = new Screen(true, ScaleMode.Embed);
const messageManager = new IOSMessageManager(session, wpState, screen, uiErrorHandler);
const messageLoader = new MessageLoader(
session,
wpState,
messageManager,
false,
uiErrorHandler
)
);
super(wpState, messageManager);
this.screen = screen
this.messageManager = messageManager
this.messageLoader = messageLoader
void messageLoader.loadFiles()
const endTime = session.duration?.valueOf() || 0
this.screen = screen;
this.messageManager = messageManager;
this.messageLoader = messageLoader;
if (hasTar) {
messageLoader
.loadTarball(session.videoURL.find((url) => url.includes('.tar.'))!)
.then((files) => {
if (files) {
this.wpState.update({ mode: PlayerMode.SNAPS });
this.messageManager.snapshotManager.mapToSnapshots(files);
this.play();
}
})
.catch((e) => {
this.wpState.update({ mode: PlayerMode.VIDEO });
});
}
const hasTar = session.videoURL.some((url) => url.includes('.tar.'));
const screen = new Screen(true, ScaleMode.Embed);
const messageManager = new IOSMessageManager(session, wpState, screen, uiErrorHandler);
const messageLoader = new MessageLoader(
session,
wpState,
messageManager,
false,
uiErrorHandler
);
super(wpState, messageManager);
this.screen = screen;
this.messageManager = messageManager;
this.messageLoader = messageLoader;
if (hasTar) {
messageLoader
.loadTarball(session.videoURL.find((url) => url.includes('.tar.'))!)
.then((files) => {
if (files) {
this.wpState.update({ mode: PlayerMode.SNAPS });
this.messageManager.snapshotManager.mapToSnapshots(files);
this.play();
}
})
.catch((e) => {
Log.error(e); // Ensure to log the error or handle it appropriately
this.wpState.update({ mode: PlayerMode.VIDEO });
});
}

Comment on lines +108 to +113
this.screen.addToBody(player);
this.screen.addMobileStyles();
window.addEventListener('resize', () =>
this.customScale(this.customConstrains.width, this.customConstrains.height)
)
}
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The injectPlayer method effectively adds the player to the screen and sets up a resize listener for custom scaling. However, consider removing the event listener on component unmount or cleanup to prevent potential memory leaks.

+ componentWillUnmount() {
+   window.removeEventListener('resize', this.customScale);
+ }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
this.screen.addToBody(player);
this.screen.addMobileStyles();
window.addEventListener('resize', () =>
this.customScale(this.customConstrains.width, this.customConstrains.height)
)
}
);
};
this.screen.addToBody(player);
this.screen.addMobileStyles();
window.addEventListener('resize', () =>
this.customScale(this.customConstrains.width, this.customConstrains.height)
);
};
componentWillUnmount() {
window.removeEventListener('resize', this.customScale);
}

Comment on lines +143 to +151
super.clean();
this.screen.clean();
// @ts-ignore
this.screen = undefined;
this.messageLoader.clean()
this.messageLoader.clean();
// @ts-ignore
this.messageManager = undefined;
window.removeEventListener('resize', this.scale)
}


window.removeEventListener('resize', this.scale);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clean method demonstrates good cleanup practices by calling the clean method of superclass and associated objects, and removing event listeners. However, setting objects to undefined using @ts-ignore is not a best practice. Consider setting them to null instead or ensuring they are properly disposed of if they are no longer needed.

- // @ts-ignore
- this.screen = undefined;
+ this.screen = null;
- // @ts-ignore
- this.messageManager = undefined;
+ this.messageManager = null;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
super.clean();
this.screen.clean();
// @ts-ignore
this.screen = undefined;
this.messageLoader.clean()
this.messageLoader.clean();
// @ts-ignore
this.messageManager = undefined;
window.removeEventListener('resize', this.scale)
}
window.removeEventListener('resize', this.scale);
};
super.clean();
this.screen.clean();
this.screen = null;
this.messageLoader.clean();
this.messageManager = null;
window.removeEventListener('resize', this.scale);
};

Comment on lines 20 to 41
const imageRef = React.useRef<HTMLImageElement>();
const containerRef = React.useRef<HTMLDivElement>();

const time = playerContext.store.get().time
const { time, currentSnapshot, mode } = playerContext.store.get();

React.useEffect(() => {
if (videoRef.current) {
const timeSecs = time / 1000
const delta = videoRef.current.currentTime - timeSecs
if (videoRef.current && mode === PlayerMode.VIDEO) {
const timeSecs = time / 1000;
const delta = videoRef.current.currentTime - timeSecs;
if (videoRef.current.duration >= timeSecs && Math.abs(delta) > 0.1) {
videoRef.current.currentTime = timeSecs
videoRef.current.currentTime = timeSecs;
}
}
}, [time])
}, [time, mode]);
React.useEffect(() => {
if (currentSnapshot && mode === PlayerMode.SNAPS) {
const blob = currentSnapshot.getBlobUrl();
if (imageRef.current) {
imageRef.current.src = blob;
}
}
}, [currentSnapshot, mode]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of useRef for imageRef and the new useEffect hook for displaying the current snapshot image are appropriate for managing DOM elements and side effects in React. Ensure that the blob URL is properly revoked when the component unmounts or the snapshot changes to avoid memory leaks.

+ useEffect(() => {
+   return () => {
+     if (imageRef.current && imageRef.current.src) {
+       URL.revokeObjectURL(imageRef.current.src);
+     }
+   };
+ }, [currentSnapshot]);

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const imageRef = React.useRef<HTMLImageElement>();
const containerRef = React.useRef<HTMLDivElement>();
const time = playerContext.store.get().time
const { time, currentSnapshot, mode } = playerContext.store.get();
React.useEffect(() => {
if (videoRef.current) {
const timeSecs = time / 1000
const delta = videoRef.current.currentTime - timeSecs
if (videoRef.current && mode === PlayerMode.VIDEO) {
const timeSecs = time / 1000;
const delta = videoRef.current.currentTime - timeSecs;
if (videoRef.current.duration >= timeSecs && Math.abs(delta) > 0.1) {
videoRef.current.currentTime = timeSecs
videoRef.current.currentTime = timeSecs;
}
}
}, [time])
}, [time, mode]);
React.useEffect(() => {
if (currentSnapshot && mode === PlayerMode.SNAPS) {
const blob = currentSnapshot.getBlobUrl();
if (imageRef.current) {
imageRef.current.src = blob;
}
}
}, [currentSnapshot, mode]);
const imageRef = React.useRef<HTMLImageElement>();
const containerRef = React.useRef<HTMLDivElement>();
const { time, currentSnapshot, mode } = playerContext.store.get();
React.useEffect(() => {
if (videoRef.current && mode === PlayerMode.VIDEO) {
const timeSecs = time / 1000;
const delta = videoRef.current.currentTime - timeSecs;
if (videoRef.current.duration >= timeSecs && Math.abs(delta) > 0.1) {
videoRef.current.currentTime = timeSecs;
}
}
}, [time, mode]);
React.useEffect(() => {
if (currentSnapshot && mode === PlayerMode.SNAPS) {
const blob = currentSnapshot.getBlobUrl();
if (imageRef.current) {
imageRef.current.src = blob;
}
}
}, [currentSnapshot, mode]);
useEffect(() => {
return () => {
if (imageRef.current && imageRef.current.src) {
URL.revokeObjectURL(imageRef.current.src);
}
};
}, [currentSnapshot]);

Comment on lines 44 to 138
const { svg, styles } = mapIphoneModel(userDevice);
if (!containerRef.current && mode) {
const host = document.createElement('div');
const shell = document.createElement('div');
const icon = document.createElement('div');
const videoContainer = document.createElement('div');

videoContainer.style.borderRadius = '10px';
videoContainer.style.overflow = 'hidden';
videoContainer.style.margin = styles.margin;
videoContainer.style.display = 'none';
videoContainer.style.width = styles.screen.width + 'px';
videoContainer.style.height = styles.screen.height + 'px';

shell.innerHTML = svg;
Object.assign(icon.style, mobileIconStyle(styles));
const spacer = document.createElement('div');
spacer.style.width = '60px';
spacer.style.height = '60px';

const loadingBar = document.createElement('div');

Object.assign(loadingBar.style, mobileLoadingBarStyle(styles));
icon.innerHTML = appleIcon;

shell.style.position = 'absolute';
shell.style.top = '0';

host.appendChild(videoContainer);
host.appendChild(shell);

icon.appendChild(spacer);
icon.appendChild(loadingBar);
host.appendChild(icon);

containerRef.current = host;

playerContext.player.injectPlayer(host);
playerContext.player.customScale(styles.shell.width, styles.shell.height);
playerContext.player.updateDimensions({
width: styles.screen.width,
height: styles.screen.height,
})
});
playerContext.player.updateOverlayStyle({
margin: styles.margin,
width: styles.screen.width + 'px',
height: styles.screen.height + 'px',
})
});

if (mode === PlayerMode.SNAPS) {
const imagePlayer = document.createElement('img');
imagePlayer.style.width = styles.screen.width + 'px';
imagePlayer.style.height = styles.screen.height + 'px';
imagePlayer.style.backgroundColor = '#333';

videoContainer.appendChild(imagePlayer);
const removeLoader = () => {
videoContainer.style.display = 'block';
icon.style.display = 'none';
host.removeChild(icon);
playerContext.player.play();
imagePlayer.removeEventListener('load', removeLoader);
};
imagePlayer.addEventListener('load', removeLoader);
imageRef.current = imagePlayer;
}
if (mode === PlayerMode.VIDEO) {
const mp4URL = videoURL.find((url) => url.includes('.mp4'));
if (mp4URL) {
const videoEl = document.createElement('video');
const sourceEl = document.createElement('source');

videoContainer.appendChild(videoEl);

videoEl.width = styles.screen.width;
videoEl.height = styles.screen.height;
videoEl.style.backgroundColor = '#333';

sourceEl.setAttribute('src', mp4URL);
sourceEl.setAttribute('type', 'video/mp4');
videoEl.appendChild(sourceEl);

videoEl.addEventListener('loadeddata', () => {
videoContainer.style.display = 'block';
icon.style.display = 'none';
host.removeChild(icon);
playerContext.player.play();
});

videoRef.current = videoEl;
}
}
}
}, [videoURL, playerContext.player.screen.document])
return (
<div />
)
}, [videoURL, playerContext.player.screen.document, mode]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic within the useEffect hook for creating and injecting the player based on the mode is comprehensive and handles both video and snapshot scenarios. However, this hook is quite large and does multiple things, which can make it harder to maintain. Consider breaking it down into smaller, more focused functions or hooks to improve readability and maintainability.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between ce64e62 and 77b1c69.
Files selected for processing (3)
  • frontend/app/components/Session/Player/MobilePlayer/ReplayWindow.tsx (1 hunks)
  • frontend/app/player/mobile/IOSPlayer.ts (1 hunks)
  • frontend/app/player/web/Screen/Screen.ts (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • frontend/app/player/mobile/IOSPlayer.ts
Additional comments: 9
frontend/app/components/Session/Player/MobilePlayer/ReplayWindow.tsx (8)
  • 1-1: The import of PlayerMode from 'Player' is correctly added to support the new player mode functionalities introduced in this PR.
  • 20-20: The addition of imageRef using useRef<HTMLImageElement>() is appropriate for managing the snapshot image element in a performant and React-friendly way.
  • 23-23: Destructuring time, currentSnapshot, and mode from playerContext.store.get() is a clean way to access these values. Ensure that playerContext.store.get() always returns an object containing these properties to avoid runtime errors.
  • 26-30: The useEffect hook for setting the current time of the video is well-implemented. It correctly checks if the mode is PlayerMode.VIDEO and adjusts the video's current time based on the time value. This logic ensures synchronization between the video playback and the player's state.
  • 35-39: The useEffect hook for displaying the current snapshot image is correctly implemented. It checks if there is a currentSnapshot and the mode is PlayerMode.SNAPS, then sets the image source to the blob URL obtained from currentSnapshot.getBlobUrl(). This approach is efficient for dynamically updating the snapshot display.
  • 44-96: The logic for injecting the player and custom scaling within the useEffect hook is comprehensive and appears to correctly handle the creation and styling of player elements based on the device model. However, ensure that the elements created (e.g., div, img, video) are properly cleaned up to prevent memory leaks or unintended side effects when the component unmounts or when the player mode changes.
  • 99-150: The conditional rendering logic based on PlayerMode within the useEffect hook is well-structured, handling both snapshot and video modes effectively. The creation of img and video elements dynamically based on the mode is a good approach. However, ensure that the removeLoader function and event listeners are correctly removed to prevent memory leaks and ensure that elements are properly cleaned up when the mode changes or the component unmounts.
  • 154-170: The styling functions mobileLoadingBarStyle and mobileIconStyle are correctly defined and provide a clean way to manage styles based on the device model. This approach enhances maintainability and readability of the styling logic.
frontend/app/player/web/Screen/Screen.ts (1)
  • 117-118: The addition of a null check for this.document before attempting to manipulate the DOM is a good practice. It enhances the robustness of the code by preventing potential runtime errors when the document is not available. Logging an error to the console is an appropriate way to notify developers of the issue.

@nick-delirium nick-delirium merged commit e207d37 into dev Feb 22, 2024
5 of 9 checks passed
@nick-delirium nick-delirium deleted the ios-player-v2 branch February 22, 2024 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant