## Issue
- selectMyActiveClaims memo problem -- being recalculated on every click -- high workload for wallet with large uploads.
- Mistake in handling abandoning IDs (it was trying to extract keys from an array)
## Changes
- selectAbandoningIds: never use `state` as an input selector. Breaks memo.
- Don't use selectMyClaimsRaw and then reduce it back to IDs. Use selectMyClaimIdsRaw instead.
- selectAbandoningIds is already in array form, so don't run Object.keys.
- Fix abandoningById never clearing when succeeded.
* Simplify dispatch map
Since none of dispatches are doing any custom transformation, just use a direct map. The number of arguments for the comment function are getting crazy.
* Block: pass comment ID for deletion when being blocked.
* Don't update 'pendingById' if no changes.
'pendingById' isn't frequently updated, but using it as a proof-of-concept to fix how reducers should be written to avoid unnecessary updates.
ImmutableJS apparently does all of this for us, but there are cons to using it as well, so using own wrappers for now.
* Don't update 'byId' if no changes + add 'selectClaimWithId'
## Ticket
116 Claim store optimization ideas (reducing unnecessary renders)
## Changes
- Ignore things like `confirmations` so that already-fetched claims aren't invalidated and causes re-rendering. The `stringify` might look expensive, but the amount of avoided re-renders outweighs it. There might be faster ways to compare, though.
- With `byId[claimId]` references more stable now, memoized selectors can now use 'selectClaimWithId' to pick a specific claim to depend on, instead of 'byId' which changes on every update.
* Fix memo: selectMyChannelClaims, selectActiveChannelClaim
## Issue
These should never recalculate after `channel_list` has been fetched, but they do because of poor selector dependency.
## Change
With the `byId` changes from the previous commit, we are now able to memoize these selectors correctly.
## Ticket
223 Add ability for delegated moderators to delete comments
## Changes
- Refactored doCommentAbandon's signature so we don't end up converting between "uri" and "Claim" several times and needing to lookup redux when the client can already provide us the exact values that we need.
- Pass the new moderator fields to the API.
- Remove the need to call 'makeSelectChannelPermUrlForClaimUri' since it's a simple field query when we already have the claim.
- selectMyChannelClaims depends on `byId`, which currently is always invalidated per update, so it is not memoized.
- Most of the use-cases just needs the ID or the length of the array anyways, so avoid generating a Claim array (in selectMyChannelClaims) unnecessarily -- the client need to reduce it back down to IDs again :/
- The simpler boolean also removes the need to memoize the selector, which saves a bit of memory.
`selectMyActiveClaims` includes `byId`, which gets invalidated on each resolve. Having this as an input selector breaks memoization.
For the case of comment-filtering, we don't really care about pending or abandoned own claims (I think), so just grab the raw IDs.
* Prevent multiple parseURI calls
## Ticket
129
## Issue
Code was shortened to use `isURIValid` during the consolidation. `isURIValid` calls `normalizeURI`, which calls another `parseURI`.
`parseURI` is pretty expensive.
## Approach
- Add optional parameter to `isURIValid` to skip the normalization.
- Set those that were converted during the consolidation to skip the normalization. Also covered a few other instances where it is obvious to me that normalization is not required.
- For the rest, I can't tell for sure if it's safe to remove the normalization, so the default `normalize=true` will leave things as is.
The whole `parseURI` probably needs a refactoring, or a few lighter version for specific needs.
* Simplify isURIEqual
## Issue
`parseURI` is too expensive to be used in a loop, plus `normalizeURI` itself is calling `parseURI`.
## Approach
Not sure if it covers all cases, but just try convert colons to hashes before comparing.
* Refactor filePrice
* Refactor Wallet Tip Components
* Add backend sticker support for comments
* Add stickers
* Refactor commentCreate
* Add Sticker Selector and sticker comment creation
* Add stickers display to comments and hyperchats
* Fix wrong checks for total Super Chats
## Issue
We previously automatically reload when there is a chunk error. This works fine if it's the case of new code was pushed recently while the user was active. But if the failure was caused by other things like network problems or the file IS actually missing, we end up in an infinite loop of refreshes.
## New approach
Tell the user to reload instead of automatically doing it.
* fix type error
fix is subscribed check
- Persist subscription data locally
- add / remove subscription during log in / out
- Use store directly in hook
Add toast error if subscription fails
Revert removal of v2
hotfix linting issue
Add custom notification handler
- fix isSupported flag
- make icon color compatible with light/dark theme
- fix icon on notifications blocked banner
wip: add push notification banner to notifications page.
- ignore failed deletions via internal API
- add ua parsing package
- add more robust meta data to token save
refactor naming + add push toggle to notification button
shift some code around
update css naming o proper BEM notation
update notifications UI
remove now unneeded util function
Update push notification system to sue firebase sdk
separate service worker webpack bundling
update service worker to use firebase sdk
Add firebase config
Add firebase and remove filemanager
Stub out the basics for browser push notifications.
* fix safari
* try smaller image for badge
* add token validation with server, refactor code
* remove param
* add special icon for web notification badge
* add translations
* add missing trans for toast error
* add pushRequest method that will not prompt users who have subscribed but since disabled notifications in the settings.
## Issue
85 Add additional GA events
## Approach
Instead of placing analytic calls all over the GUI code (no separation of concerns), try to do it through a redux middleware instead.
## Changes
- Updated GA event and parameter naming after understanding how reporting works.
- Removed unused analytics.
followedTags:
- Moved the filtering to the reducer side, so that we don't do it every time. We can't rely on `createSelector` because the store will be invalidated on each `USER_STATE_POPULATE`, unfortunately.
tags:
- Memoize via re-reselect for the "ForUri" selector.
## Issue
`makeSelectDataForUri` always returns a new reference, so `ClaimPreview` was constantly being rendered. It's pretty expensive since `ClaimPreview`'s rendering checks against a huge blocklist, which is another issue on it's own.
## Changes
- This commit tests the usage of `re-reselect` as the solution to the multi-instance memoization problem (https://github.com/toomuchdesign/re-reselect/blob/master/examples/1-join-selectors.md)
## Issue
When comments are refreshed, each `Comment` gets rendered 4-5 times due to reference invalidation for `othersReacts` (the data didn't actually change).
## Change
For selectors without transformation, there is no need to memoize using `createSelector` -- just access it directly. Also, don't do things like `return a[id] || {}` in a reducer, because the reference to the empty object will be different on each call.
Always return directly from the state so that the same reference is returned.
This simple change avoided the wasted resources needed for `createSelector`, and reduced to render to just 2 (initial render, and when reactions are fetched).
## Issue
Components render unnecessarily due to reference invalidation from `selectMutedChannels` selector.
## Notes
`selectMutedChannels` run and return a new reference each time the app gains focus. `createSelector` will not help in this case, because we are indeed invalidating the data in the store in `USER_STATE_POPULATE`.
## Changes
- Don't update the state if the array is identical in content.
- Fixed `selectMutedChannels` to return the reference from the store, so `createSelector` is not needed.
- Also, the filtering is not needed because we've already done it in the reducer.
## Comments
I've done some profiling on large blocklists. The time needed for the array comparison is still an order magnitude lower than the time needed to render all the Components that got incorrectly marked by this.
The ideal solution is for the sync code to return a hash or timestamp of the array, so that we can compare that instead of the array.
* adding functionality to detect user download speed
* calculating bandwidth speed more intelligently
* saving download speed and updating it every 30s
* all the functionality should be done needs testing
* fix linting
* use a 1mb file for calculating bandwidth
* add optional chaining plugin to babel and get bitrate from texttrack
* allow optional chaining for flow
* ignore flow error
* disable bandwidth checking functionality
* fix flow error
* Add option to pass in url-search params.
Impetus: allow linked comment ID and setting the discussion tab when clicking on the `ClaimPreview`.
* comment.list: fix typos and renamed variables
- Switch from 'author' to 'creator' to disambiguate between comment author and content author. For comment author, we'll use 'commenter' from now on.
- Corrected 'commenterClaimId' to 'creatorClaimId' (just a typo, no functional change).
* doCommentReset: change param from uri to claimId
This reduces one lookup as clients will always have the claimID ready, but might not have the full URI.
It was using URI previously just to match the other APIs.
* Add doCommentListOwn -- command to fetch own comments
Since the redux slice is set up based on content or channel ID (for Channel Discussion page), re-use the channel ID for the case of "own comments". We always clear each ID when fetching page-0, so no worries of conflict when actually browsing the Channel Discussion page.
* Comment: add option to hide the actions section
* Implement own-comments page
* Use new param to remove sort-pins-first.
comment.List currently always pushes pins to the top to support pagination. This new param removes this behavior.
I think this the best solution so far, at the expense of a slight delay in scrolling if the network call stalls.
- Added "fetching by ID" state so that we don't need to use the ugly N-retries method.
- `scrollIntoView` doesn't work if the element is already in the viewport, and the `scrollBy` adjustment doesn't take into account the y-position restoration that we perform on certain type of pages. Use `window.scrollTo` instead and taking into account current scroll position.
## Issue
.../archives/C02FQBM00Q0/p1633044695010600
## Changes
When querying a search key, it has to be an exact match. This was broken by the insertion of `free_only` in the fetch.
Added a function to generate the options, so that all clients stay in sync.
It was being recalculated repeatedly.
This memoizes it, although it still re-calculates occasionally despite none of the source arrays changed. I think it is due to the state change in the Preference Sync.
Note: input selectors to `createSelector` needs to be extractions-only (i.e. must not have transformations). I think most of our `makeSelect*` selectors violate this and broke memoization.
* ❌ Remove old method of displaying active livestreams
Completely remove it for now to make the commit deltas clearer.
We'll replace it with the new method at the end.
* Fetch and store active-livestream info in redux
* Tiles can now query active-livestream state from redux instead of getting from parent.
* ⏪ ClaimTilesDiscover: revert and cleanup
## Simplify
- Simplify to just `uris` instead of having multiple arrays (`uris`, `modifiedUris`, `prevUris`)
- The `prevUris` is for CLS prevention. With this removal, the CLS issue is back, but we'll handle it differently later.
- Temporarily disable the view-count fetching. Code is left there so that I don't forget.
## Fix
- `shouldPerformSearch` was never true when `prefixUris` is present. Corrected the logic.
- Aside: prefix and pin is so similar in function. Hm ....
* ClaimTilesDiscover: factor out options
## Change
Move the `option` code outside and passed in as a pre-calculated prop.
## Reason
To skip rendering while waiting for `claim_search`, we need to add `React.memo(areEqual)`. However, the flag that determines if we are fetching `claim_search` (fetchingClaimSearchByQuery[]) depends on the derived options as the key.
Instead of calculating `options` twice, we moved it to the props so both sides can use it.
It also makes the component a bit more readable.
The downside is that the prop-passing might not be clear.
* ClaimTilesDiscover: reduce ~17 renders at startup to just 2.
* ClaimTilesDiscover: fill with placeholder while waiting for claim_search
## Issue
Livestream claims are fetched seperately, so they might already exists. While claim_search is running, the list only consists of livestreams (collapsed).
## Fix
Fill up the space with placeholders to prevent layout shift.
* Add 'useFetchViewCount' to handle fetching from lists
This effect also stashes fetched uris, so that we won't re-fetch the same uris during the same instance (e.g. during infinite scroll).
* ⏪ ClaimListDiscover: revert and cleanup
## Revert
- Removed the 'finalUris' stuff that was meant to "pause" visual changes when fetching. I think it'll be cleaner to use React.memo to achieve that.
## Alterations
- Added `renderUri` to make it clear which array that this component will render.
- Re-do the way we fetch view counts now that 'finalUris' is gone. Not the best method, but at least correct for now.
* ClaimListDiscover: add prefixUris, similar to ClaimTilesDiscover
This will be initially used to append livestreams at the top.
* ✅ Re-enable active livestream tiles using the new method
* doFetchActiveLivestreams: add interval check
- Added a default minimum of 5 minutes between fetches. Clients can bypass this through `forceFetch` if needed.
* doFetchActiveLivestreams: add option check
We'll need to support different 'orderBy', so adding an "options check" when determining if we just made the same fetch.
* WildWest: limit livestream tiles + add ability to show more
Most likely this behavior will change in the future, so we'll leave `ClaimListDiscover` untouched and handle the logic at the page level.
This solution uses 2 `ClaimListDiscover` -- if the reduced livestream list is visible, it handles the header; else the normal list handles the header.
* Use better tile-count on larger screens.
Used the same method as how the homepage does it.
## Issue
Closes 7121 Missing mod block option (large number of moderated channels?)
## Notes
It was bad to assume `channelSignatures` would be the same length as the promise result -- any failure in signing would cause a misalignment.
For my case, an accidentally-merged channel couldn't be signed due to a missing private key. I think it's the same for Drew.
* Fix Floating Player stopping on certain files
* Dont show additional player buttons from markdown and comments
* Fix markdown resizing for the same video playing
* Update changelog
## Issue
7003 Can't unblock if delegator deleted their channel
## Changes
- Changed the function parameter from 'creatorId' to 'creatorUri'
- It got short-circuited because we don't resolve deleted channels. But the client already have the full creator URI (containing the needed 'name' and 'id'), so there is no need to actually look at the resolved list -- just pass the uri like all the other functions.
## Preamble
- The app-side uses a cached blocklist, so when a Timeout expires, it doesn't know that the ban has been lifted.
- Meanwhile, we are doing extra comment filtering using this blocklist (so that we don't see comments that we have blocked, regardless of whose claim we are viewing).
## Issue
In a livestream, if a new message from an ex-offender comes in after their ban has been lifted, we do get the websocket message but it's being filtered out locally as mentioned above. So, the msg ended up being visible for everyone except the owner.
## Fix (band aid)
- Don't run the extra filter if the claim we are viewing is ours -- commentron would have filtered it for us anyways, and is the right logic to use even before this Timeout feature is introduced.
- For the case of Timeout, this only serves as a band-aid until Commentron Issue 80 is available for us to detect the ban has been lifted. This is because it doesn't handle the case where I am a viewer and I decided to timeout someone for a few minutes. Because I am not the owner of the claim, the offender will continue to be blocked due to the same issue mentioned above.