Skip to content

Commit

Permalink
new navigation bar design (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
bob2402 authored Jul 15, 2024
1 parent 9b7373d commit 037788a
Show file tree
Hide file tree
Showing 20 changed files with 684 additions and 798 deletions.
33 changes: 22 additions & 11 deletions app/UI/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Setting } from "./setting.tsx";
import { getCurrentSignInCtx, getSignInState, setSignInState } from "./sign-in.ts";
import { SecondaryBackgroundColor } from "./style/colors.ts";
import { LamportTime } from "../time.ts";
import { InstallPrompt, NavBar } from "./nav.tsx";
import { InstallPrompt } from "./nav.tsx";
import { Component } from "preact";
import { PublicMessageContainer } from "./public-message-container.tsx";
import { ChatMessage } from "./message.ts";
Expand All @@ -38,8 +38,8 @@ import {
InvalidKey,
NostrAccountContext,
NostrKind,
PublicKey,
} from "@blowater/nostr-sdk";
import { NewNav } from "./nav.tsx";

export async function Start(database: DexieDatabase) {
console.log("Start the application");
Expand Down Expand Up @@ -180,7 +180,7 @@ export class App {
console.log(relayConfig.getRelayURLs());

// init conversation list
const conversationLists = new DM_List(args.ctx);
const conversationLists = new DM_List(args.ctx, args.database);
const err = conversationLists.addEvents(all_events, false);
if (err instanceof InvalidEvent) {
console.error(err);
Expand Down Expand Up @@ -437,7 +437,13 @@ export class AppComponent extends Component<AppProps, {
return false;
}
const relays = app.database.getRelayRecord(e.id);
return relays.has(model.currentRelay) &&
let has = relays.has(model.currentRelay);
if (model.currentRelay[model.currentRelay.length - 1] == "/") {
has = relays.has(
model.currentRelay.slice(0, model.currentRelay.length - 1),
);
}
return has &&
!app.database.isDeleted(e.id, this.state.admin);
},
),
Expand All @@ -454,7 +460,7 @@ export class AppComponent extends Component<AppProps, {
},
),
)}
relay_url={model.currentRelay}
relay_url={model.currentRelay.toString()}
bus={app.eventBus}
/>
);
Expand Down Expand Up @@ -485,14 +491,19 @@ export class AppComponent extends Component<AppProps, {

const final = (
<div class={`h-screen w-full flex`}>
<NavBar
publicKey={app.ctx.publicKey}
<NewNav
currentSpaceURL={new URL(model.currentRelay)}
spaceList={Array.from(app.pool.getRelays()).map((r) => r.url)}
activeNav={model.navigationModel.activeNav}
profile={app.database.getProfileByPublicKey(app.ctx.publicKey, model.currentRelay)}
currentConversation={model.dm.currentConversation}
getters={{
getProfileByPublicKey: app.database.getProfileByPublicKey,
getConversationList: app.conversationLists.getConversationList,
getPinList: app.otherConfig.getPinList,
}}
emit={app.eventBus.emit}
installPrompt={props.installPrompt}
currentRelay={model.currentRelay}
activeNav={model.navigationModel.activeNav}
pool={app.pool}
update={app.eventBus}
/>
{profileEditorNode}
{publicNode}
Expand Down
10 changes: 0 additions & 10 deletions app/UI/app_model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ export type Model = {

public: Public_Model;

// profile
newProfileField: {
key: string;
value: string;
};

// UI
navigationModel: NavigationModel;
};
Expand All @@ -31,10 +25,6 @@ export function initialModel(): Model {
public: {
relaySelectedChannel: new Map(),
},
newProfileField: {
key: "",
value: "",
},
navigationModel: {
activeNav: awakenActiveNav(),
},
Expand Down
14 changes: 7 additions & 7 deletions app/UI/app_update.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,13 +189,13 @@ const handle_update_event = async (chan: PutChannel<true>, args: {
let current_relay = pool.getRelay(model.currentRelay);
if (current_relay == undefined) {
current_relay = blowater_relay;
rememberCurrentRelay(default_blowater_relay);
rememberCurrentRelay(default_blowater_relay.toString());
}

// All events below are only valid after signning in
if (event.type == "SelectSpace") {
rememberCurrentRelay(event.spaceURL);
model.currentRelay = event.spaceURL;
rememberCurrentRelay(event.spaceURL.toString());
model.currentRelay = event.spaceURL.toString();
} //
// Searchx
//
Expand All @@ -207,7 +207,7 @@ const handle_update_event = async (chan: PutChannel<true>, args: {
const search = (
<Search
placeholder={`Search a user's public key or name (${
app.database.getUniqueProfileCount(model.currentRelay)
app.database.getUniqueProfileCount(model.currentRelay.toString())
} profiles)`}
getProfileByPublicKey={app.database.getProfileByPublicKey}
getProfilesByText={app.database.getProfilesByText}
Expand Down Expand Up @@ -426,8 +426,8 @@ const handle_update_event = async (chan: PutChannel<true>, args: {
app.toastInputChan.put(() => err.message);
return;
}
if (current_relay.url == event.url) {
model.currentRelay = default_blowater_relay;
if (new URL(current_relay.url).toString() == event.url.toString()) {
model.currentRelay = default_blowater_relay.toString();
}
}
})();
Expand Down Expand Up @@ -689,7 +689,7 @@ export async function handle_SendMessage(
message: ui_event.text,
files: ui_event.files,
lamport_timestamp: lamport.now(),
eventSender: args.blowater_relay,
eventSender: args.current_relay,
targetEvent: replyToEvent,
});
if (events_send instanceof Error) {
Expand Down
2 changes: 1 addition & 1 deletion app/UI/components/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function Avatar(props: {
}
<img
onClick={props.onClick}
class={`w-full h-full rounded-full ${props.onClick ? "cursor-pointer" : ""}`}
class={`w-full h-full rounded-full aspect-square ${props.onClick ? "cursor-pointer" : ""}`}
src={props.picture}
alt="avatar"
onError={(e) => {
Expand Down
4 changes: 2 additions & 2 deletions app/UI/config-other.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ export class OtherConfig implements PinListGetter, NostrEventAdder {

private pinList = new Map<string, PinConversationRelay | UnpinConversationRelay>(); // set of pubkeys in npub format

getPinList(): Set<string> {
getPinList = (): Set<string> => {
const set = new Set<string>();
for (const event of this.pinList.values()) {
if (event.type == "PinConversation") {
set.add(event.pubkey);
}
}
return set;
}
};

async addPin(pubkey: string) {
const currentPin = this.pinList.get(pubkey);
Expand Down
46 changes: 44 additions & 2 deletions app/UI/conversation-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { InvalidEvent } from "../features/dm.ts";
import { getTags } from "../nostr.ts";
import { UserBlocker } from "./app_update.tsx";
import { ConversationListRetriever, ConversationType, NewMessageChecker } from "./conversation-list.tsx";
import { RelayRecordGetter } from "../database.ts";

export interface ConversationSummary {
pubkey: PublicKey;
readonly pubkey: PublicKey;
newestEventSendByMe?: NostrEvent;
newestEventReceivedByMe?: NostrEvent;
relays?: string[];
relays: Array<URL>;
}

export class DM_List implements ConversationListRetriever, NewMessageChecker, UserBlocker {
Expand All @@ -18,6 +19,7 @@ export class DM_List implements ConversationListRetriever, NewMessageChecker, Us

constructor(
public readonly ctx: NostrAccountContext,
private readonly relayRecordGetter: RelayRecordGetter,
) {}

newNessageCount(pubkey: PublicKey): number {
Expand All @@ -28,6 +30,24 @@ export class DM_List implements ConversationListRetriever, NewMessageChecker, Us
this.newMessages.set(pubkey.bech32(), 0);
}

getConversationList = (space?: URL) => {
const convs = [];
for (const convo of this.convoSummaries.values()) {
if (
convo.newestEventReceivedByMe != undefined ||
convo.newestEventSendByMe != undefined
) {
if (!space) {
convs.push(convo);
}
if (space && hasSpace(space, convo.relays)) {
convs.push(convo);
}
}
}
return convs;
};

*getStrangers() {
for (const convoSummary of this.convoSummaries.values()) {
if (
Expand Down Expand Up @@ -165,6 +185,12 @@ export class DM_List implements ConversationListRetriever, NewMessageChecker, Us

const userInfo = this.convoSummaries.get(pubkey_I_TalkingTo.bech32());
if (userInfo) {
const spaceURLs = this.relayRecordGetter.getRelayRecord(event.id);
if (spaceURLs.size > 0) {
for (const url of spaceURLs) {
userInfo.relays.push(new URL(url));
}
}
if (pubkey_I_TalkingTo.hex == this.ctx.publicKey.hex) {
// talking to myself
if (userInfo.newestEventSendByMe) {
Expand Down Expand Up @@ -202,7 +228,14 @@ export class DM_List implements ConversationListRetriever, NewMessageChecker, Us
pubkey: pubkey_I_TalkingTo,
newestEventReceivedByMe: undefined,
newestEventSendByMe: undefined,
relays: [],
};
const spaceURLs = this.relayRecordGetter.getRelayRecord(event.id);
if (spaceURLs.size > 0) {
for (const url of spaceURLs) {
newUserInfo.relays.push(new URL(url));
}
}
if (pubkey_I_TalkingTo.hex == this.ctx.publicKey.hex) {
// talking to myself
newUserInfo.newestEventSendByMe = event;
Expand Down Expand Up @@ -235,3 +268,12 @@ function sortScore(contact: ConversationSummary) {
}
return score;
}

function hasSpace(url: URL, list: URL[]) {
for (const u of list) {
if (u.toString() == url.toString()) {
return true;
}
}
return false;
}
4 changes: 0 additions & 4 deletions app/UI/conversation-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ export interface ConversationListRetriever {
getConversationType(pubkey: PublicKey): ConversationType;
}

export interface GroupMessageListGetter {
getConversationList: () => Iterable<ConversationSummary>;
}

export type ConversationType = ContactTag;

export type ContactUpdate =
Expand Down
12 changes: 0 additions & 12 deletions app/UI/dm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,6 @@ export class DirectMessageContainer extends Component<DirectMessageContainerProp
<div
class={`h-full flex-1 flex bg-[#36393F] overflow-hidden`}
>
<div
class={`w-fit max-sm:w-full
${props.currentConversation ? "max-sm:hidden" : ""}`}
>
<ConversationList
eventSub={props.bus}
emit={props.bus.emit}
getters={props.getters}
userBlocker={props.userBlocker}
/>
</div>

{this.props.currentConversation
? (
<div class={`flex flex-col flex-1 overflow-hidden`}>
Expand Down
58 changes: 44 additions & 14 deletions app/UI/nav.test.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/** @jsx h */
import { h } from "preact";
import { render } from "preact";
import { NavBar } from "./nav.tsx";
import { testEventBus } from "./_setup.test.ts";
import { PrivateKey } from "@blowater/nostr-sdk";
import { ConnectionPool } from "@blowater/nostr-sdk";
import { h, render } from "preact";
import { NewNav } from "./nav.tsx";
import { prepareProfileEvent, testEventBus } from "./_setup.test.ts";
import { ConnectionPool, InMemoryAccountContext, PublicKey } from "@blowater/nostr-sdk";
import { ConversationSummary } from "./conversation-list.ts";

const pool = new ConnectionPool();
await pool.addRelayURLs(
[
"relay.blowater.app",
"blowater.nostr1.com",
"nos.lol",
"relay.damus.io",
"nostr.wine",
Expand All @@ -34,16 +33,47 @@ await pool.addRelayURLs(
"wss://nostr-relay.bitcoin.ninja",
],
);
const ctx = InMemoryAccountContext.Generate();
const profileEvent = await prepareProfileEvent(ctx, {
name: "test_name",
display_name: "Orionna Lumis",
about:
"Celestial bodies move in a harmonious dance, bound by the tether of gravity. Their ballet paints stories in the sky.",
website: "https://github.com",
picture: "https://image.nostr.build/655007ae74f24ea1c611889f48b25cb485b83ab67408daddd98f95782f47e1b5.jpg",
});

let currentConversation: PublicKey | undefined;
const convoList = new Array<ConversationSummary>();
const pinList = new Set<string>();
for (let i = 0; i < 50; i++) {
const pubkey = InMemoryAccountContext.Generate().publicKey;
if (i % 4 == 0) pinList.add(pubkey.hex);
if (i == 5) currentConversation = pubkey;
convoList.push({
pubkey: pubkey,
relays: [],
});
}

render(
<NavBar
<NewNav
currentSpaceURL={new URL("wss://blowater.nostr1.com")}
spaceList={[]}
activeNav={"Public"}
profile={profileEvent}
currentConversation={currentConversation}
getters={{
getProfileByPublicKey: () => profileEvent,
getConversationList: () => convoList,
getPinList: () => pinList,
}}
update={testEventBus}
emit={testEventBus.emit}
profile={undefined}
installPrompt={{ event: undefined }}
publicKey={PrivateKey.Generate().toPublicKey()}
activeNav="DM"
pool={pool}
currentRelay="ws://localhost:8000"
/>,
document.body,
);

for await (const event of testEventBus.onChange()) {
console.log(event);
}
Loading

0 comments on commit 037788a

Please sign in to comment.