## Issue
Closes 385
## Approach
As mentioned in the ticket, the current places where that info is needed is in the Invites Page and Social Share Component.
1. Invites Page: it is already doing the fetch on mount, so no issue there.
2. Social Share: show spinner until the data is fetched.
## Issue
Closes "87 Repost - Top result should show followers properly"
The winning url for "bret" search is "lbry://bret", which is a repost.
## Change
We need to use the canon url to retrieved the fetched view count.
## Issue
A huge list like http://localhost:9090/$/list/d91815c1bc8c80a1f354284a8c8e92d84d5f07a6 (193 items) often produces fewer results in the final rendered list.
## Cause
The same list of IDs was passed into `claim_search`, and we just increment the `page`. However, it seems like `claim_search` does not honor the order between each call, and some results from the previous page took the place of the results in the next page. The total is the same, but there are now duplicates.
## Fix
When batching, slice the ID list ourselves to bypass the problem for now.
Commentron json params are usually underscored instead of camel-cased.
Double-checked commentron code:
```
// MentionedChannel channels mentioned in comment
type MentionedChannel struct {
ChannelName string `json:"channel_name"`
ChannelID string `json:"channel_id"`
}
```
The parameter should probably also be skipped instead of sending empty array, but leaving as-is for now since that is minor.
## Ticket
644 investigate following vs subscription preference data
## Issue
- iOS app uses colon for following/subscriptions.
- Front-end code handled the "colon vs. hash" for CHANNEL_SUBSCRIBE, but not for CHANNEL_UNSUBSCRIBE
* Refactor CommentBadge
* Refactor livestreamComment component
* Refactor and split livestreamComment CSS
* Refactor livestreamComments component
* Refactor and split livestreamComments CSS
* Remove never used spinner
* Refactor livestream Page
* Refactor page component
* Refactor livestreamLayout component
* Break apart livestreamComments into separate sibling components
- This helps separating LivestreamComments to deal with only the comments, and the LivestreamLayout to be used for its own Page as a Popout option, and also for a layered approach for mobile
* Create Popout Chat Page, Add Popout Chat Menu Option
* Add Hide Chat option
* sockety improvements
* Websocket changes
Co-authored-by: Thomas Zarebczan <thomas.zarebczan@gmail.com>
* Refactor doAbandonClaim parameters to only claim
- Gets txid and nout by default now, and passing claim allows using more data to verify ownership in case of txid:nout failing again
- Unused on modalRemoveCard
- Edited the comment on doCollectionDelete to explain better
* Fix doAbandonClaim failing to select my claim
* Resolve claim and stream types when there is a filter
## Symptom
Channel Page 'Content Type' filter not working
## Issue
The Advanced Filter work by placing a `?content=` URL param. The list component then parses it and makes the `claim_search` params accordingly. But:
1. There is a mix up in how the list component treats `?content=`.
- The original code seems to treat this as a way to define the type externally but only for a list without `claimType` defined via code. In other words, if `claimType="something"`, `?content=` is ignored.
- On the other hand, the Advanced Filter relies on `?content=` being used.
2. `?content=` is then split between `claimType` and `streamType`. The current code does not check if the split makes sense, e.g. if `?content=channel` and `streamType=['video']`, these 2 are incompatible and produces no results.
## Change
1. I'm not really sure what's the original intention, but let's just make `?content=` as an override/filter.
2. `?content=` should probably be limited to always be a subset of `claimType` and `streamType`. But this seems complicated to do, so for now let's just make always override/filter everything. For that, we need to make sure the filtered `claimType` -- `streamType` combo makes sense.
* Fix 'Channel' filter not working in Wild West
## Cause
The Wild West list defines `release_time` to be 1 week ago. As long as this parameter exists, a channel `claim_search` produces no results (I thought channels have creation dates?). That is why an unfiltered Wild West never showed Channel Tiles.
## Change
The existing `release_time` handling does seem to hint that we should not set the parameter when searching for Channels. Expanded that to consider the final (filtered) claim type, not just the original.
## Issue
After enabling Advanced Filter in Category Pages, the 'Content Type' filter only works for "repost/video/list".
## Root-cause
When `streamType` is not provided, it defaults to 'Video|Audio', making it always "defined":
```
streamType = SIMPLE_SITE ? [CS.FILE_VIDEO, CS.FILE_AUDIO] : undefined,
```
This seem to override the purpose of `defaultStreamType`, which will not be used unless the client explicitly set `streamType=null`, which currently is only being applied for `RECENT_FROM_FOLLOWING[]`.
```
const streamTypeParam =
streamType || (CS.FILE_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultStreamType || null;
```
The quality API doesn't work on the default PNG but works on JPG.
- Switching to JPEG (100%) produces a smaller image than the default PNG. This covers most scenes.
- For some scenes, the size could still be larger than 2MB, so retry with JPEG (80%). For a 1080p image, this action produces the file at <1MB range. The quality still looks ok, I think.
* Add ordering Icons
* Refactor doCollectionEdit
- It required claims as parameter, when only uris are used to populate the collection, so that was changed to pass down the uris instead.
- There were unused and mostly unnecessary functions inside, for example the parameter claimIds was never used so it would never enter the claimSearch function which again would be used to generate uris, so it's better to just use uris as parameter
* Add List Reordering changes
* Add toggle button for list editing
* Add toggle on content page collection sidebar
* Enable drag-n-drop to re-order list items
https://www.youtube.com/watch?v=aYZRRyukuIw
* Allow removing all unavailable claims from a List
* Fix <g> on icons
* Fix section buttons positioning
* Move preventDefault and stopPropagation to buttons div instead of each button, preventing clicking even if disabled opening the claim
* Change dragging cursor
* Fix sizing
* Fix dragging component
* Restrict dragging to vertical axis
* Ignore shuffle state for ordering
* Fix console errors
* Mobile fixes
* Fix sidebar spacing
* Fix grey on mobile after click
## Issue
656 Automatic language detection can't recognize de-DE as de
## Note
We do fallback to the main language, but seems like the code got lost ... not sure when, but probably during the CN/TW or PT-BR support. The refactor in 81e47300 still did that, but the refactor was reverted due to some compilation issue (should revisit that someday).
## Change
Put back equivalent code.
* Tooltip: add 'followCursor' and 'placement' option
When used on a `<span>` with short text but large empty area, the location of the tooltip was at the bottom-center of the area, which isn't ideal.
I think 'followCursor' should be the default, but making it optional for now to minimize testing.
Also added the 'placement' prop -- for the span case again, the mouse cursor is blocking the tooltip.
* View/Follower count: only use compact when > 10k
## Issue
Received complaints -- some people prefer to see full resolution.
## Changes
- As a compromise, we'll only apply the compact notation when the value is greater than 10k, with the exception of Tile View Count, where we'll always apply it due to space limitation.
- Also added Tooltip for Follower count.
## Fixes
- The string was always in 'en' locale in some instances, so it wasn't grouping up digits properly in Japanese (groups of 4), for example.
## Issue
When "Upcoming livestream" appears in a list, infinite scroll stops working.
## Cause
The difference between `mainEl.getBoundingClientRect().bottom` and `window.innerHeight` became slightly greater than 0.5, so it was deemed as "haven't reached the bottom".
## Change
Coincidently, I've been wanting to make the inf scroll load earlier (instead of after reaching the absolute bottom) to make the experience smoother, so added a 200px threshold, which is roughly the height of a tile. This gets us the new behavior while also fixes the original problem.
- activeChannelClaim is the comment creator, not receiver.
- doSeeNotifications marks a notification as "seen", and not "send a notification".
- Removed comments that are just explaining the syntax.
* Test out a horizontal scroll for upcoming (tile only for now)
* - add support for list layout
- add following label on home page
- clan up css and naming conventions
* Update header type + show only if scheduled streams are showing
`doError` supported either a string or object, and so far there are no instances where the object version is used, so this enhancement should be safe to do without affecting anyone.
## Change
For the object version, support an additional `cause` parameter that will be logged but not show in the GUI.
## Issue
Closes 627 account header doesn't refresh on sign up / log in
## Changes
Looking back at "[Header] Changes, fixes and improvements (#493)", noticed that old code was looking at `has_verified_email` instead of just checking whether an email exists. So, restored original code.
This does have a side-effect of the Logout button not showing any email address underneath it immediately after sign up (with the flow cancelled). But I vaguely recall it was that way previously. A refresh cleans it up.
Perhaps another `user/me` when leaving the Sign Up page can make everything in sync, but this PR simpler to test.
* Add a setting to hide scheduled livestreams from home/following
* Add a hide button in the scheduled stream header.
* Fix typo + make sure pref is synced
## Issue
- When signing up, the "channel suggestions" page was stuck because `prefsReady` was never set as `preference_get` was never called.
- It was never called due to the optimizations to skip it when there is no difference between the local and server wallet.
## Change
- The first ever `sync/get` will result in a "no wallet" error, and there is already a `catch` to handle it. But the change in 38c13cf5 caused the `catch` to be skipped and went directly to `sync_apply` instead. Although the `catch` is also doing the same thing (`sync_apply`), it also has an additional callback to call `preference_get`.
- Fixed by ensuring this scenario ends up in the `catch` block like it was originally intended.
- We also did some optimization in the callback to skip the final `preference_get` if there is no difference in hash. But for the case of signing up, we do want to run it (so that `prefsReady` and other stuff gets initialized), so pass `hasNewData = true` to the callback.
## Issue
- Closes 592 Force clear stuck upload
- It was possible for an upload to stay "locked" e.g. when browser is killed.
## Change
When refreshing or opening a new tab, always clear the locks. The on-going sessions will re-lock them immediately.
## Issue
"No notifications" briefly appear when your previous filter is not "All".
## Change
When splitting up the category-fetch, the render logic was not updated accordingly.
## Issue
In the original Desktop code, new strings encountered during runtime will be automatically added to the local `app-strings.json` file. The feature is unavailable in Web because writing to file would require explicit permissions.
## Change
Partially restore the functionality by saving the strings to memory and retrieving it from the console via `copy(window.new_strings)`. It's a little bit of manual work, but I think it is good as it forces a sanity check before committing (previously, experimental/developmental strings are committed and being translated in Transifex).
* Update publish form when editing livestream + update to radios for liveststream release time
* Fix bug where upload tools may remain visible upon switching upload type, even when no option to upload is available.
* move publish source state up, when editing livestream only show scheduling option when source is none.
* Reset any set release time if switching to live stream mode.
* Update date/time cmpnts to reset any chnages they made on umount. Update schedule date/time cmpnt to clear release time when selecting anytime option.
* Additional filtering of internal tags
* Default to replay view when editing a liveststream
- Query for that tag in the upcoming section
- Improve special tag organization
- Filter out the internal tags in the UI
- Add missing types to publish state
The number of props to pass is getting out hand, so just pass the Comment object directly.
Also, moved the "is my comment" check into LivestreamComment, so we don't need to pass it as a prop from the parent.
## Issue
- Slow for users with many channels.
- The need to do it in Sync Loop is more applicable to Desktop.
## Approach
- Just remove it from sync loop.
- It will still be called when entering `/$/channels`, so that's an alternative to fix things when it is out of sync.
## Issue
In 38c13cf5, an additional `doGetAndPopulatePreferences` was added in `doSignIn` to ensure we have populated the preferences at least once. With that, `doHandleSyncComplete` can skip `doGetAndPopulatePreferences` is there is no change in the hash.
The addition broke the "initial sync lock", thus incorrectly allowing users to change preferences when the process is not completed.
## Change
I think the additional call is no longer needed since we now store a local hash for comparison, so `doGetAndPopulatePreferences` wouldn't be incorrectly skipped in the first ever `doHandleSyncComplete`.
## Repro
1. Follow a channel.
2. When `preference_set` is sent, unfollow the channel.
3. A few seconds later, the final setting reflects (1) instead of (2).
The current sync loop involves doing a final `sync/get` at the end. While not necessary for the scenario above, the code flow covers various cases, so it's still needed for now.
## Approach
Implement an abort mechanism to the sync-loop.
When syncing from the `buildSharedStateMiddleware` loop, generate an ID for each sync session, and only store the latest one. Pass the ID to the completion-callback (and other places as needed), so we can check if our session is still the latest one before executing the callback.
The check for invalidation can also be placed in more places to cut off the sync process earlier, but it's only done for 2 critical places for now.
Props: either use primitives, stable references or memoized objects to reduce renders. This update will simplify the existing `areEqual`. It is still needed though as some props are hard to memoize from where they are called, or should simply be ignore.
## Ticket
Part of "#385 Defer api.odysee.com calls to their respective pages / install new"
## Change
Pull out `notification/categories` from `doNotificationList` and fetch it in Notifications Page. I don't there there are other places that need it for now.
## Repro
- Do a search like "Test" and filter to "Channels Only".
- Follow a bunch @test channels
- Unfollow any one of them. All of them gets unfollowed.
## Notes
The change in b9fc9b63 to compare the lower-case channel name probably made it even worse, since "@TeSt" would be removed too.
## Change
Not sure why channel name was used in the first place ... perhaps it was to cover canon vs perm uri?
Anyway, comparing uri makes more sense, so doing that instead.
Was trying to save one event listener in the previous implementation and rely on other redux state-changes to spark a GUI update, but turns out there are scenarios where nothing is updated and the "offline" nag is stuck on screen.
## Change
Do it properly using the event listeners. The nag should now update promptly.
Changing the string means it will stay in English until retranslated. Reverting so that it can re-use existing translated database.
I don't think there is a clash in the `followingCount` variable, so the change was probably unnecessary.
## Issue
Apparently, a user is experiencing 423 locked errors from the server, which should not happen given the locking mechanism plus the user wasn't trying to do concurrent uploads.
## Fix
Anyway, fix the Resume button so that at least they can try to resume.
* Refactor userChannelFollowIntro
* Add community based channels to signup auto follow
* Add German channels
* Remove main english channels and leave only community ones for auto follow
* Add ability to have claim searches auto-fetch up to 3 pages.
* make total_items and total_pages optional
* use auto pagination strategy when determining live claim
* Bump page size back to 50
## Issue
The ad tile causes a layout shift on certain screen/zoom, pushing CLS from green to red.
## Change
- Do replacement instead of insertion.
- Fixed "null lastCard" flow warning instead of suppressing it.
## Issue
https://www.notion.so/Performance-Fixes-927f825a5d674bd09323830be1d263af#1beab2fee011421492b56b88f68681a3
We currently lazy-load the tiles in the category sections (but not the sections themselves, because we want to retain scroll position on Back action). This puts gray placeholders until the section is visible on screen. which turns out to be quite expensive, because the placeholders are animated, so we have a perpetual animation in the background after the homepage loads + user did not scroll.
## Change
Just disable the barely-noticeable animation for now.
There are alternatives, but probably not worth polluting the code with:
- Just like the thumbnails, use intersection observer to decide when to animate.
- Find solution to the "lazy load section + need to retain scroll position".
lbry-desktop--6844
This negates 49abbecb.
Now that we have a dedicated chromecast button, we don't need to hack Chrome's default cast button to appear on top of vjs-mobile-ui. The hack no longer works anyway, since the CSS exposure has been deprecated around mid 2020 -- it is still available, but its abilities has become less and less.
- The graphic was meant to be 50% of the card width, but was squished.
- Try to reduce scrolling by making everything fit in a 100% zoom on a 1080p screen.
The previous version was trying to fetch an optimized image with the exact size required, but the URL given was pre-optimized, so it wasn't working correctly. The additional work is also slow (seems to lock up mobile a bit), and since it wasn't functional, just removed it entirely.
It will be easier to just pre-reduce the image size to something suitable for a 1080p screen (the most common screen size at the moment).
As noted in a comment, we need to be careful when adding props to `VideoJs` to avoid renders.
Used primitive strings (title, channelName) instead of passing the entire `claim`, which could have its reference invalidated.
## Ticket
426
## Issue
Currently, we check if we have any existing claims with the same name when uploading, i.e. "lbry://<name>". It does not include claims that you are still uploading, so you might end up with duplicate claims.
In the ticket, there is also the issue of 2 uploads sharing the same slot, causing the progress indicator to jumpy between the uploads. That has been fixed by using a guid instead of using `name`.
## Aside
I think there is another request to allow the same name but on different channel ... next time, next time ....
- Using `selectIsSubscribedForUri` instead, because the given uri is in Canon while the subscription list is in Permanent, so the result was always `false`.
- More css consolidation.
- More size and padding restoration (it wasn't 445's main intention to change sizes).
- Handle padding for mobile to hopefully make everything fit, especially for Playlists. We'll need an overflow menu to truely fix this for all screens.
## Scenario
`selectHasUnclaimedRefereeReward` updated --> `AppRouter` re-render --> `dynamicRoutes` regenerates (re-mounts) list of `DiscoverPage`s
## Fix
I think `selectHasUnclaimedRefereeReward` can be moved elsewhere and would solve the problem, but avoided that since I'm not familiar with rewards enough to do minimal testing.
Memoize the Category Page routes instead.
`GetLinksData` is somewhat expensive. The value won't change until user changes the window size or selects another homepage.
As we can't call an `effect` within a `memo`, we had to extract out `isLargeScreen` as an input parameter, which is fine as it makes `GetLinksData` more functional (functional programming).
## Issues
- So many `!important` overrides that makes it hard to customize.
- Weird "813px max-width" check -- it feels random, plus does not adjust accordingly to zoom-levels.
- The button text is not always vertically centered for all layout and zoom-levels because it is being centered using hardcoded margins.
- The 2 popups don't have consistent fonts and styling, plus their customizations are all over the place.
## Changes
- Try to remove as many unnecessary "!important" as possible. Adding specificity is sufficiently, and won't block other customizations.
- Try using `rem` instead of hardcoded margins. The icons/text/margin should resize accordingly per zoom-levels.
- I didn't replicate the "813px max-width" media check. If it is really necessary, please use `vjs-layout-*` to customize them instead.
- Consolidate the 2 popup menu customizations.
Each button should have the same touch area and roughly the same left-right margins. Currently, the Theater Button (or the Chromecast button) looks too far from Speed and too close from Autoplay. They should be evenly-spaced.
* Upload: fix redux key clash
## Issue
`params` is the "final" value that will be passed to the SDK and `channel` is not a valid argument (it should be `channel_name`). Also, it seems like we only pass the channel ID now and skip the channel name entirely.
For the anonymous case, a clash will still happen when since the channel part is hardcoded to `anonymous`.
## Approach
Generate a guid in `params` and use that as the key to handle all the cases above. We couldn't use the `uploadUrl` because v1 doesn't have it.
The old formula is retained to allow users to retry or cancel their existing uploads one last time (otherwise it will persist forever). The next upload will be using the new key.
* Upload: add tab-locking
## Issue
- The previous code does detect uploads from multiple tabs, but it was done by handling the CONFLICT error message from the backend. At certain corner-cases, this does not work well. A better way is to not allow resumption while the same file is being uploading from another tab.
- When an upload from 1 tab finishes, the GUI on the other tab does not remove the completed item. User either have to refresh or click Cancel. Clicking Cancel results in the 404 backend error. This should be avoided.
## Approach
- Added tab synchronization and locking by passing the "locked" and "removed" information through `localStorage`.
## Other considered approaches
- Wallet sync -- but decided not to pollute the wallet.
- 3rd-party redux tab syncing -- but decided it's not worth adding another module for 1 usage.
* Upload: check if locked before confirming delete
## Reproduce
Have 2 tabs + paused upload
Open "cancel" dialog in one of the tabs.
Continue upload in other tab
Confirm cancellation in first tab
Upload disappears from both tabs, but based on network traffic the upload keeps happening.
(If upload finishes the claim seems to get created)
* Settings Page: add warning for unsaved settings
## Issue
When entering Settings Page, sync-loop is disable until user exist Settings Page. If browser is closed, changes will be lost.
## Change
Add the usual browser-level modal popup.
Note that all modern browsers have stopped supporting customized messages, but I still left the message there for clarity. Tried to use our own toast for it, but the handler locks all GUI until it is serviced.
* app: remove unused props
* app: use lighter selectors
When all we need is to know if something exists or their count, use the ID version instead of the url/claim version to avoid the heavy transformation.
* Fix query selection
* Fix xml format
* Fix link url and author_url
* Refactor repeated components
* Refactor repeated embed iframe string
* Add support for passing referrer queries to src
* Change iframe id from lbry to odysee
* Improve replace logic understanding
* Fix URL
Co-authored-by: Thomas Zarebczan <tzarebczan@users.noreply.github.com>
We already have a pre-calculated map, but not used except for comments.
At the expense of pre-calculating it, the subsequent queries are instantaneous compared to the loop.
We are still not perfect in term of reducing re-renders, so this helps a lot.
* Discover: add persistence to the livestream section's fold state
The persisted value should only apply when livestream section is needed, hence the need for 2 state variables.
Also renamed the variables for clarity.
* Discover: add "show less livestreams" at upper-right
Wanted to put it as an injected tile, but requires more work to do it in a general-purpose way, as opposed to a hardcoded way like how ads are currently injected. It also needs to work on both Tile and List format.
So ... just place the button at the upper-right for now. Although a bit odd, at least it'll be a consistent place (i.e. position won't be affected by live tile count).
I yanked out the parseURI part in a prior commit ... the comment was misleading me to think it was redundant. But it had another hidden function, which is to handle abandoned claims which `claim` will be `null`.
The recent change to parse the channel from a Repost using a `claim` ended up breaking the case for abandoned claims, which `claim` will be `null`.
Fix by looking at `claim` first (faster), and falling back to the `parseURI` method if it remains inconclusive.
* coming along well
* coming along well
* adding custom react element
* coming along well
* coming along well
* coming along well
* working pretty well
* almost done
* essentially working just could use a couple touchups
* cleanup and lint errors
* fix lint errors
* fix flow errors
* possible bugfix
* dynamically set width and height
* only run when rowdata is populated
* trying using ref
* better way to check for card population
* working implementation
* working implementation
* clean up flow and clean up script
* fix typo in comment and logs
## Behavioral changes
- Moved Notifications to the top for mobile.
- Added separate lines between sections.
## Code changes
The array method is too restrictive (hard to move things with display logic around). It's also hard to read.
Instead of trying to populate an array, just directly populate the return tree. Added `getLink` to make things readable. It's now easier to see the sections in a glance.
## Ticket
189: Overall React Lag or Extra Re-renders / Volume slider laggy since v0.48
## The problem
Every redux update results in each mounted component's prop mapping function (the `select` and `perform` stuff) to be recalculated. This is normal per redux, but we do lots of heavy stuff there.
The slider was sending tons of redux update for the Volume and Muted setting.
## Changes
The redux volume/muted setting is just used to restore vjs to the user's setting on the next video, so it doesn't need to be updated immediately/constantly -- vjs keeps it's own video settings. Debounced that action.
* Route recommendation search to recsys 5% of the time + add `user_id`
## Ticket
334 send some recommended requests to recsys
## Approach
`doSearch`:
- If the search options include `related_to`, route that to the new `searchRecommendations` which performs the 5% check + appends `user_id` at the end. This way, we don't need to alter the function signature of `doSearch`.
- Else, run proceed as normal.
* Always go to alt provider
f
Co-authored-by: Thomas Zarebczan <thomas.zarebczan@gmail.com>
* Add remove_duplicates to tile/list claim_search except for Channel Page
This removes the any duplicates from reposts.
* Re-activate the "Hide reposts" setting
* Category Rows: default to ['stream', 'repost'] unless specified otherwise.
## Issue
85: "user joined livestream"
## Approach
Add it into the existing "player :: action" event, so we can compare it againts `loaded_video | loaded_image | loaded_markdown | loaded_audio`.
* apiCall: add option to not send the auth header
## Why
Want an option to make un-authenticated `resolve` calls where appropriate, to improve caching.
## How
All `apiCall`s are authenticated by default, but when clients add NO_AUTH to the params, `apiCall` will exclude the X_LBRY_AUTH_TOKEN. It will also strip NO_AUTH from the param object before sending it out.
* Add hook for 'resolve' and 'claim_search' to check and skip auth...
... if the params does not contain anything that requires the wallet.
* doResolveUri, doClaimSearch: let clients decide when to include_my_output
- No more hardcoding 'include_purchase_receipt' and 'include_is_my_output'
- doResolveUri: include these params when opening a file page. This was the only place that was doing that prior to this PR.
* is_my_output: use the signing_channel as alternative
## Notes
`is_my_output` is more expensive to resolve, so it is not being requested all the time.
## Change
Looking at the signing channel as the additional fallback, on top of `myClaimIds`.
## Aside
I think using `myClaimIds` here is redundant, as it is usually populated from `is_my_ouput`. But leaving as is for now...
## Ticket
155 All live streams show on tag explore/discovery page + content type filters don't work there
`!dynamicRouteProps` wasn't good enough to determine if it's Wild West. Use direct path instead.
* add gdpr support
* only run on production
* testing implementation
* just needs last touches then ready
* ready for merge
* add cookies to sidebar
* hide button when secureprivacy not available
* switch over to loading script as a react hook
* conditionally add secureprivacy script
* save gdpr status on session
* better design
## Why
- No memo required (no transformation).
- `makeSelect*` is an incorrect pattern.
## Changes
- Replaced makeSelectClientSetting with selectClientSetting.
- Remove unused selectShowRepostedContent.
* SyncFatalError: show nag instead of hard-crashing.
## Issue
When sync fails, we crash the app.
## Ticket
Maybe closes 39 "Better handle both internal and web backend interruptions / downtime"
## Approach
I'm tackling this from the standpoint that (1) sync errors are not that fatal -- we'll just lost a few recent changes (2) network disconnection is the common cause.
## Changes
- If we are offline:
- Inform user through a nag. All other status is meaningless if we are offline.
- If we are online:
- If api is STATUS_DOWN, show the existing crash page.
- If there is a sync error, show a nag saying settings are now potentially unsynchronized, and add a button to retry sync.
- If there is a chunk error, nag to reload.
* Attempt to detect `status=DOWN`
Previous code resolves the status to either "ok" or "not", which makes the app unable to differentiate between the "degraded" (nag) and "down" (crash) states.
## Issue
- It was checking the blacklist on every render.
- Finding opportunities to improve performance
## Changes
Since the final destination will be a dead end anyways, skip the blacklist check so that livestreams can render a bit faster when there lots of mentions.
The only downside is that a claim preview for a blacklisted item would now appear (vs. being a text previously)
## Issue
- Large resolve count (albeit batched) on bootup.
## Changes
- Skip the call on bootup. The same call will happen when you click the notification bell, so it's not too late to resolve at that time.
- Added `true` to `doResolveUris` to return cached results, otherwise it will keep resolving the same channels every time we enter Notifications Page.
## Issue
312 Save notification on back navigation, enable filter on mobile
## Changes
- Don't clear then filter when mounted and there are unread notifications.
- We previously clear the filter because the user could be clicking the notification bell (which is showing some number) and we ended up with a blank page because of the filter.
- Allow the filter in mobile.
- Previously, it was intentionally removed for mobile (see bd42418f). I believe it was just because we don't have the style set up for mobile. Here's my quick attempt.
## Issue
One of the bottlenecks of livestream page.
The component probably needs a re-design:
- Don't perpetually mount -- only mount when activated by the user through "@". This would avoid the heavy processing entirely.
- Better way of resolving uris (too many arrays, too many loops).
- Tom also mentioned that we should not be resolving every commenter as we see encounter them in a livestream. This is currently the case because the component is always mounted.
## Changes
Until the re-design occurs, attempt to cache the heavy processing. Also, trimmed down the amount of loops.
For the case of livestreams, the comments are added incrementally via websocket. The selector returns everything, which grows as a user watches the livestream.
We could even make it a bit more efficient by passing in `maxCount` to `filterComments`, and do a `for` loop there, but decided to keep things readable by not changing the `filter` usage.
As long as the input parameters are the same, the selector will return the cached value so that we don't construct the list twice, which involves blocklist filtering.