From ef3b7f2d3db1d328c1704cc3c085403726423336 Mon Sep 17 00:00:00 2001 From: Jonathan Staab Date: Sat, 21 Jan 2023 11:15:10 -0800 Subject: [PATCH] Add analytics --- README.md | 14 ++++++++- src/App.svelte | 38 +++++++++++++++--------- src/agent/data.js | 8 +++-- src/agent/keys.js | 9 ++++-- src/app/index.js | 4 +-- src/app/ui.js | 29 +++++++++++++++++- src/main.js | 9 +++--- src/partials/Channel.svelte | 52 +++++++++++++++++++++------------ src/partials/Like.svelte | 2 +- src/partials/Note.svelte | 13 +++++---- src/partials/Room.svelte | 4 +-- src/routes/Chat.svelte | 4 ++- src/routes/ChatRoom.svelte | 3 +- src/routes/Login.svelte | 6 ++-- src/routes/Messages.svelte | 45 +++++++++++++++++----------- src/routes/Person.svelte | 27 ++++++++--------- src/routes/RelayList.svelte | 2 +- src/routes/Settings.svelte | 10 +++++++ src/views/ChatEdit.svelte | 7 ++--- src/views/PersonSettings.svelte | 5 ++-- 20 files changed, 194 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 14aa04cb..0b852dbc 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,11 @@ If you like Coracle and want to support its development, you can donate sats via - [ ] Add Labs tab with cards for non-standard features - Time travel - see events as of a date/time + +# Bugs + +- [ ] Sync mentions box and in-reply mentions + # Changelog ## Current @@ -53,7 +58,14 @@ If you like Coracle and want to support its development, you can donate sats via - [ ] Add petnames for channels - [ ] Add back button - [ ] Create Room -> open modal, choose dm or public room - - [ ] Add DM button to profile pages + - [x] Add DM button to profile pages +- [ ] Linkify bech32 entities +- [ ] linkify dm page header +- [ ] Add lock/unlock icon to channel header +- [ ] Add notification for dms +- [ ] Default to network/following +- [ ] Add analytics +- [ ] Allow disabling error reporting/analytics ## 0.2.7 diff --git a/src/App.svelte b/src/App.svelte index 5fa3c8dc..2f7b2b54 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -2,7 +2,7 @@ import "@fortawesome/fontawesome-free/css/fontawesome.css" import "@fortawesome/fontawesome-free/css/solid.css" - import {find, pluck} from 'ramda' + import {find, nthArg, pluck} from 'ramda' import {onMount} from "svelte" import {writable, get} from "svelte/store" import {fly, fade} from "svelte/transition" @@ -12,7 +12,7 @@ import {displayPerson, isLike} from 'src/util/nostr' import {timedelta, now} from 'src/util/misc' import {keys, user, pool, getRelays} from 'src/agent' - import {modal, toast, settings, alerts, messages} from "src/app" + import {modal, toast, settings, logUsage, alerts, messages} from "src/app" import {routes} from "src/app/ui" import Anchor from 'src/partials/Anchor.svelte' import Spinner from 'src/partials/Spinner.svelte' @@ -105,9 +105,21 @@ } }) + const unsubHistory = globalHistory.listen(({location}) => { + if (!location.hash) { + // Remove identifying information, e.g. pubkeys, event ids, etc + const name = location.pathname.slice(1) + .replace(/(npub|nprofile|note|nevent)[^\/]+/g, (_, m) => `<${m}>`) + + logUsage(btoa(['page', name].join(':'))) + } + }) + const unsubModal = modal.subscribe($modal => { // Keep scroll position on body, but don't allow scrolling if ($modal) { + logUsage(btoa(['modal', $modal.type].join(':'))) + // This is not idempotent, so don't duplicate it if (document.body.style.position !== 'fixed') { scrollY = window.scrollY @@ -123,6 +135,7 @@ return () => { clearInterval(interval) + unsubHistory() unsubModal() } }) @@ -260,7 +273,7 @@ modal.set({form: 'note/create'})}> + on:click={() => modal.set({type: 'note/create'})}> @@ -268,27 +281,24 @@ {#if $modal} - {#if $modal.note} + {#if $modal.type === 'note/detail'} {#key $modal.note.id} {/key} - {:else if $modal.form === 'note/create'} + {:else if $modal.type === 'note/create'} - {:else if $modal.form === 'relay'} + {:else if $modal.type === 'relay/add'} - {:else if $modal.form === 'signUp'} + {:else if $modal.type === 'signUp'} - {:else if $modal.form === 'room/edit'} + {:else if $modal.type === 'room/edit'} - {:else if $modal.form === 'privkeyLogin'} + {:else if $modal.type === 'login/privkey'} - {:else if $modal.form === 'pubkeyLogin'} + {:else if $modal.type === 'login/pubkey'} - {:else if $modal.form === 'person/settings'} + {:else if $modal.type === 'person/settings'} - {:else if $modal.message} -

{$modal.message}

- {/if}
{/if} diff --git a/src/agent/data.js b/src/agent/data.js index fd2c802e..7aa7706b 100644 --- a/src/agent/data.js +++ b/src/agent/data.js @@ -8,10 +8,10 @@ import {personKinds, Tags, roomAttrs} from 'src/util/nostr' export const db = new Dexie('agent/data/db') -db.version(12).stores({ +db.version(13).stores({ relays: '++url, name', alerts: '++id, created_at', - messages: '++id, pubkey', + messages: '++id, pubkey, recipient', people: '++pubkey', rooms: '++id, joined', }) @@ -157,7 +157,9 @@ const processRoomEvents = async events => { } const processMessages = async events => { - const messages = ensurePlural(events).filter(e => e.kind === 4) + const messages = ensurePlural(events) + .filter(e => e.kind === 4) + .map(e => ({...e, recipient: Tags.from(e).type("p").values().first()})) if (messages.length > 0) { await db.messages.bulkPut(messages) diff --git a/src/agent/keys.js b/src/agent/keys.js index cb3ad55c..9bd9285c 100644 --- a/src/agent/keys.js +++ b/src/agent/keys.js @@ -16,10 +16,12 @@ const setPrivateKey = _privkey => { } const setPublicKey = _pubkey => { - signingFunction = async event => { - const {sig} = await window.nostr.signEvent(event) + if (window.nostr) { + signingFunction = async event => { + const {sig} = await window.nostr.signEvent(event) - return sig + return sig + } } pubkey.set(_pubkey) @@ -59,6 +61,7 @@ const getCrypt = () => { ? nip04.decrypt($privkey, pubkey, message) : await window.nostr.nip04.decrypt(pubkey, message) } catch (e) { + console.error(e) return `` } }, diff --git a/src/app/index.js b/src/app/index.js index d6635ec8..bb9841e9 100644 --- a/src/app/index.js +++ b/src/app/index.js @@ -6,13 +6,13 @@ import {renderContent} from 'src/util/html' import {Tags, displayPerson, findReplyId} from 'src/util/nostr' import {user, people, getPerson, getRelays, keys} from 'src/agent' import defaults from 'src/agent/defaults' -import {toast, routes, modal, settings} from 'src/app/ui' +import {toast, routes, modal, settings, logUsage} from 'src/app/ui' import cmd from 'src/app/cmd' import alerts from 'src/app/alerts' import messages from 'src/app/messages' import loaders from 'src/app/loaders' -export {toast, modal, settings, alerts, messages} +export {toast, modal, settings, alerts, messages, logUsage} export const login = async ({privkey, pubkey}, usingExtension = false) => { if (privkey) { diff --git a/src/app/ui.js b/src/app/ui.js index 1a323cb9..3a7ab6d4 100644 --- a/src/app/ui.js +++ b/src/app/ui.js @@ -1,4 +1,5 @@ -import {prop} from "ramda" +import Bugsnag from "@bugsnag/js" +import {prop, nthArg} from "ramda" import {uuid} from "hurdak/lib/hurdak" import {navigate} from "svelte-routing" import {nip19} from 'nostr-tools' @@ -54,6 +55,32 @@ export const modal = { // Settings, alerts, etc export const settings = synced("coracle/settings", { + reportAnalytics: true, showLinkPreviews: true, dufflepudUrl: import.meta.env.VITE_DUFFLEPUD_URL, }) + +// Wait for bugsnag to be started in main +setTimeout(() => { + Bugsnag.addOnError(event => { + if (window.location.host.startswith('localhost')) { + return false + } + + if (!get(settings).reportAnalytics) { + return false + } + + return true + }) +}) + +const session = Math.random().toString().slice(2) + +export const logUsage = name => { + const {dufflepudUrl, reportAnalytics} = get(settings) + + if (reportAnalytics) { + fetch(`${dufflepudUrl}/usage/${session}/${name}`, {method: 'post' }) + } +} diff --git a/src/main.js b/src/main.js index d80f2396..536970a4 100644 --- a/src/main.js +++ b/src/main.js @@ -1,13 +1,14 @@ import 'src/app.css' import Bugsnag from "@bugsnag/js" -import App from 'src/App.svelte' - -// Annoying global always fails silently. Figure out an eslint rule instead -window.find = null Bugsnag.start({apiKey: "2ea412feabfe14dc9849c6f0b4fa7003"}) +import App from 'src/App.svelte' + +// Annoying global always fails silently. TODO: figure out an eslint rule instead +window.find = null + const app = new App({ target: document.getElementById('app') }) diff --git a/src/partials/Channel.svelte b/src/partials/Channel.svelte index 10f9c91b..61c0aa48 100644 --- a/src/partials/Channel.svelte +++ b/src/partials/Channel.svelte @@ -1,9 +1,10 @@ { - modal.set({form: 'signUp'}) + modal.set({type: 'signUp'}) } const pubkeyLogIn = () => { - modal.set({form: 'pubkeyLogin'}) + modal.set({type: 'login/pubkey'}) } diff --git a/src/routes/Messages.svelte b/src/routes/Messages.svelte index 8996c4c2..460dff0a 100644 --- a/src/routes/Messages.svelte +++ b/src/routes/Messages.svelte @@ -1,11 +1,11 @@ { - modal.set({form: 'person/settings', person}) + modal.set({type: 'person/settings', person}) } @@ -93,8 +94,8 @@
-
-
+
+

{displayPerson(person)}

@@ -108,21 +109,21 @@
{#if $user?.pubkey === pubkey && keys.canSign()} - - Edit - - {/if} - {#if $user && $user.pubkey !== pubkey} - - {/if} - {#if $user?.petnames && keys.canSign()} -
+ + Edit profile + + {:else if $user && keys.canSign()} + + + + + + {#if following} {:else} {/if} -
{/if}
diff --git a/src/routes/RelayList.svelte b/src/routes/RelayList.svelte index 27acc968..1dd02a74 100644 --- a/src/routes/RelayList.svelte +++ b/src/routes/RelayList.svelte @@ -73,7 +73,7 @@

Your relays

- modal.set({form: 'relay', url: q})}> + modal.set({type: 'relay/add', url: q})}> Add Relay
diff --git a/src/routes/Settings.svelte b/src/routes/Settings.svelte index a07809dc..a906707d 100644 --- a/src/routes/Settings.svelte +++ b/src/routes/Settings.svelte @@ -56,6 +56,16 @@ hosting images and loading link previews.

+
+
+ Report Errors and Analytics + +
+

+ Keep this enabled if you would like the Coracle developers to be able to + know what features are used, and to diagnose and fix bugs. +

+
diff --git a/src/views/ChatEdit.svelte b/src/views/ChatEdit.svelte index dbbb2aee..c154ded4 100644 --- a/src/views/ChatEdit.svelte +++ b/src/views/ChatEdit.svelte @@ -1,14 +1,13 @@ diff --git a/src/views/PersonSettings.svelte b/src/views/PersonSettings.svelte index 44360f84..f1f773c7 100644 --- a/src/views/PersonSettings.svelte +++ b/src/views/PersonSettings.svelte @@ -9,8 +9,9 @@ import {modal} from 'src/app' import cmd from 'src/app/cmd' + const muffle = $user.muffle || [] const muffleOptions = ['Never', 'Sometimes', 'Often', 'Always'] - const muffleValue = parseFloat(first($user.muffle.filter(t => t[1] === $modal.person.pubkey).map(last)) || 1) + const muffleValue = parseFloat(first(muffle.filter(t => t[1] === $modal.person.pubkey).map(last)) || 1) const values = { // Scale up to integers for each choice we have @@ -22,7 +23,7 @@ // Scale back down to a decimal based on string value const muffleValue = muffleOptions.indexOf(values.muffle) / 3 - const muffleTags = $user.muffle + const muffleTags = muffle .filter(t => t[1] !== $modal.person.pubkey) .concat([["p", $modal.person.pubkey, muffleValue.toString()]]) .filter(t => last(t) !== "1")