commit
ecd308ce39
|
@ -295,7 +295,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) {
|
|||
video,
|
||||
img,
|
||||
audio {
|
||||
min-height: 88px; /* for extreme dimensions */
|
||||
min-height: var(--pointer-min-dimension); /* for extreme dimensions */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ body.cloak,
|
|||
.account-block,
|
||||
.catchup-filters .filter-author *,
|
||||
.post-peek-html *,
|
||||
.post-peek-content > * {
|
||||
.post-peek-content > *,
|
||||
.request-notifications-account * {
|
||||
text-decoration-thickness: 1.1em;
|
||||
text-decoration-line: line-through;
|
||||
/* text-rendering: optimizeSpeed; */
|
||||
|
@ -51,7 +52,8 @@ body.cloak,
|
|||
.cloak {
|
||||
.media-container figcaption,
|
||||
.media-container figcaption > *,
|
||||
.catchup-filters .filter-author * {
|
||||
.catchup-filters .filter-author *,
|
||||
.request-notifications-account * {
|
||||
color: var(--text-color) !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -831,3 +831,58 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.handle-info {
|
||||
.handle-handle {
|
||||
display: inline-block;
|
||||
margin-block: 5px;
|
||||
|
||||
b {
|
||||
font-weight: 600;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
box-shadow: 0 0 0 5px var(--bg-blur-color);
|
||||
|
||||
&.handle-username {
|
||||
color: var(--orange-fg-color);
|
||||
background-color: var(--orange-bg-color);
|
||||
}
|
||||
|
||||
&.handle-server {
|
||||
color: var(--purple-fg-color);
|
||||
background-color: var(--purple-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.handle-at {
|
||||
display: inline-block;
|
||||
margin-inline: -3px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.handle-legend {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
|
||||
.handle-legend-icon {
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 4px solid transparent;
|
||||
border-radius: 8px;
|
||||
background-clip: padding-box;
|
||||
|
||||
&.username {
|
||||
background-color: var(--orange-fg-color);
|
||||
border-color: var(--orange-bg-color);
|
||||
}
|
||||
&.server {
|
||||
background-color: var(--purple-fg-color);
|
||||
border-color: var(--purple-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -541,13 +541,55 @@ function AccountInfo({
|
|||
/>
|
||||
)}
|
||||
<header>
|
||||
<AccountBlock
|
||||
account={info}
|
||||
instance={instance}
|
||||
avatarSize="xxxl"
|
||||
external={standalone}
|
||||
internal={!standalone}
|
||||
/>
|
||||
{standalone ? (
|
||||
<Menu2
|
||||
shift={
|
||||
window.matchMedia('(min-width: calc(40em))').matches
|
||||
? 114
|
||||
: 64
|
||||
}
|
||||
menuButton={
|
||||
<div>
|
||||
<AccountBlock
|
||||
account={info}
|
||||
instance={instance}
|
||||
avatarSize="xxxl"
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div class="szh-menu__header">
|
||||
<AccountHandleInfo acct={acct} instance={instance} />
|
||||
</div>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
const handle = `@${acct}`;
|
||||
try {
|
||||
navigator.clipboard.writeText(handle);
|
||||
showToast('Handle copied');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast('Unable to copy handle');
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon icon="link" />
|
||||
<span>Copy handle</span>
|
||||
</MenuItem>
|
||||
<MenuItem href={url} target="_blank">
|
||||
<Icon icon="external" />
|
||||
<span>Go to original profile page</span>
|
||||
</MenuItem>
|
||||
</Menu2>
|
||||
) : (
|
||||
<AccountBlock
|
||||
account={info}
|
||||
instance={instance}
|
||||
avatarSize="xxxl"
|
||||
internal
|
||||
/>
|
||||
)}
|
||||
</header>
|
||||
<div class="faux-header-bg" aria-hidden="true" />
|
||||
<main>
|
||||
|
@ -2000,4 +2042,27 @@ function FieldsAttributesRow({ name, value, disabled, index: i }) {
|
|||
);
|
||||
}
|
||||
|
||||
function AccountHandleInfo({ acct, instance }) {
|
||||
// acct = username or username@server
|
||||
let [username, server] = acct.split('@');
|
||||
if (!server) server = instance;
|
||||
return (
|
||||
<div class="handle-info">
|
||||
<span class="handle-handle">
|
||||
<b class="handle-username">{username}</b>
|
||||
<span class="handle-at">@</span>
|
||||
<b class="handle-server">{server}</b>
|
||||
</span>
|
||||
<div class="handle-legend">
|
||||
<span class="ib">
|
||||
<span class="handle-legend-icon username" /> username
|
||||
</span>{' '}
|
||||
<span class="ib">
|
||||
<span class="handle-legend-icon server" /> server domain name
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AccountInfo;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
import openCompose from '../utils/open-compose';
|
||||
import openOSK from '../utils/open-osk';
|
||||
import states from '../utils/states';
|
||||
|
||||
import Icon from './icon';
|
||||
|
@ -14,6 +15,7 @@ export default function ComposeButton() {
|
|||
states.showCompose = true;
|
||||
}
|
||||
} else {
|
||||
openOSK();
|
||||
states.showCompose = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -299,7 +299,7 @@ function Compose({
|
|||
setVisibility(visibility);
|
||||
setLanguage(language || presf.postingDefaultLanguage || DEFAULT_LANG);
|
||||
setSensitive(sensitive);
|
||||
setPoll(composablePoll);
|
||||
if (composablePoll) setPoll(composablePoll);
|
||||
setMediaAttachments(mediaAttachments);
|
||||
setUIState('default');
|
||||
} catch (e) {
|
||||
|
|
|
@ -2,11 +2,13 @@ import { shouldPolyfill } from '@formatjs/intl-segmenter/should-polyfill';
|
|||
import { Suspense } from 'preact/compat';
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
|
||||
import Loader from './loader';
|
||||
|
||||
const supportsIntlSegmenter = !shouldPolyfill();
|
||||
|
||||
export default function IntlSegmenterSuspense({ children }) {
|
||||
if (supportsIntlSegmenter) {
|
||||
return <Suspense>{children}</Suspense>;
|
||||
return <Suspense fallback={<Loader />}>{children}</Suspense>;
|
||||
}
|
||||
|
||||
const [polyfillLoaded, setPolyfillLoaded] = useState(false);
|
||||
|
@ -17,5 +19,9 @@ export default function IntlSegmenterSuspense({ children }) {
|
|||
})();
|
||||
}, []);
|
||||
|
||||
return polyfillLoaded && <Suspense>{children}</Suspense>;
|
||||
return polyfillLoaded ? (
|
||||
<Suspense fallback={<Loader />}>{children}</Suspense>
|
||||
) : (
|
||||
<Loader />
|
||||
);
|
||||
}
|
||||
|
|
|
@ -88,3 +88,7 @@
|
|||
.sparkle-icon {
|
||||
animation: sparkle-icon 0.3s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.nav-submenu {
|
||||
max-width: 14em;
|
||||
}
|
||||
|
|
|
@ -27,9 +27,10 @@ function NavMenu(props) {
|
|||
|
||||
const [currentAccount, moreThanOneAccount] = useMemo(() => {
|
||||
const accounts = store.local.getJSON('accounts') || [];
|
||||
const acc = accounts.find(
|
||||
(account) => account.info.id === store.session.get('currentAccount'),
|
||||
);
|
||||
const acc =
|
||||
accounts.find(
|
||||
(account) => account.info.id === store.session.get('currentAccount'),
|
||||
) || accounts[0];
|
||||
return [acc, accounts.length > 1];
|
||||
}, []);
|
||||
|
||||
|
@ -147,7 +148,7 @@ function NavMenu(props) {
|
|||
}}
|
||||
{...props}
|
||||
overflow="auto"
|
||||
viewScroll="close"
|
||||
// viewScroll="close"
|
||||
position="anchor"
|
||||
align="center"
|
||||
boundingBoxPadding={boundingBoxPadding}
|
||||
|
@ -209,6 +210,7 @@ function NavMenu(props) {
|
|||
)}
|
||||
{lists?.length > 0 ? (
|
||||
<SubMenu
|
||||
menuClassName="nav-submenu"
|
||||
overflow="auto"
|
||||
gap={-8}
|
||||
label={
|
||||
|
@ -243,6 +245,7 @@ function NavMenu(props) {
|
|||
<Icon icon="bookmark" size="l" /> <span>Bookmarks</span>
|
||||
</MenuLink>
|
||||
<SubMenu
|
||||
menuClassName="nav-submenu"
|
||||
overflow="auto"
|
||||
gap={-8}
|
||||
label={
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Fragment } from 'preact';
|
|||
import { memo } from 'preact/compat';
|
||||
|
||||
import shortenNumber from '../utils/shorten-number';
|
||||
import states from '../utils/states';
|
||||
import states, { statusKey } from '../utils/states';
|
||||
import store from '../utils/store';
|
||||
import useTruncated from '../utils/useTruncated';
|
||||
|
||||
|
@ -228,6 +228,7 @@ function Notification({
|
|||
accounts: _accounts,
|
||||
showReactions: type === 'favourite+reblog',
|
||||
excludeRelationshipAttrs: type === 'follow' ? ['followedBy'] : [],
|
||||
postID: statusKey(actualStatusID, instance),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
padding: 2px;
|
||||
vertical-align: top;
|
||||
text-transform: uppercase;
|
||||
text-shadow: 0 1px var(--bg-color);
|
||||
/* text-shadow: 0 1px var(--bg-color); */
|
||||
|
||||
&:hover {
|
||||
color: var(--text-color);
|
||||
|
@ -623,26 +623,26 @@
|
|||
.spoiler-media-button
|
||||
),
|
||||
~ .card .meta-container {
|
||||
/* filter: blur(5px) invert(0.5);
|
||||
image-rendering: crisp-edges;
|
||||
image-rendering: pixelated; */
|
||||
opacity: 0.2;
|
||||
text-decoration-thickness: 1.5em;
|
||||
text-decoration-line: line-through;
|
||||
/* text-rendering: optimizeSpeed; */
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
/* contain: layout; */
|
||||
/* transform: scale(0.97);
|
||||
transition: transform 0.1s ease-in-out; */
|
||||
|
||||
* {
|
||||
text-decoration-color: inherit;
|
||||
text-decoration-thickness: 1.5em;
|
||||
text-decoration-line: line-through;
|
||||
/* text-rendering: optimizeSpeed; */
|
||||
}
|
||||
}
|
||||
|
||||
~ *:not(
|
||||
.media-container,
|
||||
.card,
|
||||
.media-figure-multiple,
|
||||
.spoiler-media-button
|
||||
),
|
||||
~ .card .meta-container {
|
||||
img {
|
||||
filter: invert(0.5);
|
||||
background-color: black;
|
||||
|
@ -908,7 +908,7 @@
|
|||
grid-auto-rows: 1fr;
|
||||
gap: 2px;
|
||||
/* height: 160px; */
|
||||
min-height: 88px;
|
||||
min-height: var(--pointer-min-dimension);
|
||||
height: auto;
|
||||
max-height: max(160px, 33vh);
|
||||
}
|
||||
|
@ -1037,9 +1037,9 @@
|
|||
.status .media-container.media-eq1 .media {
|
||||
display: inline-block;
|
||||
max-width: 100% !important;
|
||||
min-width: 88px;
|
||||
min-width: var(--pointer-min-dimension);
|
||||
/* width: auto; */
|
||||
min-height: 88px;
|
||||
min-height: var(--pointer-min-dimension);
|
||||
/* --maxAspectHeight: max(160px, 33vh);
|
||||
--aspectWidth: calc(--width / --height * var(--maxAspectHeight)); */
|
||||
width: min(var(--aspectWidth), var(--width), 100%);
|
||||
|
@ -1300,7 +1300,7 @@ body:has(#modal-container .carousel) .status .media img:hover {
|
|||
:is(.status, .media-post) .media-audio {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 88px;
|
||||
min-height: var(--pointer-min-dimension);
|
||||
background-image: radial-gradient(
|
||||
circle at center center,
|
||||
transparent,
|
||||
|
@ -1696,6 +1696,7 @@ a.card:is(:hover, :focus):visited {
|
|||
.poll-label input:is([type='radio'], [type='checkbox']) {
|
||||
flex-shrink: 0;
|
||||
margin: 3px;
|
||||
min-height: 1em;
|
||||
}
|
||||
.poll-option-votes {
|
||||
flex-shrink: 0;
|
||||
|
@ -1719,6 +1720,7 @@ a.card:is(:hover, :focus):visited {
|
|||
}
|
||||
.poll-option-title {
|
||||
text-shadow: 0 1px var(--bg-color);
|
||||
line-height: 1.2;
|
||||
}
|
||||
.poll-option-title .icon {
|
||||
vertical-align: middle;
|
||||
|
|
|
@ -1593,11 +1593,14 @@ function Status({
|
|||
}`}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
icon={visibilityIconsMap[visibility]}
|
||||
alt={visibilityText[visibility]}
|
||||
size="s"
|
||||
/>
|
||||
visibility !== 'public' &&
|
||||
visibility !== 'direct' && (
|
||||
<Icon
|
||||
icon={visibilityIconsMap[visibility]}
|
||||
alt={visibilityText[visibility]}
|
||||
size="s"
|
||||
/>
|
||||
)
|
||||
)}{' '}
|
||||
<RelativeTime datetime={createdAtDate} format="micro" />
|
||||
{!previewMode && !readOnly && (
|
||||
|
@ -1648,11 +1651,15 @@ function Status({
|
|||
// {StatusMenuItems}
|
||||
// </Menu>
|
||||
<span class="time">
|
||||
<Icon
|
||||
icon={visibilityIconsMap[visibility]}
|
||||
alt={visibilityText[visibility]}
|
||||
size="s"
|
||||
/>{' '}
|
||||
{visibility !== 'public' && visibility !== 'direct' && (
|
||||
<>
|
||||
<Icon
|
||||
icon={visibilityIconsMap[visibility]}
|
||||
alt={visibilityText[visibility]}
|
||||
size="s"
|
||||
/>{' '}
|
||||
</>
|
||||
)}
|
||||
<RelativeTime datetime={createdAtDate} format="micro" />
|
||||
</span>
|
||||
))}
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
|
||||
--blue-color: royalblue;
|
||||
--purple-color: blueviolet;
|
||||
--purple-fg-color: color-mix(
|
||||
in srgb-linear,
|
||||
var(--purple-color) 60%,
|
||||
var(--text-color) 40%
|
||||
);
|
||||
--purple-bg-color: color-mix(in srgb, var(--purple-color) 10%, transparent);
|
||||
--green-color: darkgreen;
|
||||
--orange-color: darkorange;
|
||||
--orange-light-bg-color: color-mix(
|
||||
|
@ -23,6 +29,12 @@
|
|||
var(--orange-color) 20%,
|
||||
transparent
|
||||
);
|
||||
--orange-fg-color: color-mix(
|
||||
in srgb-linear,
|
||||
var(--orange-color) 60%,
|
||||
var(--text-color) 40%
|
||||
);
|
||||
--orange-bg-color: color-mix(in srgb, var(--orange-color) 10%, transparent);
|
||||
--red-color: orangered;
|
||||
--red-text-color: color-mix(
|
||||
in srgb-linear,
|
||||
|
@ -96,6 +108,14 @@
|
|||
|
||||
--timing-function: cubic-bezier(0.3, 0.5, 0, 1);
|
||||
--spring-timing-funtion: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
|
||||
--pointer-min-dimension: 88px;
|
||||
}
|
||||
|
||||
@media (pointer: fine) {
|
||||
:root {
|
||||
--pointer-min-dimension: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
|
|
|
@ -1263,7 +1263,7 @@ function Catchup() {
|
|||
authors[author].avatarStatic || authors[author].avatar
|
||||
}
|
||||
size="xxl"
|
||||
alt={`${authors[author].displayName} (@${authors[author].username})`}
|
||||
alt={`${authors[author].displayName} (@${authors[author].acct})`}
|
||||
/>{' '}
|
||||
<span class="count">{authorCounts[author]}</span>
|
||||
<span class="username">{authors[author].username}</span>
|
||||
|
|
|
@ -180,6 +180,8 @@ function Filters() {
|
|||
);
|
||||
}
|
||||
|
||||
let _id = 1;
|
||||
const incID = () => _id++;
|
||||
function FiltersAddEdit({ filter, onClose }) {
|
||||
const { masto } = api();
|
||||
const [uiState, setUIState] = useState('default');
|
||||
|
@ -193,7 +195,12 @@ function FiltersAddEdit({ filter, onClose }) {
|
|||
|
||||
// Hacky way of handling removed keywords for both existing and new ones
|
||||
const [removedKeywordIDs, setRemovedKeywordIDs] = useState([]);
|
||||
const [removedNewKeywordIndices, setRemovedNewKeywordIndices] = useState([]);
|
||||
const [removedKeyword_IDs, setRemovedKeyword_IDs] = useState([]);
|
||||
|
||||
const filteredEditKeywords = editKeywords.filter(
|
||||
(k) =>
|
||||
!removedKeywordIDs.includes(k.id) && !removedKeyword_IDs.includes(k._id),
|
||||
);
|
||||
|
||||
return (
|
||||
<div class="sheet" id="filters-add-edit-modal">
|
||||
|
@ -335,16 +342,12 @@ function FiltersAddEdit({ filter, onClose }) {
|
|||
</label>
|
||||
</div>
|
||||
<div class="filter-form-keywords" ref={keywordsRef}>
|
||||
{editKeywords.length ? (
|
||||
{filteredEditKeywords.length ? (
|
||||
<ul class="filter-keywords">
|
||||
{editKeywords.map((k, index) => {
|
||||
const { id, keyword, wholeWord } = k;
|
||||
const removed =
|
||||
removedKeywordIDs.includes(id) ||
|
||||
removedNewKeywordIndices.includes(index);
|
||||
if (removed) return null;
|
||||
{filteredEditKeywords.map((k) => {
|
||||
const { id, keyword, wholeWord, _id } = k;
|
||||
return (
|
||||
<li key={`${index}-${id}`}>
|
||||
<li key={`${id}-${_id}`}>
|
||||
<input
|
||||
type="hidden"
|
||||
name="keyword_attributes[][id]"
|
||||
|
@ -376,12 +379,9 @@ function FiltersAddEdit({ filter, onClose }) {
|
|||
if (id) {
|
||||
removedKeywordIDs.push(id);
|
||||
setRemovedKeywordIDs([...removedKeywordIDs]);
|
||||
} else {
|
||||
// If no id, remove by index
|
||||
removedNewKeywordIndices.push(index);
|
||||
setRemovedNewKeywordIndices([
|
||||
...removedNewKeywordIndices,
|
||||
]);
|
||||
} else if (_id) {
|
||||
removedKeyword_IDs.push(_id);
|
||||
setRemovedKeyword_IDs([...removedKeyword_IDs]);
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
@ -405,6 +405,7 @@ function FiltersAddEdit({ filter, onClose }) {
|
|||
setEditKeywords([
|
||||
...editKeywords,
|
||||
{
|
||||
_id: incID(),
|
||||
keyword: '',
|
||||
wholeWord: true,
|
||||
},
|
||||
|
@ -421,10 +422,10 @@ function FiltersAddEdit({ filter, onClose }) {
|
|||
>
|
||||
Add keyword
|
||||
</button>{' '}
|
||||
{editKeywords?.length > 1 && (
|
||||
{filteredEditKeywords?.length > 1 && (
|
||||
<small class="insignificant">
|
||||
{editKeywords.length} keyword
|
||||
{editKeywords.length === 1 ? '' : 's'}
|
||||
{filteredEditKeywords.length} keyword
|
||||
{filteredEditKeywords.length === 1 ? '' : 's'}
|
||||
</small>
|
||||
)}
|
||||
</footer>
|
||||
|
|
|
@ -532,66 +532,72 @@ function Notifications({ columnMode }) {
|
|||
)}
|
||||
{supportsFilteredNotifications &&
|
||||
notificationsPolicy?.summary?.pendingRequestsCount > 0 && (
|
||||
<div class="filtered-notifications">
|
||||
<details
|
||||
onToggle={async (e) => {
|
||||
const { open } = e.target;
|
||||
if (open) {
|
||||
const requests = await fetchNotificationsRequest();
|
||||
setNotificationsRequests(requests);
|
||||
console.log({ open, requests });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<summary>
|
||||
Filtered notifications from{' '}
|
||||
{notificationsPolicy.summary.pendingRequestsCount} people
|
||||
</summary>
|
||||
{!notificationsRequests ? (
|
||||
<p class="ui-state">
|
||||
<Loader abrupt />
|
||||
</p>
|
||||
) : (
|
||||
notificationsRequests?.length > 0 && (
|
||||
<ul>
|
||||
{notificationsRequests.map((request) => (
|
||||
<li key={request.id}>
|
||||
<div class="request-notifcations">
|
||||
{!request.lastStatus?.id && (
|
||||
<AccountBlock
|
||||
useAvatarStatic
|
||||
showStats
|
||||
account={request.account}
|
||||
/>
|
||||
)}
|
||||
{request.lastStatus?.id && (
|
||||
<div class="last-post">
|
||||
<Link
|
||||
class="status-link"
|
||||
to={`/${instance}/s/${request.lastStatus.id}`}
|
||||
>
|
||||
<Status
|
||||
status={request.lastStatus}
|
||||
size="s"
|
||||
readOnly
|
||||
<div class="shazam-container">
|
||||
<div class="shazam-container-inner">
|
||||
<div class="filtered-notifications">
|
||||
<details
|
||||
onToggle={async (e) => {
|
||||
const { open } = e.target;
|
||||
if (open) {
|
||||
const requests = await fetchNotificationsRequest();
|
||||
setNotificationsRequests(requests);
|
||||
console.log({ open, requests });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<summary>
|
||||
Filtered notifications from{' '}
|
||||
{notificationsPolicy.summary.pendingRequestsCount} people
|
||||
</summary>
|
||||
{!notificationsRequests ? (
|
||||
<p class="ui-state">
|
||||
<Loader abrupt />
|
||||
</p>
|
||||
) : (
|
||||
notificationsRequests?.length > 0 && (
|
||||
<ul>
|
||||
{notificationsRequests.map((request) => (
|
||||
<li key={request.id}>
|
||||
<div class="request-notifcations">
|
||||
{!request.lastStatus?.id && (
|
||||
<AccountBlock
|
||||
useAvatarStatic
|
||||
showStats
|
||||
account={request.account}
|
||||
/>
|
||||
</Link>
|
||||
)}
|
||||
{request.lastStatus?.id && (
|
||||
<div class="last-post">
|
||||
<Link
|
||||
class="status-link"
|
||||
to={`/${instance}/s/${request.lastStatus.id}`}
|
||||
>
|
||||
<Status
|
||||
status={request.lastStatus}
|
||||
size="s"
|
||||
readOnly
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<NotificationRequestModalButton
|
||||
request={request}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<NotificationRequestModalButton request={request} />
|
||||
</div>
|
||||
<NotificationRequestButtons
|
||||
request={request}
|
||||
onChange={() => {
|
||||
loadNotifications(true);
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
)}
|
||||
</details>
|
||||
<NotificationRequestButtons
|
||||
request={request}
|
||||
onChange={() => {
|
||||
loadNotifications(true);
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
)}
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div id="mentions-option">
|
||||
|
|
16
src/utils/open-osk.jsx
Normal file
16
src/utils/open-osk.jsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); // https://stackoverflow.com/a/23522755
|
||||
|
||||
export default function openOSK() {
|
||||
if (isSafari) {
|
||||
const fauxEl = document.createElement('input');
|
||||
fauxEl.style.position = 'absolute';
|
||||
fauxEl.style.top = '0';
|
||||
fauxEl.style.left = '0';
|
||||
fauxEl.style.opacity = '0';
|
||||
document.body.appendChild(fauxEl);
|
||||
fauxEl.focus();
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(fauxEl);
|
||||
}, 500);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import store from './store';
|
|||
|
||||
export function getAccount(id) {
|
||||
const accounts = store.local.getJSON('accounts') || [];
|
||||
if (!id) return accounts[0];
|
||||
return accounts.find((a) => a.info.id === id) || accounts[0];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue