@@ -85,6 +85,7 @@ export default function CertificateCard({ cert, onReset }: Props) {
8585 const exportStampRef = useRef < HTMLDivElement > ( null )
8686 const [ visible , setVisible ] = useState ( false )
8787 const [ uiScale , setUiScale ] = useState ( DESKTOP_CERT_UI_SCALE )
88+ const [ isMobileViewport , setIsMobileViewport ] = useState ( false )
8889 const [ isGeneratingShare , setIsGeneratingShare ] = useState ( false )
8990 const [ showInlineShare , setShowInlineShare ] = useState ( false )
9091 const [ copied , setCopied ] = useState ( false )
@@ -96,7 +97,10 @@ export default function CertificateCard({ cert, onReset }: Props) {
9697
9798 useEffect ( ( ) => {
9899 if ( typeof window === 'undefined' ) return
99- const applyScale = ( ) => setUiScale ( getCertificateUiScale ( window . innerWidth ) )
100+ const applyScale = ( ) => {
101+ setUiScale ( getCertificateUiScale ( window . innerWidth ) )
102+ setIsMobileViewport ( window . innerWidth <= 640 )
103+ }
100104 applyScale ( )
101105 window . addEventListener ( 'resize' , applyScale )
102106 return ( ) => window . removeEventListener ( 'resize' , applyScale )
@@ -183,20 +187,25 @@ export default function CertificateCard({ cert, onReset }: Props) {
183187 const shareUrl = `https://commitmentissues.dev/?repo=${ encodeURIComponent ( cert . repoData . fullName ) } `
184188 const shareText = buildShareCopy ( cert , shareUrl )
185189
186- async function generateShareBlob ( ) {
190+ async function generateSocialBlob ( formatKey : SocialFormatKey ) {
187191 const masterBlob = await exportBlob ( 2.5 , true )
188192 if ( ! masterBlob ) return null
189- return composeSocialBlob ( masterBlob , SOCIAL_EXPORT_FORMATS . instagramPortrait )
193+ return composeSocialBlob ( masterBlob , SOCIAL_EXPORT_FORMATS [ formatKey ] )
194+ }
195+
196+ async function generateShareBlob ( ) {
197+ return generateSocialBlob ( 'instagramPortrait' )
190198 }
191199
192200 async function handleShare ( ) {
193201 track ( 'share_clicked' )
194202 setIsGeneratingShare ( true )
195203 try {
196- const blob = await generateShareBlob ( )
204+ const shareFormat : SocialFormatKey = isMobileViewport ? 'story' : 'instagramPortrait'
205+ const blob = await generateSocialBlob ( shareFormat )
197206 if ( ! blob ) return
198207
199- const file = new File ( [ blob ] , `${ cert . repoData . name } -certificate-of-death .png` , { type : 'image/png' } )
208+ const file = new File ( [ blob ] , `${ cert . repoData . name } -${ SOCIAL_EXPORT_FORMATS [ shareFormat ] . filename } .png` , { type : 'image/png' } )
200209 const hasNativeShare = typeof navigator !== 'undefined' && 'share' in navigator
201210 const hasCanShare = typeof navigator !== 'undefined' && 'canShare' in navigator
202211 const canNativeShareFiles = hasNativeShare && ( ! hasCanShare || navigator . canShare ( { files : [ file ] } ) )
@@ -212,7 +221,7 @@ export default function CertificateCard({ cert, onReset }: Props) {
212221 stat ( 'shared' )
213222 } catch ( error ) {
214223 if ( ! ( error instanceof DOMException && error . name === 'AbortError' ) ) {
215- triggerDownload ( blob , `${ cert . repoData . name } -share .png` )
224+ triggerDownload ( blob , `${ cert . repoData . name } -${ SOCIAL_EXPORT_FORMATS [ shareFormat ] . filename } .png` )
216225 stat ( 'downloaded' )
217226 }
218227 }
@@ -378,7 +387,7 @@ export default function CertificateCard({ cert, onReset }: Props) {
378387 onMouseUp = { e => { e . currentTarget . style . opacity = '1' } }
379388 onMouseLeave = { e => { e . currentTarget . style . opacity = '1' } }
380389 >
381- { isGeneratingShare ? < span className = "btn-spinner" /> : 'Share →' }
390+ { isGeneratingShare ? < span className = "btn-spinner" /> : ( isMobileViewport ? 'Share Story (9:16) →' : 'Share →' ) }
382391 </ button >
383392 ) }
384393
0 commit comments