2023-06-30 14:05:57 +00:00
|
|
|
/** @jsx h */
|
|
|
|
import { h, render, VNode } from "https://esm.sh/preact@10.11.3";
|
|
|
|
import * as dm from "../features/dm.ts";
|
|
|
|
|
|
|
|
import { DirectMessageContainer, MessageThread } from "./dm.tsx";
|
|
|
|
import * as db from "../database.ts";
|
|
|
|
|
|
|
|
import { tw } from "https://esm.sh/twind@0.16.16";
|
|
|
|
import { EditProfile } from "./edit-profile.tsx";
|
|
|
|
import * as nav from "./nav.tsx";
|
|
|
|
import { EventBus } from "../event-bus.ts";
|
|
|
|
import { MessagePanel } from "./message-panel.tsx";
|
|
|
|
|
|
|
|
import { Setting } from "./setting.tsx";
|
2023-07-11 09:49:58 +00:00
|
|
|
import { Database_Contextual_View } from "../database.ts";
|
2023-06-30 14:05:57 +00:00
|
|
|
|
2023-07-15 16:40:21 +00:00
|
|
|
import { AllUsersInformation, ProfilesSyncer, UserInfo } from "./contact-list.ts";
|
2023-07-09 07:06:13 +00:00
|
|
|
|
2023-06-30 14:05:57 +00:00
|
|
|
import { new_DM_EditorModel } from "./editor.tsx";
|
|
|
|
import { initialModel, Model } from "./app_model.ts";
|
2023-07-11 10:45:57 +00:00
|
|
|
import {
|
|
|
|
AppEventBus,
|
|
|
|
Database_Update,
|
|
|
|
Relay_Update,
|
|
|
|
UI_Interaction_Event,
|
|
|
|
UI_Interaction_Update,
|
|
|
|
} from "./app_update.ts";
|
2023-06-30 14:05:57 +00:00
|
|
|
import { getSocialPosts } from "../features/social.ts";
|
|
|
|
import * as time from "../time.ts";
|
|
|
|
import { PublicKey } from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/key.ts";
|
|
|
|
import {
|
|
|
|
DecryptionFailure,
|
|
|
|
decryptNostrEvent,
|
|
|
|
NostrAccountContext,
|
|
|
|
NostrEvent,
|
|
|
|
NostrKind,
|
|
|
|
} from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/nostr.ts";
|
|
|
|
import {
|
|
|
|
ConnectionPool,
|
|
|
|
newSubID,
|
|
|
|
} from "https://raw.githubusercontent.com/BlowaterNostr/nostr.ts/main/relay.ts";
|
2023-07-09 08:06:49 +00:00
|
|
|
import { getCurrentSignInCtx, setSignInState, SignIn } from "./signIn.tsx";
|
2023-06-30 14:05:57 +00:00
|
|
|
import { AppList } from "./app-list.tsx";
|
2023-07-12 16:20:38 +00:00
|
|
|
import { LinkColor, PrimaryTextColor, SecondaryBackgroundColor } from "./style/colors.ts";
|
2023-07-05 09:32:02 +00:00
|
|
|
import { EventSyncer } from "./event_syncer.ts";
|
2023-07-09 07:06:13 +00:00
|
|
|
import { getRelayURLs } from "./setting.ts";
|
2023-07-11 09:49:58 +00:00
|
|
|
import { DexieDatabase } from "./dexie-db.ts";
|
2023-07-12 16:20:38 +00:00
|
|
|
import { DividerClass } from "./components/tw.ts";
|
|
|
|
import { About } from "./about.tsx";
|
2023-07-13 13:52:52 +00:00
|
|
|
import { computeThreads } from "../nostr.ts";
|
2023-07-09 07:06:13 +00:00
|
|
|
|
2023-07-11 09:49:58 +00:00
|
|
|
export async function Start(database: DexieDatabase) {
|
2023-07-11 10:45:57 +00:00
|
|
|
const model = initialModel();
|
|
|
|
const eventBus = new EventBus<UI_Interaction_Event>();
|
|
|
|
const pool = new ConnectionPool();
|
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
console.log("Start the application");
|
2023-07-11 10:45:57 +00:00
|
|
|
|
2023-07-09 08:06:49 +00:00
|
|
|
const ctx = await getCurrentSignInCtx();
|
2023-07-09 08:17:09 +00:00
|
|
|
console.log("Start:", ctx);
|
2023-07-09 12:43:03 +00:00
|
|
|
if (ctx instanceof Error) {
|
|
|
|
console.error(ctx);
|
2023-07-11 10:45:57 +00:00
|
|
|
model.signIn.warningString = "Please add your private key to your NIP-7 extension";
|
2023-07-09 12:43:03 +00:00
|
|
|
} else if (ctx) {
|
2023-07-11 10:45:57 +00:00
|
|
|
const dbView = await Database_Contextual_View.New(database, ctx);
|
|
|
|
const lamport = time.fromEvents(dbView.filterEvents((_) => true));
|
|
|
|
const app = new App(dbView, lamport, model, ctx, eventBus, pool);
|
2023-07-09 08:17:09 +00:00
|
|
|
const err = await app.initApp(ctx);
|
|
|
|
if (err instanceof Error) {
|
|
|
|
throw err;
|
|
|
|
}
|
2023-07-11 10:45:57 +00:00
|
|
|
model.app = app;
|
2023-07-09 08:17:09 +00:00
|
|
|
}
|
2023-07-09 07:06:13 +00:00
|
|
|
|
2023-07-11 10:45:57 +00:00
|
|
|
/* first render */ render(<AppComponent model={model} eventBus={eventBus} />, document.body);
|
2023-07-09 07:06:13 +00:00
|
|
|
|
2023-07-11 10:45:57 +00:00
|
|
|
for await (let _ of UI_Interaction_Update(model, eventBus, database, pool)) {
|
2023-07-09 07:06:13 +00:00
|
|
|
const t = Date.now();
|
|
|
|
{
|
2023-07-11 10:45:57 +00:00
|
|
|
render(<AppComponent model={model} eventBus={eventBus} />, document.body);
|
2023-07-09 07:06:13 +00:00
|
|
|
}
|
|
|
|
console.log("render", Date.now() - t);
|
|
|
|
}
|
|
|
|
|
|
|
|
(async () => {
|
2023-07-11 10:45:57 +00:00
|
|
|
for await (let _ of Relay_Update(pool)) {
|
|
|
|
render(<AppComponent model={model} eventBus={eventBus} />, document.body);
|
2023-07-09 07:06:13 +00:00
|
|
|
}
|
|
|
|
})();
|
|
|
|
}
|
2023-06-30 14:05:57 +00:00
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
async function initProfileSyncer(
|
2023-07-05 09:32:02 +00:00
|
|
|
pool: ConnectionPool,
|
2023-06-30 14:05:57 +00:00
|
|
|
accountContext: NostrAccountContext,
|
2023-07-11 09:49:58 +00:00
|
|
|
database: db.Database_Contextual_View,
|
2023-06-30 14:05:57 +00:00
|
|
|
) {
|
|
|
|
const myPublicKey = accountContext.publicKey;
|
|
|
|
|
|
|
|
////////////////////
|
|
|
|
// Init Core Data //
|
|
|
|
////////////////////
|
2023-07-11 10:45:57 +00:00
|
|
|
const newestEvent = dm.getNewestEventOf(database, myPublicKey);
|
2023-06-30 14:05:57 +00:00
|
|
|
console.info("newestEvent", newestEvent);
|
|
|
|
const _24h = 60 * 60 * 24;
|
|
|
|
let since: number = _24h;
|
|
|
|
if (newestEvent !== db.NotFound) {
|
|
|
|
since = newestEvent.created_at - _24h;
|
|
|
|
}
|
|
|
|
console.info("since", new Date(since * 1000));
|
|
|
|
|
|
|
|
// Sync DM events
|
|
|
|
const messageStream = dm.getAllEncryptedMessagesOf(
|
2023-07-11 09:19:57 +00:00
|
|
|
myPublicKey,
|
2023-06-30 14:05:57 +00:00
|
|
|
pool,
|
|
|
|
since,
|
|
|
|
);
|
|
|
|
database.syncNewDirectMessageEventsOf(
|
|
|
|
accountContext,
|
|
|
|
messageStream,
|
|
|
|
);
|
|
|
|
|
|
|
|
// Sync my profile events
|
|
|
|
const profilesSyncer = new ProfilesSyncer(database, pool);
|
|
|
|
await profilesSyncer.add(myPublicKey.hex);
|
|
|
|
|
|
|
|
// Sync Custom App Data
|
|
|
|
(async () => {
|
|
|
|
let subId = newSubID();
|
|
|
|
let resp = await pool.newSub(
|
|
|
|
subId,
|
|
|
|
{
|
|
|
|
authors: [myPublicKey.hex],
|
|
|
|
kinds: [NostrKind.CustomAppData],
|
|
|
|
},
|
|
|
|
);
|
|
|
|
if (resp instanceof Error) {
|
|
|
|
throw resp;
|
|
|
|
}
|
2023-07-12 07:14:45 +00:00
|
|
|
for await (const { res, url } of resp) {
|
|
|
|
if (res.type == "EVENT") {
|
|
|
|
database.addEvent(res.event);
|
2023-06-30 14:05:57 +00:00
|
|
|
}
|
2023-07-12 07:14:45 +00:00
|
|
|
}
|
|
|
|
})();
|
2023-06-30 14:05:57 +00:00
|
|
|
|
|
|
|
///////////////////////////////////
|
|
|
|
// Add relays to Connection Pool //
|
|
|
|
///////////////////////////////////
|
2023-07-09 07:06:13 +00:00
|
|
|
const relayURLs = getRelayURLs(database);
|
2023-07-09 08:17:09 +00:00
|
|
|
pool.addRelayURLs(relayURLs);
|
2023-06-30 14:05:57 +00:00
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
return profilesSyncer;
|
2023-06-30 14:05:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export class App {
|
2023-07-05 05:50:34 +00:00
|
|
|
profileSyncer!: ProfilesSyncer;
|
2023-07-05 09:32:02 +00:00
|
|
|
eventSyncer: EventSyncer;
|
2023-07-15 16:40:21 +00:00
|
|
|
public readonly allUsersInfo: AllUsersInformation;
|
2023-06-30 14:05:57 +00:00
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
constructor(
|
2023-07-11 09:49:58 +00:00
|
|
|
public readonly database: Database_Contextual_View,
|
2023-07-09 07:06:13 +00:00
|
|
|
public readonly lamport: time.LamportTime,
|
2023-07-11 10:45:57 +00:00
|
|
|
public readonly model: Model,
|
|
|
|
public readonly myAccountContext: NostrAccountContext,
|
|
|
|
public readonly eventBus: EventBus<UI_Interaction_Event>,
|
|
|
|
public readonly relayPool: ConnectionPool,
|
2023-06-30 14:05:57 +00:00
|
|
|
) {
|
2023-07-05 09:32:02 +00:00
|
|
|
this.eventSyncer = new EventSyncer(this.relayPool, this.database);
|
2023-07-15 16:40:21 +00:00
|
|
|
this.allUsersInfo = new AllUsersInformation(myAccountContext);
|
2023-06-30 14:05:57 +00:00
|
|
|
}
|
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
initApp = async (accountContext: NostrAccountContext) => {
|
2023-07-15 16:40:21 +00:00
|
|
|
// const events = this.database.filterEvents((e) => e.kind == NostrKind.TEXT_NOTE);
|
2023-07-13 13:52:52 +00:00
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
console.log("App.initApp");
|
|
|
|
const profilesSyncer = await initProfileSyncer(this.relayPool, accountContext, this.database);
|
|
|
|
if (profilesSyncer instanceof Error) {
|
|
|
|
return profilesSyncer;
|
|
|
|
}
|
|
|
|
|
2023-07-05 05:50:34 +00:00
|
|
|
this.profileSyncer = profilesSyncer;
|
2023-06-30 14:05:57 +00:00
|
|
|
|
2023-07-15 16:40:21 +00:00
|
|
|
this.allUsersInfo.addEvents(this.database.events);
|
2023-06-30 14:05:57 +00:00
|
|
|
console.log("App allUsersInfo");
|
2023-07-15 16:40:21 +00:00
|
|
|
this.model.social.threads = getSocialPosts(this.database, this.allUsersInfo.userInfos);
|
2023-06-30 14:05:57 +00:00
|
|
|
|
|
|
|
/* my profile */
|
2023-07-15 16:40:21 +00:00
|
|
|
this.model.myProfile = this.allUsersInfo.userInfos.get(accountContext.publicKey.hex)?.profile
|
|
|
|
?.profile;
|
2023-06-30 14:05:57 +00:00
|
|
|
|
|
|
|
/* contacts */
|
2023-07-15 16:40:21 +00:00
|
|
|
for (const contact of this.allUsersInfo.userInfos.values()) {
|
2023-06-30 14:05:57 +00:00
|
|
|
const editor = this.model.editors.get(contact.pubkey.hex);
|
|
|
|
if (editor == null) {
|
|
|
|
const pubkey = PublicKey.FromHex(contact.pubkey.hex);
|
|
|
|
if (pubkey instanceof Error) {
|
|
|
|
throw pubkey; // impossible
|
|
|
|
}
|
|
|
|
this.model.editors.set(
|
|
|
|
contact.pubkey.hex,
|
|
|
|
new_DM_EditorModel({
|
|
|
|
pubkey,
|
2023-07-14 10:59:25 +00:00
|
|
|
name: contact.profile?.profile.name,
|
|
|
|
picture: contact.profile?.profile.picture,
|
2023-06-30 14:05:57 +00:00
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
await profilesSyncer.add(
|
2023-07-15 16:40:21 +00:00
|
|
|
...Array.from(this.allUsersInfo.userInfos.keys()),
|
2023-06-30 14:05:57 +00:00
|
|
|
);
|
|
|
|
console.log("user set", profilesSyncer.userSet);
|
|
|
|
|
2023-07-09 07:06:13 +00:00
|
|
|
// Database
|
2023-06-30 14:05:57 +00:00
|
|
|
(async () => {
|
2023-07-09 07:06:13 +00:00
|
|
|
let i = 0;
|
2023-06-30 14:05:57 +00:00
|
|
|
for await (
|
|
|
|
let _ of Database_Update(
|
|
|
|
accountContext,
|
|
|
|
this.database,
|
|
|
|
this.model,
|
2023-07-09 07:06:13 +00:00
|
|
|
this.profileSyncer,
|
|
|
|
this.lamport,
|
2023-06-30 14:05:57 +00:00
|
|
|
this.eventBus,
|
2023-07-15 16:40:21 +00:00
|
|
|
this.allUsersInfo,
|
2023-06-30 14:05:57 +00:00
|
|
|
)
|
|
|
|
) {
|
2023-07-11 10:45:57 +00:00
|
|
|
render(<AppComponent model={this.model} eventBus={this.eventBus} />, document.body);
|
2023-06-30 14:05:57 +00:00
|
|
|
console.log(`render ${++i} times`);
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
};
|
|
|
|
|
|
|
|
logout = () => {
|
|
|
|
setSignInState("none");
|
|
|
|
window.location.reload();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function AppComponent(props: {
|
2023-07-11 10:45:57 +00:00
|
|
|
model: Model;
|
|
|
|
eventBus: AppEventBus;
|
2023-06-30 14:05:57 +00:00
|
|
|
}) {
|
|
|
|
const t = Date.now();
|
2023-07-11 10:45:57 +00:00
|
|
|
const model = props.model;
|
|
|
|
|
|
|
|
if (model.app == undefined) {
|
2023-06-30 14:05:57 +00:00
|
|
|
console.log("render sign in page");
|
|
|
|
return (
|
|
|
|
<SignIn
|
2023-07-11 10:45:57 +00:00
|
|
|
eventBus={props.eventBus}
|
|
|
|
privateKey={model.signIn.privateKey}
|
|
|
|
state={model.signIn.state}
|
|
|
|
warningString={model.signIn.warningString}
|
2023-06-30 14:05:57 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-07-11 10:45:57 +00:00
|
|
|
const app = model.app;
|
|
|
|
const myAccountCtx = model.app.myAccountContext;
|
|
|
|
|
2023-06-30 14:05:57 +00:00
|
|
|
let socialPostsPanel: VNode | undefined;
|
2023-07-11 10:45:57 +00:00
|
|
|
if (model.navigationModel.activeNav == "Social") {
|
2023-07-08 09:12:43 +00:00
|
|
|
let focusedContentGetter = () => {
|
2023-07-12 07:14:45 +00:00
|
|
|
// console.log("AppComponent:getFocusedContent before", Date.now() - t);
|
2023-07-15 16:40:21 +00:00
|
|
|
let _ = getFocusedContent(
|
|
|
|
model.social.focusedContent,
|
|
|
|
app.allUsersInfo.userInfos,
|
|
|
|
model.social.threads,
|
|
|
|
);
|
2023-07-12 07:14:45 +00:00
|
|
|
// console.log("AppComponent:getFocusedContent", Date.now() - t);
|
2023-06-30 14:05:57 +00:00
|
|
|
if (_?.type === "MessageThread") {
|
2023-07-11 10:45:57 +00:00
|
|
|
let editor = model.social.replyEditors.get(_.data.root.event.id);
|
2023-06-30 14:05:57 +00:00
|
|
|
if (editor == undefined) {
|
|
|
|
editor = {
|
|
|
|
id: _.data.root.event.id,
|
|
|
|
files: [],
|
|
|
|
text: "",
|
|
|
|
tags: [
|
|
|
|
["e", _.data.root.event.id],
|
|
|
|
],
|
|
|
|
target: {
|
|
|
|
kind: NostrKind.TEXT_NOTE,
|
|
|
|
},
|
|
|
|
};
|
2023-07-11 10:45:57 +00:00
|
|
|
model.social.replyEditors.set(editor.id, editor);
|
2023-06-30 14:05:57 +00:00
|
|
|
}
|
|
|
|
return {
|
|
|
|
..._,
|
|
|
|
editor,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return _;
|
2023-07-08 09:12:43 +00:00
|
|
|
};
|
|
|
|
let focusedContent = focusedContentGetter();
|
2023-06-30 14:05:57 +00:00
|
|
|
socialPostsPanel = (
|
|
|
|
<div
|
|
|
|
class={tw`flex-1 overflow-hidden bg-[#313338]`}
|
|
|
|
>
|
|
|
|
<MessagePanel
|
|
|
|
focusedContent={focusedContent}
|
2023-07-11 10:45:57 +00:00
|
|
|
editorModel={model.social.editor}
|
2023-06-30 14:05:57 +00:00
|
|
|
myPublicKey={myAccountCtx.publicKey}
|
2023-07-13 13:52:52 +00:00
|
|
|
messages={model.social.threads}
|
2023-07-11 10:45:57 +00:00
|
|
|
rightPanelModel={model.rightPanelModel}
|
2023-07-04 06:37:14 +00:00
|
|
|
db={app.database}
|
2023-06-30 14:05:57 +00:00
|
|
|
eventEmitter={app.eventBus}
|
2023-07-05 05:50:34 +00:00
|
|
|
profilesSyncer={app.profileSyncer}
|
2023-07-05 09:32:02 +00:00
|
|
|
eventSyncer={app.eventSyncer}
|
2023-07-16 15:04:23 +00:00
|
|
|
allUserInfo={app.allUsersInfo.userInfos}
|
2023-06-30 14:05:57 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let settingNode;
|
2023-07-11 10:45:57 +00:00
|
|
|
if (model.navigationModel.activeNav == "Setting") {
|
2023-06-30 14:05:57 +00:00
|
|
|
settingNode = (
|
|
|
|
<div
|
|
|
|
class={tw`flex-1 overflow-hidden overflow-y-auto bg-[${SecondaryBackgroundColor}]`}
|
|
|
|
>
|
|
|
|
{Setting({
|
|
|
|
logout: app.logout,
|
|
|
|
pool: app.relayPool,
|
|
|
|
eventBus: app.eventBus,
|
2023-07-11 10:45:57 +00:00
|
|
|
AddRelayButtonClickedError: model.AddRelayButtonClickedError,
|
|
|
|
AddRelayInput: model.AddRelayInput,
|
2023-06-30 14:05:57 +00:00
|
|
|
myAccountContext: myAccountCtx,
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let appList;
|
2023-07-11 10:45:57 +00:00
|
|
|
if (model.navigationModel.activeNav == "AppList") {
|
2023-06-30 14:05:57 +00:00
|
|
|
appList = (
|
|
|
|
<div
|
|
|
|
class={tw`flex-1 overflow-hidden overflow-y-auto bg-[#313338]`}
|
|
|
|
>
|
|
|
|
<AppList />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let dmVNode;
|
|
|
|
let aboutNode;
|
|
|
|
if (
|
2023-07-11 10:45:57 +00:00
|
|
|
model.navigationModel.activeNav == "DM" ||
|
|
|
|
model.navigationModel.activeNav == "About"
|
2023-06-30 14:05:57 +00:00
|
|
|
) {
|
2023-07-11 10:45:57 +00:00
|
|
|
if (model.navigationModel.activeNav == "DM") {
|
2023-06-30 14:05:57 +00:00
|
|
|
dmVNode = (
|
|
|
|
<div
|
|
|
|
class={tw`flex-1 overflow-hidden`}
|
|
|
|
>
|
|
|
|
{DirectMessageContainer({
|
2023-07-11 10:45:57 +00:00
|
|
|
editors: model.editors,
|
|
|
|
...model.dm,
|
|
|
|
rightPanelModel: model.rightPanelModel,
|
2023-06-30 14:05:57 +00:00
|
|
|
eventEmitter: app.eventBus,
|
|
|
|
myAccountContext: myAccountCtx,
|
|
|
|
db: app.database,
|
2023-07-11 10:45:57 +00:00
|
|
|
pool: app.relayPool,
|
2023-07-15 16:40:21 +00:00
|
|
|
allUserInfo: app.allUsersInfo.userInfos,
|
2023-07-05 05:50:34 +00:00
|
|
|
profilesSyncer: app.profileSyncer,
|
2023-07-05 09:32:02 +00:00
|
|
|
eventSyncer: app.eventSyncer,
|
2023-06-30 14:05:57 +00:00
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-07-11 10:45:57 +00:00
|
|
|
if (model.navigationModel.activeNav == "About") {
|
2023-06-30 14:05:57 +00:00
|
|
|
aboutNode = About();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const final = (
|
|
|
|
<div
|
|
|
|
class={tw`font-roboto flex flex-col h-screen w-screen overflow-hidden`}
|
|
|
|
>
|
|
|
|
<div class={tw`w-full h-full flex flex-col`}>
|
|
|
|
<div class={tw`w-full flex-1 flex overflow-hidden`}>
|
|
|
|
<div class={tw`mobile:hidden`}>
|
|
|
|
{nav.NavBar({
|
2023-07-11 10:45:57 +00:00
|
|
|
profilePicURL: model.myProfile?.picture,
|
2023-06-30 14:05:57 +00:00
|
|
|
publicKey: myAccountCtx.publicKey,
|
|
|
|
database: app.database,
|
|
|
|
pool: app.relayPool,
|
|
|
|
eventEmitter: app.eventBus,
|
2023-07-11 10:45:57 +00:00
|
|
|
AddRelayButtonClickedError: model.AddRelayButtonClickedError,
|
|
|
|
AddRelayInput: model.AddRelayInput,
|
|
|
|
...model.navigationModel,
|
2023-06-30 14:05:57 +00:00
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div
|
|
|
|
class={tw`h-full px-[3rem] bg-[${SecondaryBackgroundColor}] flex-1 overflow-auto${
|
2023-07-11 10:45:57 +00:00
|
|
|
model.navigationModel.activeNav == "Profile" ? " block" : " hidden"
|
2023-06-30 14:05:57 +00:00
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
class={tw`max-w-[35rem] h-full m-auto`}
|
|
|
|
>
|
|
|
|
{EditProfile({
|
|
|
|
eventEmitter: app.eventBus,
|
2023-07-11 10:45:57 +00:00
|
|
|
myProfile: model.myProfile,
|
|
|
|
newProfileField: model.newProfileField,
|
2023-06-30 14:05:57 +00:00
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{dmVNode}
|
|
|
|
{aboutNode}
|
|
|
|
{settingNode}
|
|
|
|
{socialPostsPanel}
|
|
|
|
{appList}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class={tw`desktop:hidden`}>
|
|
|
|
<nav.MobileNavBar
|
2023-07-11 10:45:57 +00:00
|
|
|
profilePicURL={model.myProfile?.picture}
|
2023-06-30 14:05:57 +00:00
|
|
|
publicKey={myAccountCtx.publicKey}
|
|
|
|
database={app.database}
|
|
|
|
pool={app.relayPool}
|
|
|
|
eventEmitter={app.eventBus}
|
2023-07-11 10:45:57 +00:00
|
|
|
AddRelayButtonClickedError={model.AddRelayButtonClickedError}
|
|
|
|
AddRelayInput={model.AddRelayInput}
|
|
|
|
{...model.navigationModel}
|
2023-06-30 14:05:57 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
2023-07-13 13:52:52 +00:00
|
|
|
console.debug("AppComponent:end", Date.now() - t);
|
2023-06-30 14:05:57 +00:00
|
|
|
return final;
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo: move to somewhere else
|
|
|
|
export function getFocusedContent(
|
|
|
|
focusedContent: PublicKey | NostrEvent | undefined,
|
|
|
|
allUserInfo: Map<string, UserInfo>,
|
|
|
|
threads: MessageThread[],
|
|
|
|
) {
|
|
|
|
if (focusedContent == undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (focusedContent instanceof PublicKey) {
|
2023-07-14 10:59:25 +00:00
|
|
|
const profileData = allUserInfo.get(focusedContent.hex)?.profile?.profile;
|
2023-06-30 14:05:57 +00:00
|
|
|
return {
|
|
|
|
type: "ProfileData" as "ProfileData",
|
|
|
|
data: profileData,
|
|
|
|
pubkey: focusedContent,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
for (const thread of threads) {
|
|
|
|
if (thread.root.event.id == focusedContent.id) {
|
|
|
|
return {
|
|
|
|
type: "MessageThread" as "MessageThread",
|
|
|
|
data: thread,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|