Skip to content

Commit

Permalink
making nostrize beta from alpha release. tw: fix caching, fix show mo…
Browse files Browse the repository at this point in the history
…re/less, fix shorten text, nprofile encoding
  • Loading branch information
dhalsim committed Sep 10, 2024
1 parent 6fd2492 commit 05722b0
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 178 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Nostrize Browser Extension (Work In Progress)
# Nostrize Browser Extension

Welcome to Nostrize - the browser extension that empowers any website with the [Nostr](https://github.com/nostr-protocol/nostr) experience. Nostrize seamlessly integrates tipping and crowdsourcing capabilities through Bitcoin, making every interaction permissionless. Join us in a world where supporting content and collaborative projects is effortless. Elevate your browsing with the power of Nostr and Bitcoin, and become part of the [Value4Value](https://value4value.info/) movement today.

Expand All @@ -17,6 +17,9 @@ https://github.com/user-attachments/assets/a12b9fa1-e351-462c-b706-d186040ffc6e
* Do you still need to use X/Twitter because everyone is still there?
* Good news: you can use nostr via Nostrize on X/Twitter now! 🤯
* Add your npub or nip05 to your account bio and you are ready to receive zaps
* Follow other Nostrize users directly from their X/Twitter profile
* Read Nostr notes of Nostrize users
* Lightsats integration (Will be a part of our Nostr onboarding)

## Youtube

Expand All @@ -38,7 +41,7 @@ With Nostrize on GitHub, you can:
* Earn payments for your pull requests that address and resolve issues.
* And more features are coming...

### Nostrize Booster
### Nostrize Booster (WIP)

Nostrize Booster is designed for GitHub and may be added for other platforms later.

Expand Down
3 changes: 2 additions & 1 deletion src/components/checkbox/checkbox-wrapper.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as html from "../../imgui-dom/html.js";

export function wrapCheckbox({ input, onclick, text }) {
export function wrapCheckbox({ input, onclick, text, id }) {
return html.div({
id,
classList: "checkbox-container",
children: [
input,
Expand Down
22 changes: 8 additions & 14 deletions src/helpers/nostr.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,16 +329,11 @@ function insertEventIntoDescendingList(sortedArray, event) {
const latestNotesCacheKey = (pubkey) => `nostrize-latest-notes-${pubkey}`;

export function fetchLatestNotes({ pubkey, relays, callback }) {
const cache = getFromCache(latestNotesCacheKey(pubkey));

if (cache) {
return cache;
}
const cacheKey = latestNotesCacheKey(pubkey);
const cachedNotes = getFromCache(cacheKey) || [];

const pool = new SimplePool();

const notesSet = new Set();
const latestNotes = [];
const notesSet = new Set(cachedNotes.map((note) => note.id));

pool.subscribeMany(
relays,
Expand All @@ -347,32 +342,31 @@ export function fetchLatestNotes({ pubkey, relays, callback }) {
kinds: [1],
authors: [pubkey],
limit: 100,
since: cachedNotes.length > 0 ? cachedNotes[0].created_at : undefined,
},
],
{
onevent(event) {
if (notesSet.has(event.id)) {
return;
console.log("already have event", event.id);
}

notesSet.add(event.id);

const index = insertEventIntoDescendingList(latestNotes, event);

console.log(`inserted at index: ${index}`);
const index = insertEventIntoDescendingList(cachedNotes, event);

callback(event, index);
},
oneose() {
console.log("eose, updating cache");

insertToCache(latestNotesCacheKey(pubkey), latestNotes);
insertToCache(cacheKey, cachedNotes);
},
alreadyHaveEvent(id) {
return notesSet.has(id);
},
},
);

return latestNotes;
return cachedNotes;
}
3 changes: 2 additions & 1 deletion src/twitter/profile/notes.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
border-radius: 5px;
margin: 10px;
color: black;
scroll-margin-top: 100px;
}

.n-tw-note .ago {
Expand All @@ -46,6 +47,6 @@
}

.n-tw-note-content a {
color: white;
color: blueviolet;
text-decoration: underline;
}
2 changes: 1 addition & 1 deletion src/twitter/profile/profile.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
background-color: rgb(130, 80, 223);
}

.n-follows-you-indicator {
.n-follows-you-indicator, .n-nostr-profile-button {
font-family: TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: rgb(130, 80, 223);
font-weight: 500;
Expand Down
209 changes: 106 additions & 103 deletions src/twitter/profile/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ async function twitterProfilePage() {
gui.gebid("n-tw-nostr-profile-button")?.remove();
gui.gebid("n-tw-follow-unfollow-button")?.remove();
gui.gebid("n-tw-account-notes")?.remove();
// TODO: remove the nostr mode checkbox
// TODO: remove the notes section
gui.gebid("n-tw-enable-nostr-mode-checkbox")?.remove();
gui.gebid("n-tw-notes-section")?.remove();
};

removeNostrButtons();
Expand All @@ -70,7 +70,7 @@ async function twitterProfilePage() {
return;
}

log("accountName", pageUsername);
log("pageUsername", pageUsername);

let userNameContainer = document.querySelector("div[data-testid='UserName']");

Expand Down Expand Up @@ -110,13 +110,9 @@ async function twitterProfilePage() {
"button[data-testid='userActions']",
);

if (!buttonTobeCloned) {
log("no copy button, probably it is user's account");
const isPageUserTwitterAccount = !buttonTobeCloned;

return;
}

if (!npub && !nip05) {
if (!npub && !nip05 && !isPageUserTwitterAccount) {
log("No Nostr integration found");

if (
Expand Down Expand Up @@ -165,97 +161,104 @@ async function twitterProfilePage() {
timelineNavbar,
pageUserPubkey,
pageUserWriteRelays,
pageUserReadRelays,
settings,
});

// nostr mode is on by default
enableNostrModeCheckbox.insertAdjacentElement("afterend", notesSection);

if (pageUserPubkey === nostrizeUserPubkey) {
log("current page user is the nostrize user");

removeNostrButtons();

return;
}

const metadataEvent = await getMetadataEvent({
cacheKey: pageUserPubkey,
filter: { authors: [pageUserPubkey], kinds: [0], limit: 1 },
relays: nostrizeUserRelays,
});

const handleContainer = setupNostrProfileLink(settings, pageUserPubkey);
const pageUserIsNostrizeUser = pageUserPubkey === nostrizeUserPubkey;

// follows of the account
const pageUserFollowSubscription = getFollowSet({
pubkey: pageUserPubkey,
relays: pageUserWriteRelays,
callback: ({ followSet }) => {
const pageUserFollowsNostrizeUser = followSet.has(nostrizeUserPubkey);

log("pageUserFollowsNostrizeUser", pageUserFollowsNostrizeUser);

if (pageUserFollowsNostrizeUser) {
handleContainer?.append(
wrapInputTooltip({
id: "n-follows-you-indicator",
input: html.span({
text: "Follows you",
classList: "n-follows-you-indicator",
}),
tooltipText: `${pageUsername} follows you on Nostr.`,
}),
);
}
},
});

// follows of the nostrize user
// the button to follow/unfollow
getFollowSet({
pubkey: nostrizeUserPubkey,
relays: nostrizeUserRelays,
timeout: 1000 * 60 * 10, // 10 minutes
callback: ({ followSet, latestEvent }) => {
gui.gebid("n-tw-follow-unfollow-button")?.remove();
const handleContainer = setupNostrProfileLink(
settings,
pageUserPubkey,
pageUserIsNostrizeUser,
pageUserWriteRelays,
);

let userFollowsNostrizeUser = followSet.has(pageUserPubkey);
if (!pageUserIsNostrizeUser) {
getFollowSet({
pubkey: pageUserPubkey,
relays: pageUserWriteRelays,
callback: ({ followSet }) => {
const pageUserFollowsNostrizeUser = followSet.has(nostrizeUserPubkey);

log("pageUserFollowsNostrizeUser", pageUserFollowsNostrizeUser);

if (pageUserFollowsNostrizeUser) {
handleContainer?.append(
wrapInputTooltip({
id: "n-follows-you-indicator",
input: html.span({
text: "Follows you",
classList: "n-follows-you-indicator",
}),
tooltipText: `${pageUsername} follows you on Nostr.`,
}),
);
}
},
});

// follows of the nostrize user
// the button to follow/unfollow

if (!isPageUserTwitterAccount) {
getFollowSet({
pubkey: nostrizeUserPubkey,
relays: nostrizeUserRelays,
timeout: 1000 * 60 * 10, // 10 minutes
callback: ({ followSet, latestEvent }) => {
gui.gebid("n-tw-follow-unfollow-button")?.remove();

let userFollowsNostrizeUser = followSet.has(pageUserPubkey);

const button = wrapInputTooltip({
id: "n-tw-follow-unfollow-button",
input: createTwitterButton(buttonTobeCloned, pageUsername, {
emojiIcon: userFollowsNostrizeUser ? "➖" : "➕",
modalComponentFn: async () => {
const followParams = {
pubkey: nostrizeUserPubkey,
currentFollowEvent: latestEvent,
accountPubkey: pageUserPubkey,
relays: [...nostrizeUserRelays, ...pageUserReadRelays],
log,
};

button.disabled = true;

updateFollowButton(
gui.gebid("n-tw-follow-unfollow-button"),
"⏳",
);

try {
if (userFollowsNostrizeUser) {
await unfollowAccount(followParams);
} else {
await followAccount(followParams);
}
} catch (err) {
alert("Nostrize error on follow/unfollow: " + err);
}
},
}),
tooltipText: `${userFollowsNostrizeUser ? "Unfollow" : "Follow"} ${pageUsername} on Nostr`,
});

const button = wrapInputTooltip({
id: "n-tw-follow-unfollow-button",
input: createTwitterButton(buttonTobeCloned, pageUsername, {
emojiIcon: userFollowsNostrizeUser ? "➖" : "➕",
modalComponentFn: async () => {
const followParams = {
pubkey: nostrizeUserPubkey,
currentFollowEvent: latestEvent,
accountPubkey: pageUserPubkey,
relays: [...nostrizeUserRelays, ...pageUserReadRelays],
log,
};

button.disabled = true;

updateFollowButton(gui.gebid("n-tw-follow-unfollow-button"), "⏳");

try {
if (userFollowsNostrizeUser) {
await unfollowAccount(followParams);
} else {
await followAccount(followParams);
}
} catch (err) {
alert("Nostrize error on follow/unfollow: " + err);
}
},
}),
tooltipText: `${userFollowsNostrizeUser ? "Unfollow" : "Follow"} ${pageUsername} on Nostr`,
gui.insertAfter(button, buttonTobeCloned);
},
});

gui.insertAfter(button, buttonTobeCloned);
},
});
}
}

const lnurlData = await getOrInsertCache({
key: `nostrize-lnurldata-${metadataEvent.id}`,
Expand All @@ -265,27 +268,27 @@ async function twitterProfilePage() {
}),
});

const zapButton = wrapInputTooltip({
id: "n-tw-zap-button",
input: createTwitterButton(buttonTobeCloned, pageUsername, {
if (!isPageUserTwitterAccount) {
const zapButton = wrapInputTooltip({
id: "n-tw-zap-button",
emojiIcon: "⚡️",
modalComponentFn: () =>
zapModalComponent({
user: pageUsername,
metadataEvent,
relays: nostrizeUserRelays,
lnurlData,
log,
settings,
}),
}),
tooltipText: `Zap ${pageUsername}`,
});

gui.insertAfter(zapButton, buttonTobeCloned);
input: createTwitterButton(buttonTobeCloned, pageUsername, {
id: "n-tw-zap-button",
emojiIcon: "⚡️",
modalComponentFn: () =>
zapModalComponent({
user: pageUsername,
metadataEvent,
relays: nostrizeUserRelays,
lnurlData,
log,
settings,
}),
}),
tooltipText: `Zap ${pageUsername}`,
});

pageUserFollowSubscription.close();
gui.insertAfter(zapButton, buttonTobeCloned);
}
}

twitterProfilePage().catch((e) => console.error(e));
Loading

0 comments on commit 05722b0

Please sign in to comment.