fix mobile dropdown

This commit is contained in:
Martti Malmi 2023-01-12 11:30:42 +02:00
parent 1401482097
commit a6100268fc
6 changed files with 79 additions and 41 deletions

View File

@ -1282,7 +1282,7 @@ a.msg {
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
display: block;
position: absolute;
right: 0;
min-width: 160px;
@ -1325,11 +1325,6 @@ a.msg {
background-color: var(--header-color);
}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}
.emoji {
font-size: 1.3em;
line-height: 1em;

View File

@ -51,10 +51,14 @@ class CopyButton extends Component<Props, State> {
if (iris.util.isMobile && !this.props.notShareable) {
// TODO: sometimes needs to be url
navigator.share({ text: copyStr, title: this.props.title }).catch((err) => {
console.error('share failed', err);
if (navigator && navigator.share) {
navigator.share({ text: copyStr, title: this.props.title }).catch((err) => {
console.error('share failed', err);
this.copy(e, copyStr);
});
} else {
this.copy(e, copyStr);
});
}
} else {
this.copy(e, copyStr);
}

View File

@ -0,0 +1,37 @@
import $ from 'jquery';
import { Component } from 'preact';
type Props = {
children: JSX.Element | JSX.Element[];
};
type State = {
open: boolean;
};
class Dropdown extends Component<Props, State> {
toggle = (e: MouseEvent, open = !this.state.open) => {
if (e.type === 'click' && e.target !== null && !$(e.target).hasClass('dropbtn')) {
return;
}
e.stopPropagation();
e.preventDefault();
this.setState({ open });
};
render() {
return (
<div
class="dropdown"
onClick={this.toggle}
onMouseEnter={(e) => this.toggle(e, true)}
onMouseLeave={(e) => this.toggle(e, false)}
>
<div class="dropbtn"></div>
{this.state.open ? <div class="dropdown-content">{this.props.children}</div> : ''}
</div>
);
}
}
export default Dropdown;

View File

@ -26,7 +26,11 @@ class Name extends Component<Props, State> {
}
render() {
return this.state.name ?? this.props.placeholder ?? Helpers.generateName(this.props.pub);
return (
this.state.name ??
this.props.placeholder ??
Helpers.generateName(Nostr.toNostrBech32Address(this.props.pub, 'npub'))
);
}
}

View File

@ -10,6 +10,7 @@ import Nostr from '../Nostr';
import { translate as t } from '../translations/Translation';
import CopyButton from './CopyButton';
import Dropdown from './Dropdown';
import FeedMessageForm from './FeedMessageForm';
import Identicon from './Identicon';
import Message from './Message';
@ -297,7 +298,7 @@ class PublicMessage extends Message {
if (this.props.standalone) {
return;
}
if (['A', 'BUTTON', 'TEXTAREA', 'IMG', '.dropdown'].find((tag) => event.target.closest(tag))) {
if (['A', 'BUTTON', 'TEXTAREA', 'IMG'].find((tag) => event.target.closest(tag))) {
return;
}
route(`/post/${Nostr.toNostrBech32Address(this.props.hash, 'note')}`);
@ -340,31 +341,28 @@ class PublicMessage extends Message {
renderDropdown() {
return html`
<div class="msg-menu-btn">
<div class="dropdown">
<div class="dropbtn"></div>
<div class="dropdown-content">
<${CopyButton}
key=${`${this.props.hash}copy`}
text=${t('copy_note_ID')}
title="Note ID"
copyStr=${Nostr.toNostrBech32Address(this.props.hash, 'note')}
/>
${this.state.msg
? html`
<${CopyButton}
key=${`${this.props.hash}copyRaw`}
text=${t('copy_raw_data')}
title="Message raw data"
copyStr=${JSON.stringify(this.state.msg.event, null, 2)}
/>
${this.state.msg.info.isMine
? html` <!-- <a href="#" onClick=${(e) => this.onDelete(e)}>Delete</a> --> `
: ''}
<a href="#" onClick=${(e) => this.onBroadcast(e)}>${t('resend_to_relays')}</a>
`
: ''}
</div>
</div>
<${Dropdown}>
<${CopyButton}
key=${`${this.props.hash}copy`}
text=${t('copy_note_ID')}
title="Note ID"
copyStr=${Nostr.toNostrBech32Address(this.props.hash, 'note')}
/>
${this.state.msg
? html`
<${CopyButton}
key=${`${this.props.hash}copyRaw`}
text=${t('copy_raw_data')}
title="Message raw data"
copyStr=${JSON.stringify(this.state.msg.event, null, 2)}
/>
${this.state.msg.info.isMine
? html` <!-- <a href="#" onClick=${(e) => this.onDelete(e)}>Delete</a> --> `
: ''}
<a href="#" onClick=${(e) => this.onBroadcast(e)}>${t('resend_to_relays')}</a>
`
: ''}
<//>
</div>
`;
}
@ -490,7 +488,7 @@ class PublicMessage extends Message {
style="cursor: pointer"
onClick=${(e) => {
// if event target is not a link or a button, open reply
if (!['A', 'BUTTON', '.dropdown'].find((tag) => e.target.closest(tag))) {
if (!['A', 'BUTTON'].find((tag) => e.target.closest(tag))) {
e.stopPropagation();
route(`/post/${s.msg.replyingTo}`);
}

View File

@ -9,6 +9,7 @@ import { Link } from 'preact-router/match';
import Button from '../components/basic/Button';
import BlockButton from '../components/BlockButton';
import CopyButton from '../components/CopyButton';
import Dropdown from '../components/Dropdown';
import FeedMessageForm from '../components/FeedMessageForm';
import FollowButton from '../components/FollowButton';
import Identicon from '../components/Identicon';
@ -173,9 +174,8 @@ class Profile extends View {
<h3 style="flex: 1" class="profile-name">
${this.state.name || Helpers.generateName(this.props.id)}
</h3>
<div class="dropdown profile-actions">
<div class="dropbtn"></div>
<div class="dropdown-content">
<div class="profile-actions">
<${Dropdown}>
${this.state.isMyProfile
? html`<${Button} onClick=${() => route('/profile/edit')}>Edit profile<//>`
: html`<${BlockButton} key=${`${this.props.id}block`} id=${this.props.id} />`}
@ -200,7 +200,7 @@ class Profile extends View {
title=${this.state.name}
copyStr=${rawDataJson}
/>
</div>
<//>
</div>
</div>