選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

sponsorware.tsx 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import { styled } from 'styles'
  2. import { getSession, signin, signout, useSession } from 'next-auth/client'
  3. import type { GetServerSideProps } from 'next'
  4. import Link from 'next/link'
  5. import React from 'react'
  6. import Head from 'next/head'
  7. export default function Sponsorware(): JSX.Element {
  8. const [session, loading] = useSession()
  9. return (
  10. <>
  11. <Head>
  12. <title>tldraw</title>
  13. </Head>
  14. <StyledOuterContent>
  15. <StyledContent
  16. size={{
  17. '@sm': 'small',
  18. }}
  19. >
  20. <h1>Tldraw (is sponsorware)</h1>
  21. <p>
  22. Hey, thanks for visiting <Link href="/">Tldraw</Link>, a tiny little drawing app by{' '}
  23. <a
  24. target="_blank"
  25. rel="noreferrer nofollow noopener"
  26. href="https://twitter.com/steveruizok"
  27. >
  28. steveruizok
  29. </a>{' '}
  30. and friends .
  31. </p>
  32. <video autoPlay muted playsInline onClick={(e) => e.currentTarget.play()}>
  33. <source src="images/hello.mp4" type="video/mp4" />
  34. </video>
  35. <p>This project is currently: </p>
  36. <ul>
  37. <li>in development</li>
  38. <li>only available for my sponsors</li>
  39. </ul>
  40. <p>
  41. If you&apos;d like to try it out,{' '}
  42. <a
  43. href="https://github.com/sponsors/steveruizok"
  44. target="_blank"
  45. rel="noopener noreferrer"
  46. >
  47. sponsor me on GitHub
  48. </a>{' '}
  49. (at any level) and sign in below.
  50. </p>
  51. <StyledButtonGroup>
  52. {session ? (
  53. <>
  54. <StyledButton variant="secondary" onClick={() => signout()}>
  55. Sign Out
  56. </StyledButton>
  57. <StyledDetail>
  58. Signed in as {session?.user?.name} ({session?.user?.email}), but it looks like
  59. you&apos;re not yet a sponsor.
  60. <br />
  61. Something wrong? Try <Link href="/">reloading the page</Link> or DM me on{' '}
  62. <a
  63. target="_blank"
  64. rel="noreferrer nofollow noopener"
  65. href="https://twitter.com/steveruizok"
  66. >
  67. Twitter
  68. </a>
  69. .
  70. </StyledDetail>
  71. </>
  72. ) : (
  73. <>
  74. <StyledButton variant="primary" onClick={() => signin('github')}>
  75. {loading ? 'Loading...' : 'Sign in with GitHub'}
  76. </StyledButton>
  77. <StyledDetail>Already a sponsor? Just sign in to visit the app.</StyledDetail>
  78. </>
  79. )}
  80. </StyledButtonGroup>
  81. </StyledContent>
  82. </StyledOuterContent>
  83. </>
  84. )
  85. }
  86. export const getServerSideProps: GetServerSideProps = async (context) => {
  87. const session = await getSession(context)
  88. return {
  89. props: {
  90. session,
  91. },
  92. }
  93. }
  94. const StyledOuterContent = styled('div', {
  95. backgroundColor: '$canvas',
  96. padding: '8px 8px 64px 8px',
  97. margin: '0 auto',
  98. overflow: 'scroll',
  99. position: 'fixed',
  100. display: 'flex',
  101. justifyContent: 'center',
  102. alignItems: 'flex-start',
  103. top: 0,
  104. left: 0,
  105. right: 0,
  106. bottom: 0,
  107. width: '100%',
  108. height: '100%',
  109. })
  110. const StyledContent = styled('div', {
  111. width: '720px',
  112. padding: '8px 16px',
  113. maxWidth: '100%',
  114. backgroundColor: '$panel',
  115. borderRadius: '4px',
  116. boxShadow: '$12',
  117. color: '$text',
  118. fontSize: '$2',
  119. fontFamily: '$body',
  120. lineHeight: 1.5,
  121. '& a': {
  122. color: '$bounds',
  123. backgroundColor: '$boundsBg',
  124. padding: '2px 4px',
  125. margin: '0 -3px',
  126. borderRadius: '2px',
  127. },
  128. '& p': {
  129. borderRadius: '8px',
  130. },
  131. '& video': {
  132. maxWidth: '100%',
  133. border: '1px solid $overlay',
  134. borderRadius: '4px',
  135. overflow: 'hidden',
  136. margin: '16px 0',
  137. },
  138. '& iframe': {
  139. border: 'none',
  140. backgroundColor: 'none',
  141. background: 'none',
  142. },
  143. variants: {
  144. size: {
  145. small: {
  146. fontSize: '$3',
  147. padding: '32px',
  148. },
  149. },
  150. },
  151. })
  152. const StyledButtonGroup = styled('div', {
  153. display: 'grid',
  154. gap: '16px',
  155. margin: '40px 0 32px 0',
  156. })
  157. const StyledDetail = styled('p', {
  158. fontSize: '$2',
  159. textAlign: 'center',
  160. })
  161. const StyledButton = styled('button', {
  162. cursor: 'pointer',
  163. width: '100%',
  164. padding: '12px 0',
  165. display: 'flex',
  166. alignItems: 'center',
  167. justifyContent: 'center',
  168. font: '$ui',
  169. fontSize: '$3',
  170. color: '$panel',
  171. border: 'none',
  172. borderRadius: '4px',
  173. variants: {
  174. variant: {
  175. primary: {
  176. fontWeight: 'bold',
  177. background: '$bounds',
  178. color: '$panel',
  179. boxShadow: '$4',
  180. },
  181. secondary: {
  182. border: '1px solid $overlay',
  183. background: 'transparent',
  184. color: '$muted',
  185. },
  186. },
  187. },
  188. })