Skip to content

Commit

Permalink
more fn components
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalmi committed Aug 20, 2023
1 parent 151c028 commit 3f1e40e
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 159 deletions.
108 changes: 47 additions & 61 deletions src/js/views/View.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import debounce from 'lodash/debounce';
import { JSX } from 'preact';
import { useEffect, useRef } from 'preact/hooks';

import Component from '../BaseComponent';
import ErrorBoundary from '../components/ErrorBoundary';
import Header from '../components/Header';
import Show from '../components/helpers/Show';
Expand All @@ -15,61 +14,27 @@ const listener = function () {
};
window.addEventListener('popstate', listener);

abstract class View extends Component {
class = '';
id = '';
observer: ResizeObserver | null = null;
scrollPosition = 0;
hideSideBar = false;
hideHeader = false;
const View = ({ children, hideHeader = false, hideSideBar = false }) => {
const observerRef = useRef<any>(null);

abstract renderView(): JSX.Element;

render() {
return (
<div className="flex flex-row h-full w-full">
<div className={`flex flex-col w-full h-full ${this.hideSideBar ? '' : 'lg:w-2/3'}`}>
<Show when={!this.hideHeader}>
<Header />
</Show>
<div class={this.class} id={this.id} className="h-full">
<ErrorBoundary>{this.renderView()}</ErrorBoundary>
</div>
</div>
<Show when={!this.hideSideBar}>
<div className="flex-col hidden lg:flex lg:w-1/3">
<Search focus={false} />
</div>
</Show>
</div>
);
}

componentDidMount() {
window.addEventListener('scroll', this.saveScrollPosition);
this.restoreScrollPosition();
}

saveScrollPosition = debounce(() => {
const scrollPosition = window.scrollY || document.documentElement.scrollTop;
const saveScrollPosition = debounce(() => {
const position = window.scrollY || document.documentElement.scrollTop;
const currentHistoryState = window.history.state;
const newHistoryState = {
...currentHistoryState,
scrollPosition,
scrollPosition: position,
};
window.history.replaceState(newHistoryState, '');
}, 100);

restoreScrollPosition(observe = true) {
const restoreScrollPosition = (observe = true) => {
const currentHistoryState = window.history.state;
const previousHistoryState = window.history.state?.previousState;
if (!isInitialLoad && currentHistoryState !== previousHistoryState) {
observe && this.observeScrollElement();
if (!this.scrollPosition) {
this.scrollPosition = window.history.state?.scrollPosition;
}
if (this.scrollPosition) {
window.scrollTo(0, this.scrollPosition);
observe && observeScrollElement();
const position = window.history.state?.scrollPosition || 0;
if (position) {
window.scrollTo(0, position);
}
} else {
const oldState = window.history.state || {};
Expand All @@ -79,29 +44,50 @@ abstract class View extends Component {
};
window.history.replaceState(newHistoryState, '');
}
}
};

observeScrollElement = () => {
this.observer = new ResizeObserver((entries) => {
const observeScrollElement = () => {
observerRef.current = new ResizeObserver((entries) => {
entries.forEach(() => {
this.restoreScrollPosition(false);
restoreScrollPosition(false);
});
});

this.observer.observe(document.body);
observerRef.current.observe(document.body);
setTimeout(() => {
if (this.observer) {
this.observer.disconnect();
}
observerRef.current.disconnect();
}, 1000);
};

componentWillUnmount() {
if (this.observer) {
this.observer.disconnect();
}
window.removeEventListener('scroll', this.saveScrollPosition);
}
}
useEffect(() => {
window.addEventListener('scroll', saveScrollPosition);
restoreScrollPosition();

return () => {
if (observerRef.current) {
observerRef.current.disconnect();
}
window.removeEventListener('scroll', saveScrollPosition);
};
}, []);

return (
<div className="flex flex-row h-full w-full">
<div className={`flex flex-col w-full h-full ${hideSideBar ? '' : 'lg:w-2/3'}`}>
<Show when={!hideHeader}>
<Header />
</Show>
<div className="h-full">
<ErrorBoundary>{children}</ErrorBoundary>
</div>
</div>
<Show when={!hideSideBar}>
<div className="flex-col hidden lg:flex lg:w-1/3">
<Search focus={false} />
</div>
</Show>
</div>
);
};

export default View;
45 changes: 17 additions & 28 deletions src/js/views/chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PaperAirplaneIcon } from '@heroicons/react/24/solid';
import { useEffect } from 'preact/hooks';

import Key from '../../nostr/Key';
import { translate as t } from '../../translations/Translation.mjs';
Expand All @@ -9,33 +10,23 @@ import ChatMessages from './ChatMessages';
import Header from './Header';
import NewChat, { addChatWithInputKey } from './NewChat';

class Chat extends View {
id: string;

constructor() {
super();
this.id = 'chat-view';
this.hideSideBar = true;
this.hideHeader = true;
}

componentDidMount() {
super.componentDidMount();
const id = window.location.hash.substr(1);
if (id && id.startsWith('nsec')) {
const Chat = ({ id }) => {
useEffect(() => {
const hashId = window.location.hash.substr(1);
if (hashId && hashId.startsWith('nsec')) {
window.history.replaceState({}, document.title, window.location.pathname);
if (!Key.getPubKey()) {
Key.loginAsNewUser();
}
addChatWithInputKey(id);
addChatWithInputKey(hashId);
}
}
}, []);

renderContent = (id) => {
if (id === 'new') {
const renderContent = (chatId) => {
if (chatId === 'new') {
return <NewChat />;
} else if (id) {
return <ChatMessages id={id} key={id} />;
} else if (chatId) {
return <ChatMessages id={chatId} key={chatId} />;
} else {
return (
<div className="hidden md:flex flex-col items-center justify-center flex-1">
Expand All @@ -48,10 +39,8 @@ class Chat extends View {
}
};

renderView() {
const { id } = this.props;

return (
return (
<View>
<div className="flex flex-col h-full max-h-screen">
<Header key={id} activeChat={id} />
<div className="flex flex-row flex-grow overflow-hidden">
Expand All @@ -66,12 +55,12 @@ class Chat extends View {
key={`chat-content-${id}`}
className={`flex-grow overflow-y-auto ${!id ? 'hidden md:flex' : 'flex'}`}
>
{this.renderContent(id)}
{renderContent(id)}
</div>
</div>
</div>
);
}
}
</View>
);
};

export default Chat;
5 changes: 3 additions & 2 deletions src/js/views/feeds/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getEventReplyingTo } from '@/nostr/utils';
import { translate as t } from '@/translations/Translation.mjs';
import { ID, STR } from '@/utils/UniqueIds';
import { RouteProps } from '@/views/types.ts';
import View from '@/views/View.tsx';

import SocialNetwork from '../../nostr/SocialNetwork';

Expand Down Expand Up @@ -54,7 +55,7 @@ const Home: React.FC<RouteProps> = () => {
console.log('followedUsers.length', followedUsers.length); // TODO this keeps changing, fix

return (
<div className="flex flex-row">
<View>
<div className="flex flex-col w-full">
<OnboardingNotification />
<div className="hidden md:block px-4">
Expand All @@ -64,7 +65,7 @@ const Home: React.FC<RouteProps> = () => {
<FeedComponent key={`feed-${followedUsers.length}`} filterOptions={filterOptions} />
</Show>
</div>
</div>
</View>
);
};

Expand Down
50 changes: 22 additions & 28 deletions src/js/views/feeds/Search.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,36 @@
import { useMemo } from 'preact/hooks';

import FeedComponent from '@/components/feed/Feed';

import View from '../View';

class Search extends View {
constructor() {
super();
this.state = { sortedMessages: [] };
this.id = 'message-view';
this.class = 'public-messages-view';
}

componentDidMount() {
this.restoreScrollPosition();
}
const Search = ({ keyword }) => {
const filterOptions = useMemo(() => {
const filter = { kinds: [1], keywords: [keyword || ''] };

renderView() {
const filterFn = (event) => {
// some relays don't support filtering by keyword
return event.content.includes(this.props.keyword);
return event.content.includes(keyword);
};
const filter = { kinds: [1], keywords: [this.props.keyword || ''] };
return (

return [
{
name: 'Search',
filter,
filterFn,
},
];
}, [keyword]);

return (
<View>
<div className="flex flex-row">
<div className="flex flex-col w-full">
<FeedComponent
key={this.props.keyword}
filterOptions={[
{
name: 'Search',
filter,
filterFn,
},
]}
/>
<FeedComponent key={keyword} filterOptions={filterOptions} />
</div>
</div>
);
}
}
</View>
);
};

export default Search;
Loading

0 comments on commit 3f1e40e

Please sign in to comment.