## Issue
- "Following" was showing up in place of "Featured"
- "Following" doesn't appear until livestreams are fetched, causing shifts.
When "Upcoming Livestreams" was implemented, it was trying to retain the original behavior of not showing "Following" title if that was the first in the list.
Not only is it a chicken-and-egg problem, but it causes extra renders due to the need to check if the other guys was rendered.
With FYP, there are now more combinations to handle.
## Change
Just show the title...
Was trying to save 1 state by assuming the homepage will be in a busy state and the ad-detection code will finish first. But this is not true for those with a small Following count.
- Variable names are for translators to determine the context, so choose more relevant names. e.g 'displayedInterval' and 'date_range' will not make much sense to a non-programmer.
- No need to localize dev-only strings.
- Various other fixes.
* Factor out lighthouse-result processing code for FYP re-use.
The FYP results will be in the same format as LH.
* Recsys: add ability to pass in specific uuid to use
For FYP, we want to pass the UUID as a param when searching for recommendations. The search comes before the recsys entry creation, so we need to generate the UUID first when searching, and then tell recsys to use that specific ID.
* Redux: fetch and store FYP
Note that the gid cannot be used as "hash" for the uri list -- it doesn't necessarily change when the list changes, so we can't use it to optimize redux. For now, just always update/render when re-fetched.
* UI for FYP
* Mark rendered FYPs
* Pass the FYP ID down the same way as Collection ID
Not ideal, but at least it's in the same pattern as existing code for now. The whole prop-drilling problem with the claim components will be fixed together later.
* Include 'gid' and 'uuid' in recommendation search
* Allow users to mark recommendations that they dislike
* Pass auth-token to all FYP requests + remove beacon use
beacons are unreliable and often blocked
* Only show FYP for members
* FYP readme page
* small fixes
* fyp
Co-authored-by: Thomas Zarebczan <thomas.zarebczan@gmail.com>
* various cleanups
* more touchups
* select currency to use based on location
* fix sidebar
* fixing strings and other touchups
* refactor and do proper string interpolation
* fix stripe error
* text bugfix
* Adjust help
Co-authored-by: Thomas Zarebczan <thomas.zarebczan@gmail.com>
Ticket: 1079 Support geoblocking channels/videos
## Changes
- Replaced the .env version with iapi version.
- Includes 'videos' blocking and custom messages.
* Homepage-Following: insert instead of replace when ad-blocker is detected.
`window.odysee_ad_blocker_detected` was not meant to be used outside of `<Ads>`, since it wouldn't spark a GUI update. But since homepages are rendered several times, perhaps it doesn't matter and we can skip adding to redux for now.
* Handle uBlock origin
If refreshed via "Clear Cache and Hard Reload", the detection method fails, but it does perform an internal redirect, so treat that as a failure.
* Add last used collection to right click menu.
* Small fix for last used collection when it's a published collection.
* Update last used collection when a collection is pending or published.
* Small refactor to get the last used collection.
We need to store the resolved claims first before marking COLLECTION_ITEMS_RESOLVE_COMPLETED, otherwise the GUI still sees undefined claims.
798 just accidentally flipped the order due to refactoring, I believe. It's now back to original.
Closes 916 "NaN in Total Staked Amount"
Contemplated putting the fallback into `<CreditAmount>` itself, but decided to minimize testing. Not sure if there are clients that would rely on NaN being used.
* Add swipe layout support for Collection Tiles
* Lists: use swipe layout for mobile
Ticket: 950 "playlists page - right now we show watch later on top, and if you have stuff here, you have to scroll down to other playlists. Show a selector on top? Whatever other improvements we can make here to improve UX."
The solution didn't work 100%, only reduces the chances of happening significantly. So far, still can happen on hot-reload during development.
- Reverted 15bd26399f.
- Fix by just hiding the unoccupied aniBox
- Initially, we did a bunch of forceful CSS to make the ad tile resize properly when the browser resizes. This was causing the EU ad to display incorrectly. Turns out, that css is no longer needed after the BEM-style re-write.
- Changed the floating ad selector to cover both EU and non-EU version. It's probably still not the best given it relies on style rather than ID, but the ID seems dynamic.
Closes 605 "Add pagination support to channel search"
## Previous Attempt
The previous attempt (69de63c4) didn't work because the wunderbar is part of the list component, so it is unmounted when we switch between the Normal and Filtered list, causing it to lose focus while typing.
Also, creating another full-blown ClaimList* component is really redundant (we should be consolidating instead).
## Approach
ClaimListDiscover recently added a new `subSection`, so we can place the filtered `ClaimList` here without causing the wunderbar to unmount.
Wrapped the "lighthouse search with channel_id" into `searchResults.jsx` for now as a quick and isolated solution. When we refactor ClaimList*, we can then consider incorporating into `doSearch`.
The tile placeholder method didn't work well because the component doesn't know how big the page size is, so we always end up rendering 1 placeholder tile, followed by N (= page size) placeholders (if not yet resolved). It's pretty ugly.
Removed comments:
- Incorrect/misleading: "injected item" does not mean "ads". It can be any React component that you want to put at a specific index.
- Redundant: don't explain the syntax. It's very annoying having to maintain the comment when the logic changes.
- Instead of 2 ways to display ads (DOM injection + React method) and having both of them clash, just do it the predictable React way.
- Augment the existing React version to support tile layout + ability to place in last visible slot.
- Consolidate styling code to scss ... DOM manipulations were making it even harder to maintain.
- Removed the need to check for ad-blockers for now. It was being executed every time an ad is displayed, and now that we are displaying ads in more places, the gains doesn't justify the performance loss. Also, it wasn't being done for Recommended ads anyway, so the inconsistency probably means it's not needed in the first place.
Other known issues fixed:
- double ad injection when changing language via nag.
- additional "total-blocking-time" due to ads at startup removed.
- fixed ads not appearing in mobile homepage until navigated away and back to homepage.
- enable ads in channel page.
- support for both List and Tile layout.
Since `triggerBlacklist` is just a simple boolean and `<Ads>` is not doing any additional logic on top of it, it doesn't make sense to pass as a parameter. Just not mount the component -- it's more concise and obvious at the client side.
Ticket: 1018
Reference: 2575c5d
- Restored position of the ad to the 4th slot.
- Moved repeated query out of the map predicate (`droppableProvided ?`)
- For draggables, make the injected item always on top for now. There are draggables with injected items at the moment.
## Cause
When 'selectRecommendedContentForUri' is filtering results against the blocklist, it relies on claim data which could be unresolved yet. It filters to empty results for this scenario, hence the flashing message.
## Change
Just return raw results when claims are not resolved yet, so that the GUI knows it needs to show the placeholders while resolving. After resolving, it'll go through the blocklist filtering again.
## Issue
Closes 1020 strange refresh on signup + youtube sync
It's due to the sync-on-focus.
## Change
Only show the spinner for the initial wallet sync. I thought we can do without the spinner for sync completely, but based on the comments below, better to retain that for the initial sync. I think the rest of the stages don't need to block over a sync call.
```
// Don't claim the reward if sync is enabled until after a sync has been completed successfully
// If we do it before, we could end up trying to sync a wallet with a non-zero balance which will fail to sync
```
This is a follow-up for #1016
Still doesn't affect anything at the moment, but this reduce the amount of work needed when we yank out the homepages from our bundle later.
Currently, homepages are still build as part of the app, so this change doesn't bring much benefit other than to support the wrapper app.
When the service is moved away from the app, we won't have to rebuild the app when homepages change, and also the ui.js bundle would be smaller without the need to code-split.
## Issues
Ad-filtering:
- Filtering was done whether or not ads are injected.
- Constants are repeatedly calculated.
- No short-circuiting in the for-loop.
- No memoization (being called 5-6 times on average due to redux updates, can't avoid that).
Others:
- Potentially passing null claimID to recsys (I think this is the issue that Johnny reported in Slack).
## Changes
- Moved 1-time calculations outside of the function.
- Optimized the filtering function and memoize it.
- Reduce unnecessary props since we are passing the whole `Claim` object already.
- Fix recsys being called when claim is not resolved yet (null claimId).
- Move away from the incorrect `makeSelect*` selectors.
* Use locale/get response to suggest homepage and language switch
* Fix language modal condition
* Fixes from review
* Fixes from review
* Fix gdpr
* string
* Fix multiple options behavior
* Fix gdpr and use only one fetch
* Only show if no languages set or loaded
* pt-br
* Fix ad
* Fix homepage select
* Fix zh langs
Clients can still choose to roll their own way of showing "is fetching", like how ClaimListDiscover displays a whole bunch of placeholder tiles. This just serves as a default.
List-layout is not scrollable, and doesn't look good either. Force to tile-only until we can fix it. If we decide to always use tile-only, then remove the parameter for ScheduledStreams.
- `filteredSubscriptions` was running the filter code whether or not it actually required filtering, because the `!subscriptionFilter` logic is placed in the predicate. While it is a clean one-liner, it is slow when the subs list is huge.
- While at it, moved the code into `getSubscriptionSection` to isolate things.
- The sidebar was resolving the entire subs list, which is super slow for a list of 500+. Since we now have a "Manage Subscriptions" page, just batch-resolve the N visible subs.
- TODO: the code should probably be moved from 'app' to 'sideNavigate'.
The idea of using claim_search to indirectly batch-resolve didn't work out well. There's something wrong with the claim_search pagination where some results are duplicated in multiple pages, while some are missing. It's also returning less results that than the given number of claim ids, so sometimes the infinite scroll breaks.
The `useDualLayout` junk is super confusing to maintain and no longer extensible.
At the expense of making the "livestream + regular" list no longer seamlessly continuous when expanded (or when there just a handful of livestreams), use the new `subSection` feature to inject the livestream tiles. This is far easier to manage and tweak.
## Issues
1. We were manually adding `selectLanguage(state)` as a prop to components used in Settings Page to trigger a render. Flaws:
- Unclear that the unused prop is just to trigger a render.
- Manually adding on a case-by-case basis will break over time, especially when language can now be changed outside of the Settings Page.
2. The translation file fetching is delayed and also takes time, so the GUI will end up having mixed strings on F5, depending on when the fetch completed.
## Approach
Make the app wrapper have a key that's tied to the language and translation data, so the entire app renders when language changes. Seems like a common design in most apps.
## Ticket
921 language refresh / selection issues
## Ticket
968 Truncate views/subs in other areas
## Changes
- Corrected logic for `minThresholdToApply`, which was ignoring the case of "no threshold", causing it to not be truncated in Channel Page. We want to always truncate there due to the smaller cards.
- Missed out handling `ClaimPreviewSubtitle`.
The function argument order can be a bit ugly, but putting it at the back as optional param makes it easier to test without affecting existing clients.
## Ticket
948 wildwest: always show boosting message, move next to category name
## Changes
1. Make "Show less livestreams" share the same space as "Boosted by LBC", instead of only showing either 1.
- It's a bit troublesome to move it next to the filter without tweaking the generic `ClaimListDiscover`, so I think this would be a good compromise.
2. Fix "show less livestreams" being super tiny in mobile.
- I think it is caused by some component-specific changes are being applied at the global level (not sure).
* Bump react-draggable
Old version was giving out console errors for outdated react functions
* Refactor fileRenderFloating
* Merge fileRenderMobile into fileRenderFloating
* Fixes from review
* Attempt fix failed to view live
> _Max date it can do is back to : 2022-02-08 - so don't allow a days value that's higher than this. (hint before selection / submission if possible)_
My initial understanding was that it is ok to set beyond this date (e.g. "1 year"), just that any channels created before Feb 7 will still be able to comment even if they are less than a year old. That feels like ok behavior to me (easier for user to grasp), but turns out setting anything before that date will block all channels.
So, this commit changes the warning message and also blocks the user from finalizing.
This reverts commit b3c4ce05fa.
The suggested 2-list approach broke the search bar because the bar is part of the list, so it gets unmounted while the user is typing. Oops.
* Band-aid: warn about AdGuard blocking our CDN
Getting 50-100 errors per day. This will be a band-aid until the AdGuard fixes it.
* update message
Co-authored-by: Thomas Zarebczan <thomas.zarebczan@gmail.com>
* Move into getLocalStorageSummary + always log
- Move into getLocalStorageSummary to clean up the clutter.
- Always log the localStorage info to get a bigger picture of what's going on with the QuotaExceededError.
* Remove 'findPreviousUploads' - we use the url stored in Redux.
Something I forgot to remove in the past. It also reads from localStorage, so remove since we are trying to avoid touching localStorage.
* Ensure localStorage is not used when uploading
I don't think it's being written when `storeFingerprintForResuming` is disabled, but doing the suggestion nonetheless.
`https://github.com/tus/tus-js-client/issues/315#issuecomment-1046821112`
## Ticket
lbry-desktop 6841
## Issue
If you are already at the homepage and you click the "Home" or "Odysee" logo again, the entire page reloads, causing the whole startup sequence to re-run (lots of fetches).
This can be annoying when not intended (e.g. clicked too many times), as startup is slow for some and we also lose non-persistent Redux data (for debugging).
I believe the requirement was just to reload the homepage tiles, as they might be showing stale ones after a while. A full reload was the quick-and-easy fix.
## Approach
Best not to touch the complicated `ClaimTilesDiscover`, so just clear the search cache key in this scenario. `ClaimTilesDiscover` will then pick this up and perform a new `claim_search`.
## Root-cause?
It doesn't happen on the commit before the Theme change. However, it's possible that the y-pos is reset since we are indeed unmounting the dual list and re-mounting the single list.
Maybe the css got more efficient and we ended up painting more frames than before.
## Fix
Fix by stashing and restoring the the y-position during the expansion.
## Issue
535
## Change
- Header: Use the "channel list undefined" instead of "active channel url undefined" to determine if the button should be "pending".
- App: restore the use of `activeChannelClaim` instead of `activeChannelId`. In the existing design, the latter is never cleared is some situations, so the former is more accurate as it takes the current channel list into account. We might want to hide (not export) `activeChannelId` to avoid this mis-use again.
## Issue
When loading the homepage, I kept seeing a blank page with footer first. Even Google is picking it up.
## Ticket
572 Slow appearance of tiles
## Notes
The tiles were originally delayed to prevent the "Upcoming Livestream" section from causing layout shifts.
With the new theme, the footer would cause a visible shift anyway. Hiding the footer is one solution, but I think not showing anything until the fetch is done is bad because the livestream fetch could stall.
## Why
The playing URI was being cleared every time we leave the File Page, I believe to prevent the floating from continue playing outside of the File Page.
## Approach
Close FileRenderMobile by checking playingUri/primaryURI instead.
For the case of livestreams, just display it.
These are now checked at client side (not CDN side), so not actually an error worth collecting.
Also removed "Uploading the same file from multiple tabs or windows is not allowed." -- no longer exists.
## Issue
534 prevent new channel creation over x channels
## Notes
Also handled from the API call (`doCreateChannel`) in case there are other UI components that create channels.
- Marked optional props properly.
- Re-ordered to make it easier to differentiate "props used in jsx" vs. "from redux".
Separated the commit to make the upcoming diffs easier to read.
Code-splits the module into "dnd.js", reducing the ui.js bundle size. This module is only needed when viewing lists.
## Room for improvement
`ClaimList` can probably improve further by only using the dnd components in "edit" mode.
## Implementation notes
- The modules are not default exports, so the additional chaining to `React.lazy` was required.
- Experimenting with using an Object to store the import so that a single "prettier-ignore" can be used to make it not wrap.
- The FlowFixMe came from the original code. It is unclear why it is needed to resolve the module, but Haffa mentioned it's something related to .flowconfig.
## Ticket
852 Markdown inline images in comments don't work for any channel level
## Change
The prior commit simplified the props from individual comment fields to just 1 `Comment` object, but there was a typo in the parameter where it should be `channel_url` instead of `author_uri`.
- The previous 2MB was a CDN limit (more of a mistake). That has been increased to a far greater number, so we're setting a more reasonable 5MB limit.
- The previous code checks/shows the "size exceeded" message after the file has been uploaded ... in the `catch` block. This will not work since the CDN now allows a 5MB file.
- Fixed by checking the size before actually uploading.
## Issue
When pressing "Done", it will call the upload function, which usually results in a "please select a file" error, or the file being uploaded if a file was selected prior to switching to "Use Url".
- Move stickers and emojis to a single menu comment-selectors on both mobile and desktop
- More style improvements
- Some fixes
- Fix livechat scrolling
- CommentsList needs to return a title with comment amounts
- mobile player dimensions needed to fill in the cover
- hid livestream header for now until figuring out a better presentation
- ~colum-reverse~ was causing problems with MUI's drawer scrolling, so reversed the chat order and made it ~column~ by default
- Hid bottom expand navigation if component not yet opened
- some other style changes in the middle
- Biggest change: Moved mobile player logic outside of fileRenderFloating into its own component fileRenderMobile, since there is no need for all that extra resizing and dragging code (for now, as mobile doesn't have a floating player)
- Moved player to the header height
- Removed rounded borders and margins
- Only pass necessary props
- Created new initialize play redux action
- Removed deprecated ~file app download~ keyboard functionality, moved preventDefault to videojs keyboard events to prevent ~space~ moving down the page
- moved doPrepareEdit incognito and channel calls to separate action
- same with download
- Tooltips
- No major differences between mobile or default returned components so removed condition since mobile style will be changed later on this branch
* Fix avatar occasionally stuck in spaceman
## Issue
Sometimes, we'll see a channel profile (e.g. in upper-right, in channel selector) stuck in the fallback Spaceman image.
This is due to OptimizedImage always starting with a blank src, and updated later when the mounted size has been determined. ChannelThumbnail, which uses OptimizedImage, captured the `onError` due to blank src.
## Fix
Don't mount the <img> until the optimum size has been determined.
* FileThumbnail: skip resolve if thumbnail url is specified
* UriIndicator: skip resolve if channel info is specified
* Notifications: disable batch resolve + use fetched data if available + fallback to resolve if n/a
The fallback is using the individual resolve when no direct data is provided and claim is undefined.
* Patch to restore position upon returning to video until more fully fleshed out fix can be introduced
* Add code to notify other open tabs of position saving
* Fix typo
* Wrap localStorage access in try/catch in event browser settings make it unavailable
* Remove formatting changes
* Move constant from 'pages' to 'player'
* Move dispatch out of try/catch
* Fixed typo
* fix RESOLVE_URIS_COMPLETED, to have one large action instead of hundreds of small ones
* Addressed comments.
* Addressed comments.
* Addressed comments.
Co-authored-by: Asad Umar <au@visuary.fr>
## Ticket
761 Should Posts have embed links
The original code also supported all text modes like PDF, all of which looked really bad, so it's unlikely someone is utilizing it.
Disabling them until a designer can fix 'em.
fixed the issue by removing the useRect, and putting in a resize event, going to try and make the code cleaner by removing all that logic and putting it in a hook.
## Issue
On large screens, the comment field and autoplay countdown can both be visible at the same time. The currently code only stops the timer when the countdown component is not visible on screen.
The page annoyingly navigates away while typing.
## Change
When servicing the timer, check if the current active element is an input type. As far as I know, there is no React equivalent for this.
1. Added size-specific error message.
2. Route whatever Vanwa's error instead of showing "unexpected json token". It's ugly, but at least it contains the reason string.
## 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.
`<div>` cannot be a descendend of `<p>`, and `{subtitle}`s sometimes need to have `<div>`s.
Just switch from `<p>` to `<div>`, and let the client decide when the actual text paragraphs are.
- Memo not required. `resolvingUris` is very dynamic and is a short array anyways.
- Changeg from using `indexOf` to `includes`, which is more concise.
## Issues
- 251 Dragging the floating player is super laggy
Recent changes and/or refactoring combined the effects or added dependancies into the effects, causing them to re-run excessively.
## Changes
- Restored effects to their original behavior.
- Don't perform the position check when dragging -- only do it when released.
- Do proper debouncing for the 'resize' listener -- the previous method was incorrect as a new function is created on each render.
## Changes
- doHandleSyncComplete: only call doGetAndPopulatePreferences when there is new data.
- But for that to work, we'll need to populate preferences at least once. We'll do that in doSignIn.
- We can also remove the "sync/prefs ready" mechanism that was mainly meant for Desktop.
Then came another problem: while trying to spark changes between 2 tabs, `sync/get` was saying "no change" despite the local and server hash being different. I think it is because the both `sync_hash + sync/get` combo is operating on server data, so the hash is the same. I'm guessing this is why we ended up just running doGetAndPopulatePreferences every time before PR, since this flag wasn't correct in this scenario.
- Updated `data.changed` to consider both API results and comparison with local hash.