Commit graph

420 commits

Author SHA1 Message Date
Rafael
f9d32abbf6 Fix embed end links 2022-03-28 14:39:36 -04:00
Anthony
63a4a597a9 passing meme actually isnt required 2022-03-25 14:44:13 -04:00
Anthony
e921d58f73 dont open meme link in new tab 2022-03-25 14:44:13 -04:00
Thomas Zarebczan
aeb475ec2e
temp: pass random param
There are some channels returning 304, and they can't stream without this param
2022-03-23 14:48:45 -04:00
infinite-persistence
c0015ca442 Category: Artists 2022-03-21 09:51:50 -04:00
Thomas Zarebczan
496c90db0e
Fix channel display on Twitter OG 2022-03-18 09:54:03 -04:00
infinite-persistence
fdb5658df6 Reduce verbosity of tus errors now that we know the locked problem is with tusd 2022-03-18 08:52:49 -04:00
Thomas Zarebczan
ab67e47794
Copy Pasta! 2022-03-16 22:38:18 -04:00
Thomas Zarebczan
b5184078b8
Take 3 og for livestream 2022-03-16 22:24:26 -04:00
Thomas Zarebczan
a6c832bac1
take 2 twitter live test 2022-03-16 19:28:45 -04:00
Thomas Zarebczan
c1e97ee451
test twitter lives 2022-03-16 18:46:46 -04:00
Rafael
b7f9152dca Improve livestream external embeds 2022-03-16 16:36:50 -04:00
infinite-persistence
745e40a83e
Move blocker flag to redux
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.
2022-03-16 16:48:26 +08:00
infinite-persistence
f8b54cabbc FYP: update i18n entry for the readme 2022-03-15 21:03:31 -07:00
infinite-persistence
1e67a5cc7f
[on hold recsys work] Recommended For You (#782)
* 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>
2022-03-15 15:07:31 -04:00
mayeaux
4a9ba6555b
Various touchups/fixes of membership functionality (#1066)
* 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>
2022-03-14 22:38:45 -04:00
infinite-persistence
de29e323a8
Homepage-Following: insert instead of replace when ad-blocker is detected (#1092)
* 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.
2022-03-14 14:25:51 -04:00
infinite-persistence
ea7a6cb04f
Fix tile misaligned due to ad-blockers. 2022-03-10 22:03:19 +08:00
infinite-persistence
ea8af5aa89
Handle case where ad-cleanup fails (redo)
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
2022-03-10 21:54:12 +08:00
mayeaux
fb3a73d8a7
Membership subscriptions (#812)
Enter: Odysee Premium.
2022-03-09 13:05:37 -05:00
infinite-persistence
15bd26399f Handle case where ad-cleanup fails
## Issue
Double ads on screen

## Reproduce
- Pre re-design:
    - Change "Only Language" from tne locale nag.
- Post re-design:
    - Follow a bunch of channels with active livestreams. The homepage ad will show 2 ads stack on each other, with second one invisible.

Both should be equivalent, just different UI/style.

## Analysis
In both cases, it is due to `removeIfExists` failing to remove the element if the ad script hasn't run yet.

This can happen when the component is re-mounted immediately after the ad script was added. When the effect-cleanup runs, the script have not started or is running halfway.

Aside: The need to run `removeIfExists` further strengthens my hunch that the script is meant to live throughout the lifetime of the app, with it populating the given div as we navigate. But just my guess.

## Approach
Clean up before adding the script as well. This covers any missed elements from the previous cleanup.

The drawback is that this approach assumes there will only be 1 ad per page, but that's pretty much the case with the existing `removeIfExists` approach.
2022-03-09 08:47:13 -05:00
infinite-persistence
a98dc18fc6
Fix EU ad and minor tweaks
- 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.
2022-03-09 18:44:38 +08:00
infinite-persistence
73552e35f9
Ad: remove unused style ID
- Removed "customAniviewStyling"
    - No longer exists -- it was from the old DOM manipulation method.

- Removed "with no tileLayout it indicates sidebar ad"
    - Misleading and not useful. I can easily set the sidebar ad to Tile if we wanted to (it used to be in Tile, we changed to save space). So, every time we change the style, we need to update the comment??

    - The sidebar is not the only place that List layout is used -- there's Channel and Category pages, which allows either layout.
2022-03-09 16:02:11 +08:00
infinite-persistence
d210e81ded
useBrowserNotifications: don't set state if already unmounted.
Closes 1053

We can't cancel a promise, but we could prevent setting orphaned states by taking advantage of closures to detect if we have unmounted.

Reference: https://juliangaramendy.dev/blog/use-promise-subscription
2022-03-09 13:22:54 +08:00
Anthony
af8d742b75 add some comments for documentation 2022-03-08 10:53:52 -05:00
infinite-persistence
0fa20114be Re-enable for Firefox Android
Since we are temporarily disabling the floating ad, it means that the invisible close button issue in Firefox Android is also temporarily not an issue.
2022-03-08 10:53:52 -05:00
infinite-persistence
cdcedb8063 Don't use EU script on mobile as it breaks the app 2022-03-08 10:53:52 -05:00
infinite-persistence
0143b63c74 Ads: replace DOM manipulations with React components
- 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.
2022-03-08 10:53:52 -05:00
infinite-persistence
e2f73a30c6 Remove triggerBlacklist
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.
2022-03-08 10:53:52 -05:00
infinite-persistence
1b0b9cad94 Cleanup ad container css
- Non hardcoded way to reserve space.
- Replace hardcoded margin.
2022-03-08 10:53:52 -05:00
infinite-persistence
f979f9b575 Code cleanup; no functional change 2022-03-08 10:53:52 -05:00
infinite-persistence
8772ebe0ad Update CORS for homepage api so localhost works 2022-03-03 21:22:30 -05:00
Thomas Zarebczan
71589721ef
Fix logic 2022-03-03 10:23:40 -05:00
infinite-persistence
66e0b84e12
Grab homepages from the content API (#1016)
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.
2022-03-03 09:22:59 -05:00
Thomas Zarebczan
a01e4bad78
update iframe type + sentry 2022-03-02 12:45:26 -05:00
infinite-persistence
27f70d5f90
tus: try longer retry delays to maybe avoid lockups (#1012) 2022-03-02 11:03:49 -05:00
infinite-persistence
59e83f3fa8
tus: sentry improvements
## Ticket
910

## Changes
- Change the "message" from a generic "tus-upload" to more specific ones like "tus: failed to resume upload". These are grouped as "Events" in sentry, so we can isolate and search for them easily.

- Pass more info to Sentry (previously only available from Slack). It is still good to send to both, since some browsers block Sentry even without blocker extensions.

- Reduce verbosity of Slack's

## Notes
- Was unable to change the "unknown" problem mentioned in the ticket. The API does not accept `new Error('xxx')`, even though that's being mentioned by many in the forums. It might be due to the version of Sentry that we are using.

- To search for tus issues, go to "Issues" and query `message:tus*`. Results are collapsed per event, so click on the item of interest, then click "Events" at the upper right to see all occurrences of the same problem.
2022-02-27 17:40:19 +08:00
infinite-persistence
3f8dfd5b21 Stop logging localStorage sizes
The issue has been solved, plus we've collected enough data.
2022-02-26 10:34:12 -05:00
Thomas Zarebczan
b4b7803684
Remove FB image test 2022-02-24 10:04:37 -05:00
infinite-persistence
77aa405fc6
Increase specificity of og:type (#955)
Doesn't seem to do much, but it is what others do, so might as well be specific.
2022-02-24 00:11:57 -05:00
Thomas Zarebczan
3d23c7f78b
Test FB preview
Can determine image type dynamically later, just wanted to test out to see if previews are full screen.
2022-02-23 18:17:08 -05:00
infinite-persistence
c74dbbb68a
tus: QuotaExceededError (#935)
* 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`
2022-02-22 10:11:22 -05:00
infinite-persistence
c1fed3f4df
Undo tus-sentry experiment since it completely broke 2022-02-22 00:43:57 +08:00
infinite-persistence
0ae015b7a5
Revert "tus: remove 'uploader' param -- seems to be breaking Sentry."
This reverts commit f14e7ad0ec.
2022-02-21 23:02:59 +08:00
infinite-persistence
f14e7ad0ec
tus: remove 'uploader' param -- seems to be breaking Sentry. 2022-02-21 22:28:03 +08:00
infinite-persistence
5b81346e59 Sentry: fix tus errors
The first parameter should be the error object, not a general label.
2022-02-21 00:12:37 -08:00
dependabot[bot]
7612722263
Bump url-parse from 1.5.3 to 1.5.7 in /web (#926)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-19 14:40:32 -05:00
infinite-persistence
636b00f9db
Sync up with recent homepage string changes 2022-02-18 20:00:37 +08:00
dependabot[bot]
5c5b46ddb3
Bump follow-redirects from 1.14.7 to 1.14.8 in /web (#866)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 14:23:57 -05:00
infinite-persistence
85ef16026d tus: log reason for QuotaExceededError
We no longer ask tus to save the upload URL since December, so there should no reason for it to be writing to localStorage.

Adding more logs to determine what is the actual cause -- localStorage being full, or not available. Neither should affect the upload but they are the only known causes for that error message, so try to narrow down the investigation path.
2022-02-14 09:41:46 -08:00
Thomas Zarebczan
c34840a4d4
Fix some RSS issues 2022-02-13 15:25:18 -05:00
infinite-persistence
d102cbe802
Fix broken resolves due to escaped characters (#849)
## Issue
`/$/embed/尾崎豊----大阪球場ライブ%E3%80%801_6/bfd63daa9453bb1a11674ca8a7c5f5dd6b49d024?r=2ituZftpdG18f1TBADDbCaaEZ9ecYYYm` wasn't working

## Change
Probably need to revisit this properly, but for now, grab the `requestPath` that's needed for resolving before escaping the characters.

Tested that `http://localhost:1337/$/search?q=%22\/%3E%3Cimg%20s+src+c=x%20on+onerror+%20=alert(1)+\%3E` would still be blocked.
2022-02-11 21:26:36 -05:00
mayeaux
0c4f85fe53
MAKE ODYSEE EVEN MORE BEAUTIFUL (#539)
WE LOVE YOU RAPHAEL FOR MAKING THIS HAPPEN!
2022-02-11 13:50:55 -05:00
infinite-persistence
02accb5c79 Strip timestamp from url when resolving for OG
`Lbry.resolve` won't work with timestamps in the url.
2022-02-09 10:11:31 -05:00
Thomas Zarebczan
bb14fe30b4
update videoplayer 2022-02-08 13:34:37 -05:00
Rafael
07eaba5a89 Unscape uri for resolve 2022-02-08 13:34:26 -05:00
infinite-persistence
dbeb102dc4
clean up URLs 2022-02-08 11:04:25 -05:00
infinite-persistence
57bcf6bc03 Update description in PWA 2022-02-07 07:29:11 -08:00
Thomas Zarebczan
ffcf09efd0 category updates
thx Drew
2022-02-03 11:02:59 -05:00
infinite-persistence
fae68d40fd Category: Featured 2022-02-03 11:02:59 -05:00
Rafael
e37a6c66be Fix embed params regex again 2022-02-01 15:52:39 -05:00
Rafael
e1b6c5149a Fix Regex for claimUrl embed url params 2022-02-01 09:02:57 -05:00
Rafael
b30a8568e5 Fix embed url param parsing 2022-01-31 14:22:39 -05:00
Thomas Zarebczan
92f0fd8745
More cleanup 2022-01-31 11:39:03 -05:00
Thomas Zarebczan
5ee2f40608
Take 2 encoding test 2022-01-29 15:24:35 -05:00
Thomas Zarebczan
185c2d8496
encode oembed full url 2022-01-29 15:04:19 -05:00
infinite-persistence
d68be6e9af
tus: route errors to sentry
Per discussion with Andrey
2022-01-24 12:25:54 +08:00
Thomas Zarebczan
784711c4e3
Mobile ads on Android too 2022-01-19 10:20:07 -05:00
infinite-persistence
adc9575504
Category-metadata: add stub for Education + cleanup old categories (#735) 2022-01-19 09:04:15 -05:00
David Granado
179bd44665
Clean invisible chars and adjust "__" for server and client use (#715)
* Rewrite __ to be usable on server side

* Add changelog entry

* Clean invisible characters from primaryModValue

* Revert "Rewrite __ to be usable on server side"

This reverts commit 53f63c01f3b56c5530955323612826c0ac5dc5d3.

* Make pass-through placeholder for __ fn until it can be adapted for node.

* Switch messagages to inline interpolation until i18n done

Co-authored-by: Thomas Zarebczan <tzarebczan@users.noreply.github.com>
2022-01-18 12:09:59 -05:00
Thomas Zarebczan
2eadd986b4
ad adjustments per vidcrunch
confirming what to do with the mobile tag...
2022-01-18 09:56:58 -05:00
David Granado
783520f734
Adjust meta data to allow search pages to reflect search term (#713)
* Adjust meta data to allow search pages to reflect search term

* Update changelog

* Address empty query string case and pass query string to append to og:url

Co-authored-by: Thomas Zarebczan <tzarebczan@users.noreply.github.com>
2022-01-17 12:40:18 -05:00
David Granado
2b9fd723f9
Upgrade nodemon to latest and add --inspect flag for remote debugging (#714) 2022-01-17 08:41:44 -05:00
infinite-persistence
c1af19c7b9
Creative Arts strings 2022-01-17 09:28:02 +08:00
dependabot[bot]
e57ebbc74f
Bump follow-redirects from 1.13.0 to 1.14.7 in /web (#709)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.13.0 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.13.0...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-15 13:02:05 -05:00
infinite-persistence
d14470830c
tus: reduce chunk size (25MB -> 10MB)
With the throughput tweaks at the backend, it seems like the number of "file is locked" errors have reduced.

The next thing to try is to reduce the chunk size, hoping that file writes would be faster, reducing the lock duration from causing a timeout.
2022-01-15 14:44:15 +08:00
mayeaux
ae976c377e
EU ads (#700)
* add new ad

* bugfix

* prioritize eu ad over mobile ad

* replace frontpage ad with EU ad

* bugfix checking for EU
2022-01-14 14:21:17 -05:00
infinite-persistence
91d0eb30b8
tus: remove multi-tab assumption + pass original err msg
Completely remove any assumptions of multi-tab uploading from server status (should have done it previously, but wanted to be conservative). This should make it less confusing to the user.

The real issue still remains -- the upload is somehow locked at the backend.

Also, when we override the error to present a user-friendly message to the user, pass the original error to the log (just in case it gives extra info).
2022-01-13 09:57:45 +08:00
infinite-persistence
238f6b2eda
tus: adjust retry delay + remove logging
From the logs, it seems like the second retry (5s) fixes the "normal" cases, so just remove the first retry (0s).

Also from the logs, if a retry doesn't work by the third attempt (10s), it's most likely the "locked" case and retrying further doesn't help. So, reduce one more useless retry attemp.

Removed logging since we've gathered enough data, and that this hook is expected to be hit a lot, so we don't want to clog the logs.
2022-01-13 09:43:29 +08:00
infinite-persistence
c90c5bcc2a
Route markdown to v1 (#680)
I think I just forgot to do it the first time.
2022-01-12 10:31:46 -05:00
infinite-persistence
431f55ef26
Delete pixel experiment (#683) 2022-01-12 10:14:44 -05:00
infinite-persistence
6bd384b01a
TUS: retry on 423_locked to try address "failed to upload chunk"
## Background
Per developer of `tus-js-client`, it is normal to occasionally encounter upload errors. The auto-retry mechanism is meant to address this.

While implementing tab-lock to prevent multiple uploads of the same file, 423_locked was used to detect this scenario. But 423_locked could also mean "the server is busy writing the chunk" (per discussion with Randy), so we kind of disabled the auto-retry mechanism accidentally.

Meanwhile, from a prior discussion with Randy, one of the chunk-writing duration took 3 minutes. Our current maximum of "retry after 15s" wouldn't help.

## Change
1. Given that tab-locking was improved recently and no longer reliant on the server error messages (we use secure storage to mark a file as locked), reverted the change to "skip retry on 409/423". This is now back to normal recommended behavior.
2. `tus-js-client` currently does not support variable retry delay, otherwise we could prolong the delay if the error was 423. Since we know it could take up to 3 minutes, and that we don't know if it's file-size dependant, just add another 30s retry and put a friendlier message asking the user to retry themselves after waiting a bit.
2022-01-10 16:46:57 +08:00
infinite-persistence
46c7c193be
Log the status code for the retry 2022-01-10 11:50:29 +08:00
infinite-persistence
47043bc965
Remove 'retryTimeout' - that's just the timer ID, nothing useful 2022-01-10 11:39:34 +08:00
mayeaux
58bdcbd1ed
Reduce triple call to single call, improve video loading, fix embed play button being off-center (#546)
Lots of optimizations and cleanup for the player. If we run into any strange issues, can revert.
2022-01-06 14:28:27 -05:00
infinite-persistence
01459d906a
tus: Get more information from publish errors 2022-01-06 15:39:51 +08:00
infinite-persistence
555bde87f8
tus: make chunk size multiples of 256KiB
Our current chunk size is 25,000,000.

Google and S3 documentation suggests the chunk size to be multiples of 256KiB. MongoDB too.  We aren't using any of those, but I guess no harm doing the same.  From the logs, the values "25,000,000" and "50,000,000" seems to be common.
2022-01-06 15:39:51 +08:00
Thomas Zarebczan
d4866b09bb
update embedly referrer param 2022-01-05 10:58:23 -05:00
infinite-persistence
c6fb204d11 Skip checking DIST_ROOT twice
f0cd1592 did an additional call instead of replacement.

Aside: the 1 hour value only has effect in dev instances. For prod, CloudFlare seems to override that to 4 hours.
2022-01-05 09:00:28 -05:00
Anthony
ec5a9802fc
Refactor ad implementation, fix two bugs (#616) 2022-01-05 16:15:08 +08:00
Anthony
cac05d5714 more touchups 2022-01-04 18:05:10 -05:00
Anthony
e3395e31ba refactor ad implementation 2022-01-04 18:05:10 -05:00
Anthony
28bcb96ec7 autoscroll on home page and dont run ads js at all for firefox android 2022-01-04 18:05:10 -05:00
Dan Peterson
24cc07c09b escape referrerQuery in the oEmebed xml generator 2022-01-04 17:19:55 -05:00
Dan Peterson
3744f26295 Escape/encode referrerQuery 2022-01-04 17:19:55 -05:00
infinite-persistence
e5a2e3961e Remove unused items 2022-01-04 08:54:30 -05:00
infinite-persistence
5948ee0d80
i18n: restore ability to retrieve new i18n strings
## 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).
2022-01-03 10:36:12 +08:00
infinite-persistence
5aa6827258
NagNoUser i18n update 2021-12-30 20:42:53 +08:00
Dan Peterson
60430b5267 clean up dupe code + make sure failing analytics doesn't throw subscription error. 2021-12-29 15:45:10 -05:00
Dan Peterson
c22a3048dc Make sure user is available (ie. backend api not down) 2021-12-29 15:45:10 -05:00