+ {selection && (
+
+
+
+ {canQuoteImage && (
+ <>
+
+ {quoteImageDialog(
+ <>
+
+
+ >,
+ styles.barButton
+ )}
+ >
+ )}
+
+ )}
+
+ )
+ }
+
return (
{selection && position && (
@@ -186,10 +308,16 @@ export const TextSelectionPopover = ({
- {/*
- */}
+
+ {canQuoteImage && (
+ <>
+
+ {quoteImageDialog(
+ ,
+ styles.shareButton
+ )}
+ >
+ )}
)}
diff --git a/src/components/TextSelectionPopover/styles.module.css b/src/components/TextSelectionPopover/styles.module.css
index fe75f1fc50..f2484360d0 100644
--- a/src/components/TextSelectionPopover/styles.module.css
+++ b/src/components/TextSelectionPopover/styles.module.css
@@ -60,3 +60,42 @@
}
}
}
+
+/* mobile: fixed action bar at the bottom of the screen, so it never fights
+ with the iOS/Android native selection menu near the selected text */
+.bottomBar {
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 100;
+ display: flex;
+ align-items: stretch;
+ justify-content: space-around;
+ padding-bottom: env(safe-area-inset-bottom);
+ background: var(--color-black);
+
+ & .divider {
+ width: 1px;
+ margin: var(--sp12) 0;
+ background-color: var(--color-grey-darker);
+ }
+
+ & .barButton {
+ @mixin transition;
+
+ display: flex;
+ flex: 1;
+ gap: var(--sp8);
+ align-items: center;
+ justify-content: center;
+ padding: var(--sp12) var(--sp16);
+ font-size: var(--text14);
+ color: var(--color-white);
+ transition-property: opacity;
+
+ &:active {
+ opacity: 0.6;
+ }
+ }
+}
diff --git a/src/components/index.tsx b/src/components/index.tsx
index 4297e37892..063ca4de65 100644
--- a/src/components/index.tsx
+++ b/src/components/index.tsx
@@ -76,6 +76,7 @@ export * from './Interaction'
export * from './Layout'
export * from './Notice'
export * from './Protected'
+export * from './QuoteImageDialog'
export * from './ReCaptcha'
export * from './Search'
export * from './TagDigest'
diff --git a/src/views/ArticleDetail/Content/index.tsx b/src/views/ArticleDetail/Content/index.tsx
index c7ad6a1000..968b948fb5 100644
--- a/src/views/ArticleDetail/Content/index.tsx
+++ b/src/views/ArticleDetail/Content/index.tsx
@@ -13,7 +13,10 @@ import {
ViewerContext,
} from '~/components'
import { useReadTimer } from '~/components/Hook'
-import { ReadArticleMutation } from '~/gql/graphql'
+import {
+ QuoteImageArticleFragment,
+ ReadArticleMutation,
+} from '~/gql/graphql'
import styles from './styles.module.css'
@@ -27,10 +30,12 @@ const READ_ARTICLE = gql`
const Content = ({
articleId,
+ article,
content,
indentFirstLine,
}: {
articleId: string
+ article?: QuoteImageArticleFragment | null
content: string
indentFirstLine: boolean
}) => {
@@ -140,6 +145,18 @@ const Content = ({
{!isInArticleDetailHistory && contentContainer.current && (