Improve context menu design
This commit is contained in:
parent
731f91122b
commit
50eb9b9f59
3 changed files with 119 additions and 48 deletions
24
src/app.css
24
src/app.css
|
@ -1100,10 +1100,16 @@ body:has(.status-deck) .media-post-link {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
padding: 8px 16px !important;
|
padding: 8px 16px !important;
|
||||||
transition: all 0.1s ease-in-out;
|
transition: all 0.1s ease-in-out;
|
||||||
|
text-decoration: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-decoration: none;
|
}
|
||||||
|
.szh-menu .szh-menu__item span {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
line-height: 1.05;
|
||||||
}
|
}
|
||||||
.szh-menu .szh-menu__item * {
|
.szh-menu .szh-menu__item * {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -1141,6 +1147,22 @@ body:has(.status-deck) .media-post-link {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.szh-menu .menu-double-lines {
|
||||||
|
white-space: normal;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.szh-menu .menu-double-lines span {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
.szh-menu .menu-horizontal {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.szh-menu .menu-horizontal .szh-menu__item {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
.szh-menu .szh-menu__item .menu-shortcut {
|
.szh-menu .szh-menu__item .menu-shortcut {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|
|
@ -68,7 +68,14 @@ const ICONS = {
|
||||||
|
|
||||||
const modules = import.meta.glob('/node_modules/@iconify-icons/mingcute/*.js');
|
const modules = import.meta.glob('/node_modules/@iconify-icons/mingcute/*.js');
|
||||||
|
|
||||||
function Icon({ icon, size = 'm', alt, title, class: className = '' }) {
|
function Icon({
|
||||||
|
icon,
|
||||||
|
size = 'm',
|
||||||
|
alt,
|
||||||
|
title,
|
||||||
|
class: className = '',
|
||||||
|
style = {},
|
||||||
|
}) {
|
||||||
if (!icon) return null;
|
if (!icon) return null;
|
||||||
|
|
||||||
const iconSize = SIZES[size];
|
const iconSize = SIZES[size];
|
||||||
|
@ -97,6 +104,7 @@ function Icon({ icon, size = 'm', alt, title, class: className = '' }) {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
lineHeight: 0,
|
lineHeight: 0,
|
||||||
|
...style,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{iconData && (
|
{iconData && (
|
||||||
|
|
|
@ -373,7 +373,7 @@ function Status({
|
||||||
</MenuHeader>
|
</MenuHeader>
|
||||||
<MenuLink to={instance ? `/${instance}/s/${id}` : `/s/${id}`}>
|
<MenuLink to={instance ? `/${instance}/s/${id}` : `/s/${id}`}>
|
||||||
<Icon icon="arrow-right" />
|
<Icon icon="arrow-right" />
|
||||||
View post and replies
|
<span>View post by @{username || acct}</span>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -408,7 +408,12 @@ function Status({
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="rocket" />
|
<Icon
|
||||||
|
icon="rocket"
|
||||||
|
style={{
|
||||||
|
color: reblogged && 'var(--reblog-color)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<span>{reblogged ? 'Unboost' : 'Boost…'}</span>
|
<span>{reblogged ? 'Unboost' : 'Boost…'}</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
|
@ -421,7 +426,12 @@ function Status({
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="heart" />
|
<Icon
|
||||||
|
icon="heart"
|
||||||
|
style={{
|
||||||
|
color: favourited && 'var(--favourite-color)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<span>{favourited ? 'Unfavourite' : 'Favourite'}</span>
|
<span>{favourited ? 'Unfavourite' : 'Favourite'}</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
@ -433,16 +443,33 @@ function Status({
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="bookmark" />
|
<Icon
|
||||||
|
icon="bookmark"
|
||||||
|
style={{
|
||||||
|
color: bookmarked && 'var(--favourite-color)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<span>{bookmarked ? 'Unbookmark' : 'Bookmark'}</span>
|
<span>{bookmarked ? 'Unbookmark' : 'Bookmark'}</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
{enableTranslate && (
|
||||||
|
<MenuItem
|
||||||
|
disabled={forceTranslate}
|
||||||
|
onClick={() => {
|
||||||
|
setForceTranslate(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon icon="translate" />
|
||||||
|
<span>Translate</span>
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<MenuItem href={url} target="_blank">
|
<MenuItem href={url} target="_blank">
|
||||||
<Icon icon="external" />
|
<Icon icon="external" />
|
||||||
<span>Open link to post</span>
|
<small class="menu-double-lines">{nicePostURL(url)}</small>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<div class="menu-horizontal">
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// Copy url to clipboard
|
// Copy url to clipboard
|
||||||
|
@ -456,19 +483,8 @@ function Status({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="link" />
|
<Icon icon="link" />
|
||||||
<span>Copy link to post</span>
|
<span>Copy</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{enableTranslate && (
|
|
||||||
<MenuItem
|
|
||||||
disabled={forceTranslate}
|
|
||||||
onClick={() => {
|
|
||||||
setForceTranslate(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon icon="translate" />
|
|
||||||
<span>Translate</span>
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
{navigator?.share &&
|
{navigator?.share &&
|
||||||
navigator?.canShare?.({
|
navigator?.canShare?.({
|
||||||
url,
|
url,
|
||||||
|
@ -489,6 +505,7 @@ function Status({
|
||||||
<span>Share…</span>
|
<span>Share…</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
{isSelf && (
|
{isSelf && (
|
||||||
<>
|
<>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
|
@ -546,6 +563,9 @@ function Status({
|
||||||
onContextMenu={(e) => {
|
onContextMenu={(e) => {
|
||||||
if (size === 'l') return;
|
if (size === 'l') return;
|
||||||
if (e.metaKey) return;
|
if (e.metaKey) return;
|
||||||
|
console.log('context menu', e);
|
||||||
|
const link = e.target.closest('a');
|
||||||
|
if (link && /^https?:\/\//.test(link.getAttribute('href'))) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setContextMenuAnchorPoint({
|
setContextMenuAnchorPoint({
|
||||||
x: e.clientX,
|
x: e.clientX,
|
||||||
|
@ -1537,6 +1557,27 @@ function _unfurlMastodonLink(instance, url) {
|
||||||
return Promise.any([remoteInstanceFetch, mastoSearchFetch]);
|
return Promise.any([remoteInstanceFetch, mastoSearchFetch]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nicePostURL(url) {
|
||||||
|
const urlObj = new URL(url);
|
||||||
|
const { host, pathname } = urlObj;
|
||||||
|
const path = pathname.replace(/\/$/, '');
|
||||||
|
// split only first slash
|
||||||
|
const [_, username, restPath] = path.match(/\/(@[^\/]+)\/(.*)/) || [];
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{host}
|
||||||
|
{username ? (
|
||||||
|
<>
|
||||||
|
/{username}
|
||||||
|
<span class="more-insignificant">/{restPath}</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span class="more-insignificant">{path}</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const unfurlMastodonLink = throttle(_unfurlMastodonLink);
|
const unfurlMastodonLink = throttle(_unfurlMastodonLink);
|
||||||
|
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
|
|
Loading…
Add table
Reference in a new issue