Skip to content

Commit

Permalink
custom chat header component
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalmi committed Aug 2, 2023
1 parent 2f05584 commit ee6f047
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 182 deletions.
2 changes: 1 addition & 1 deletion src/js/views/chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Chat extends View {

return (
<div className="flex flex-col h-screen">
<Header />
<Header key={id} activeChat={id} />
<div className="flex flex-row flex-grow overflow-hidden">
<div
className={`flex-shrink-0 ${
Expand Down
216 changes: 35 additions & 181 deletions src/js/views/chat/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,165 +1,26 @@
import { Cog8ToothIcon, HeartIcon } from '@heroicons/react/24/outline';
import { ArrowLeftIcon, HeartIcon as HeartIconFull } from '@heroicons/react/24/solid';
import { ArrowLeftIcon } from '@heroicons/react/24/solid';
import { route } from 'preact-router';

import Component from '../../BaseComponent';
import Show from '../../components/helpers/Show';
import SearchBox from '../../components/SearchBox';
import Avatar from '../../components/user/Avatar';
import Name from '../../components/user/Name';
import Icons from '../../Icons';
import localState from '../../LocalState';
import Key from '../../nostr/Key';
import Relays from '../../nostr/Relays';
import { translate as t } from '../../translations/Translation.mjs';

export default class Header extends Component {
userId = null as string | null;
iv = null as any;

constructor() {
super();
this.state = { latest: {} };
this.escFunction = this.escFunction.bind(this);
}

escFunction(event) {
if (event.keyCode === 27) {
this.state.showMobileSearch && this.setState({ showMobileSearch: false });
}
}

backButtonClicked() {
const Header = ({ activeChat }) => {
const backButtonClicked = () => {
window.history.back();
}

componentWillUnmount() {
super.componentWillUnmount();
this.iv && clearInterval(this.iv);
document.removeEventListener('keydown', this.escFunction, false);
}

setTitle(activeRoute: string) {
let title: any = activeRoute.split('/')[1] || t('home');
if (title.startsWith('note')) {
title = t('post');
} else if (title.startsWith('npub')) {
this.userId = title;
title = <Name key={`${this.userId}title`} pub={this.userId || ''} />;
} else {
title = title.charAt(0).toUpperCase() + title.slice(1);
}

const replaced = activeRoute.replace('/chat/new', '').replace('/chat/', '');

if (activeRoute.indexOf('/chat/') === 0 && activeRoute.indexOf('/chat/new') !== 0) {
this.userId = replaced.length < activeRoute.length ? replaced : null;
if (activeRoute.indexOf('/chat/') === 0 && this.userId === Key.getPubKey()) {
title = (
<>
<b className="mr-5">📝</b> <b>{t('note_to_self')}</b>
</>
);
} else {
title = <Name key={`${this.userId}title`} pub={this.userId || ''} />;
}
}

this.setState({ title });
}
};

componentDidMount() {
document.addEventListener('keydown', this.escFunction, false);
localState.get('showParticipants').on(this.inject());
localState.get('unseenMsgsTotal').on(this.inject());
localState.get('unseenNotificationCount').on(this.inject());
localState.get('showConnectedRelays').on(this.inject());
localState.get('isMyProfile').on(this.inject());
localState.get('activeRoute').on(
this.sub((activeRoute) => {
this.setState({
about: null,
activeRoute,
showMobileSearch: false,
});
this.setTitle(activeRoute);
}),
);
this.updateRelayCount();
this.iv = setInterval(() => this.updateRelayCount(), 1000);
}

onTitleClicked() {
const onTitleClicked = () => {
window.scrollTo(0, 0);
if (this.userId && this.userId.indexOf('hashtag') === -1) {
route('/' + this.userId);
if (activeChat && activeChat.length > 15) {
route('/' + Key.toNostrBech32Address(activeChat, 'npub'));
}
}

updateRelayCount() {
this.setState({ connectedRelays: Relays.getConnectedRelayCount() });
}

renderSearchBox() {
return !this.userId ? <SearchBox onSelect={(item) => route(`/${item.key}`)} /> : '';
}

renderConnectedRelays() {
return (
<a
href="/settings/network"
className={`ml-2 tooltip tooltip-bottom mobile-search-hidden ${
this.state.showMobileSearch ? 'hidden-xs' : ''
} ${this.state.connectedRelays > 0 ? 'connected' : ''}`}
data-tip={t('connected_relays')}
>
<small className="flex items-center gap-2">
<span class="icon">{Icons.network}</span>
<span>{this.state.connectedRelays}</span>
</small>
</a>
);
}
};

renderTitle() {
const isHome = this.state.activeRoute === '/';
return (
<div
className={`flex-1 text-center ${isHome ? 'invisible md:visible' : ''}`}
onClick={() => this.onTitleClicked()}
>
{this.state.title}
</div>
);
}

renderNotifications() {
return (
<>
<Show when={this.state.isMyProfile}>
<a href="/settings" className="md:hidden">
<Cog8ToothIcon width={28} />
</a>
</Show>
<a
href="/notifications"
className={`relative inline-block ${this.state.isMyProfile ? 'hidden md:flex' : ''}`}
>
{this.state.activeRoute === '/notifications' ? (
<HeartIconFull width={28} />
) : (
<HeartIcon width={28} />
)}
<Show when={this.state.unseenNotificationCount}>
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 bg-iris-purple text-white text-sm rounded-full h-5 w-5 flex items-center justify-center">
{this.state.unseenNotificationCount > 99 ? '' : this.state.unseenNotificationCount}
</span>
</Show>
</a>
</>
);
}

renderLoginBtns() {
const renderLoginBtns = () => {
return (
<div className="flex gap-2">
<button
Expand All @@ -176,37 +37,30 @@ export default class Header extends Component {
</button>
</div>
);
}

renderBackBtnOrLogo() {
const isHome = this.state.activeRoute === '/';
return isHome ? (
<div className="flex flex-row items-center gap-2 md:hidden">
<img src="/img/icon128.png" width="30" height="30" />
<h1 className=" text-3xl">iris</h1>
</div>
) : (
<ArrowLeftIcon width={24} onClick={() => this.backButtonClicked()} />
);
}

render() {
const pub = Key.getPubKey();
const loggedIn = !!pub;
return (
<div className="sticky top-0 z-10 cursor-pointer flex flex-wrap">
<div className="w-full overflow-x-hidden bg-black md:bg-opacity-50 md:shadow-lg md:backdrop-blur-lg px-2">
<div className="flex items-center justify-between h-12">
{this.renderBackBtnOrLogo()}
<Show when={loggedIn && this.state.showConnectedRelays}>
{this.renderConnectedRelays()}
</Show>
{this.renderTitle()}
<Show when={loggedIn}>{this.renderNotifications()}</Show>
<Show when={!loggedIn}>{this.renderLoginBtns()}</Show>
</div>
};

const pub = Key.getPubKey();
const loggedIn = !!pub;

return (
<div className="sticky top-0 z-10 cursor-pointer flex flex-wrap" onClick={onTitleClicked}>
<div className="w-full overflow-x-hidden bg-black md:bg-opacity-50 md:shadow-lg md:backdrop-blur-lg px-2">
<div className="flex items-center justify-between h-12">
<ArrowLeftIcon width={24} onClick={backButtonClicked} />
<Show when={activeChat}>
<div className="flex flex-row gap-2 items-center">
<Avatar width={30} str={activeChat} />
<Name pub={activeChat} />
</div>
</Show>
<Show when={loggedIn}>
<div></div>
</Show>
<Show when={!loggedIn}>{renderLoginBtns()}</Show>
</div>
</div>
);
}
}
</div>
);
};

export default Header;

0 comments on commit ee6f047

Please sign in to comment.