Browse Source

[chore] Sponsors in README (#301)

* Add images, read me links

* Add API route for sponsor image

* Update cache max age
main
Steve Ruiz 3 years ago
parent
commit
cd48b67a74
No account linked to committer's email address

+ 1
- 0
.gitignore View File

@@ -14,3 +14,4 @@ coverage
14 14
 apps/www/public/worker-*
15 15
 apps/www/public/sw.js
16 16
 apps/www/public/sw.js.map
17
+.env

+ 14
- 6
README.md View File

@@ -1,5 +1,5 @@
1 1
 <div style="text-align: center; transform: scale(.5);">
2
-  <img src="card-repo.png"/>
2
+  <img src="./assets/tldraw.png"/>
3 3
 </div>
4 4
 
5 5
 Welcome to the [tldraw](https://tldraw.com) monorepo. Here you'll find the source code for [@tldraw/tldraw](https://www.npmjs.com/package/@tldraw/tldraw), [@tldraw/core](https://www.npmjs.com/package/@tldraw/core), and the tldraw.com website.
@@ -8,6 +8,14 @@ Welcome to the [tldraw](https://tldraw.com) monorepo. Here you'll find the sourc
8 8
 
9 9
 💕 Love this project? Consider [becoming a sponsor](https://github.com/sponsors/steveruizok?frequency=recurring&sponsor=steveruizok).
10 10
 
11
+Thanks to our corporate sponsors:
12
+
13
+<a href="https://sentry.io"><img src="./assets/sentry.svg"></img></a>
14
+
15
+<a href="https://vercel.com/?utm_source=team-slug&utm_campaign=oss"><img src="./assets/vercel.svg"></img></a>
16
+
17
+...and to our [individual sponsors](https://github.com/sponsors/steveruizok#sponsors)!
18
+
11 19
 ## Contents
12 20
 
13 21
 This repository is a monorepo containing two packages:
@@ -27,18 +35,18 @@ This repository is a monorepo containing two packages:
27 35
 - [**examples/core-example-advanced**](https://github.com/tldraw/tldraw/tree/main/examples/core-example-advanced) is a second example for `@tldraw/core`.
28 36
 - [**examples/tldraw-example**](https://github.com/tldraw/tldraw/tree/main/examples/tldraw-example) is an example for `@tldraw/tldraw`.
29 37
 
38
+## Discussion
39
+
40
+Want to connect? Visit the [Discord channel](https://discord.gg/SBBEVCA4PG).
41
+
30 42
 ## Contribution
31 43
 
32
-See the [contributing guide](/CONTRIBUTING.md).
44
+Interested in contributing? See the [contributing guide](/CONTRIBUTING.md).
33 45
 
34 46
 ## Support
35 47
 
36 48
 Need help? Please [open an issue](https://github.com/tldraw/tldraw/issues/new) for support.
37 49
 
38
-## Discussion
39
-
40
-Want to connect with other devs? Visit the [Discord channel](https://discord.gg/SBBEVCA4PG).
41
-
42 50
 ## License
43 51
 
44 52
 This project is licensed under MIT.

+ 0
- 1
apps/www/.env View File

@@ -1 +0,0 @@
1
-NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_API_KEY=pk_live_1LJGGaqBSNLjLT-4Jalkl-U9

+ 2
- 2
apps/www/components/Editor.tsx View File

@@ -11,7 +11,7 @@ interface EditorProps {
11 11
   isSponsor?: boolean
12 12
 }
13 13
 
14
-export default function Editor({ id = 'home', isSponsor = false }: EditorProps) {
14
+export default function Editor({ id = 'home', isUser = false, isSponsor = false }: EditorProps) {
15 15
   const handleMount = React.useCallback((app: TldrawApp) => {
16 16
     window.app = app
17 17
   }, [])
@@ -39,7 +39,7 @@ export default function Editor({ id = 'home', isSponsor = false }: EditorProps)
39 39
         onPersist={handlePersist}
40 40
         showSponsorLink={!isSponsor}
41 41
         onSignIn={isSponsor ? undefined : onSignIn}
42
-        onSignOut={onSignOut}
42
+        onSignOut={isUser ? onSignOut : undefined}
43 43
         {...fileSystemEvents}
44 44
       />
45 45
     </div>

+ 10
- 2
apps/www/components/MultiplayerEditor.tsx View File

@@ -38,7 +38,15 @@ export default function MultiplayerEditor({
38 38
 
39 39
 // Inner Editor
40 40
 
41
-function Editor({ roomId, isSponsor }: { roomId: string; isUser; isSponsor: boolean }) {
41
+function Editor({
42
+  roomId,
43
+  isUser,
44
+  isSponsor,
45
+}: {
46
+  roomId: string
47
+  isUser: boolean
48
+  isSponsor: boolean
49
+}) {
42 50
   const [docId] = React.useState(() => Utils.uniqueId())
43 51
 
44 52
   const [app, setApp] = React.useState<TldrawApp>()
@@ -175,7 +183,7 @@ function Editor({ roomId, isSponsor }: { roomId: string; isUser; isSponsor: bool
175 183
         showPages={false}
176 184
         showSponsorLink={isSponsor}
177 185
         onSignIn={isSponsor ? undefined : onSignIn}
178
-        onSignOut={onSignOut}
186
+        onSignOut={isUser ? onSignOut : undefined}
179 187
         {...fileSystemEvents}
180 188
       />
181 189
     </div>

+ 1
- 25
apps/www/pages/api/auth/[...nextauth].ts View File

@@ -1,3 +1,4 @@
1
+import { isSponsoringMe } from '-utils/isSponsoringMe'
1 2
 import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
2 3
 import NextAuth from 'next-auth'
3 4
 import Providers from 'next-auth/providers'
@@ -30,28 +31,3 @@ export default function Auth(
30 31
     },
31 32
   })
32 33
 }
33
-
34
-const whitelist = ['steveruizok']
35
-
36
-async function isSponsoringMe(login: string) {
37
-  if (whitelist.includes(login)) return true
38
-
39
-  const res = await fetch('https://api.github.com/graphql', {
40
-    method: 'POST',
41
-    headers: {
42
-      'Content-Type': 'application/json',
43
-      Authorization: 'bearer ' + process.env.GITHUB_API_SECRET,
44
-    },
45
-    body: JSON.stringify({
46
-      query: `
47
-        query { 
48
-          user(login: "steveruizok") { 
49
-            isSponsoredBy(accountLogin: "${login}") 
50
-          } 
51
-        }
52
-      `,
53
-    }),
54
-  }).then((res) => res.json())
55
-
56
-  return res?.data?.user?.isSponsoredBy
57
-}

+ 96
- 0
apps/www/pages/api/sponsors.ts View File

@@ -0,0 +1,96 @@
1
+import { NextApiRequest, NextApiResponse } from 'next'
2
+
3
+const AV_SIZE = 32
4
+const PADDING = 4
5
+const COLS = 16
6
+
7
+type SponsorResult = { url: string; login: string }
8
+type QueryResult = {
9
+  node: { sponsorEntity: { avatarUrl: string; login: string } }
10
+}
11
+
12
+function getXY(i: number) {
13
+  return [(i % COLS) * (AV_SIZE + PADDING), Math.floor(i / COLS) * (AV_SIZE + PADDING)]
14
+}
15
+
16
+export default async function GetSponsors(req: NextApiRequest, res: NextApiResponse) {
17
+  const sponsorInfo = await fetch('https://api.github.com/graphql', {
18
+    method: 'POST',
19
+    headers: {
20
+      'Content-Type': 'application/json',
21
+      Authorization: 'bearer ' + process.env.GITHUB_API_SECRET,
22
+    },
23
+    body: JSON.stringify({
24
+      query: `{
25
+        viewer {
26
+          sponsors(first: 0) {
27
+            totalCount
28
+          }
29
+          sponsorshipsAsMaintainer(first: 100, orderBy: {
30
+            field:CREATED_AT,
31
+            direction:DESC
32
+          }) {
33
+            edges {
34
+              node {
35
+                sponsorEntity {
36
+                  ...on User {
37
+                    avatarUrl
38
+                    login
39
+                  }
40
+                }
41
+              }
42
+            }
43
+          }
44
+        }
45
+      }`,
46
+    }),
47
+  }).then((res) => res.json())
48
+
49
+  const totalCount: number = sponsorInfo.data.viewer.sponsors.totalCount
50
+
51
+  const results = (
52
+    sponsorInfo.data.viewer.sponsorshipsAsMaintainer.edges as QueryResult[]
53
+  ).map<SponsorResult>((edge) => ({
54
+    url: edge.node.sponsorEntity.avatarUrl?.replaceAll('&', '&amp;') ?? '',
55
+    login: edge.node.sponsorEntity.login,
56
+  }))
57
+
58
+  if (results.length % COLS <= 2) {
59
+    results.pop()
60
+    results.pop()
61
+    results.pop()
62
+  }
63
+
64
+  // Avatars
65
+
66
+  const avatars = results
67
+    .map(({ url, login }, i) => {
68
+      const [x, y] = getXY(i)
69
+      return `<image alt="${login}" href="${url}" x="${x}" y="${y}" width="${AV_SIZE}" height="${AV_SIZE}"/>`
70
+    })
71
+    .join('')
72
+
73
+  // More text
74
+
75
+  const [x, y] = getXY(results.length)
76
+  const width = (AV_SIZE + PADDING) * 3
77
+  const more = `
78
+  <g transform="translate(${x},${y})"><text text-lenth="${width}" font-family="Arial" font-size="12px" font-weight="bold" text-anchor="middle" text-align="center" x="${
79
+    width / 2
80
+  }" y="${AV_SIZE / 2 + 3}">...and ${totalCount - 100} more!</text></g>`
81
+
82
+  const svgImage = `
83
+<svg xmlns="http://www.w3.org/2000/svg"><a href="https://github.com/sponsors/steveruizok"><g>${avatars}${more}</g></a></svg>`
84
+
85
+  // const html = `
86
+  // <div style="display: grid; width: fit-content; grid-template-columns: repeat(25, auto); gap: 4px;">
87
+  //     ${images.join(`
88
+  //       `)}
89
+  // </div>`
90
+
91
+  res
92
+    .status(200)
93
+    .setHeader('Cache-Control', 'max-age=604800')
94
+    .setHeader('Content-Type', 'image/svg+xml')
95
+    .send(svgImage)
96
+}

+ 1
- 1
apps/www/pages/index.tsx View File

@@ -26,7 +26,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
26 26
 
27 27
   return {
28 28
     props: {
29
-      isUser: false,
29
+      isUser: session?.user,
30 30
       isSponsor: session?.user ? true : false,
31 31
     },
32 32
   }

+ 1
- 1
apps/www/pages/r/[id].tsx View File

@@ -22,7 +22,7 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
22 22
   return {
23 23
     props: {
24 24
       id,
25
-      isUser: false,
25
+      isUser: session?.user,
26 26
       isSponsor: session?.user ? true : false,
27 27
     },
28 28
   }

+ 24
- 0
apps/www/utils/isSponsoringMe.ts View File

@@ -0,0 +1,24 @@
1
+const whitelist = ['steveruizok']
2
+
3
+export async function isSponsoringMe(login: string) {
4
+  if (whitelist.includes(login)) return true
5
+
6
+  const res = await fetch('https://api.github.com/graphql', {
7
+    method: 'POST',
8
+    headers: {
9
+      'Content-Type': 'application/json',
10
+      Authorization: 'bearer ' + process.env.GITHUB_API_SECRET,
11
+    },
12
+    body: JSON.stringify({
13
+      query: `
14
+        query { 
15
+          user(login: "steveruizok") { 
16
+            isSponsoredBy(accountLogin: "${login}") 
17
+          } 
18
+        }
19
+      `,
20
+    }),
21
+  }).then((res) => res.json())
22
+
23
+  return res?.data?.user?.isSponsoredBy
24
+}

+ 1
- 0
assets/sentry.svg View File

@@ -0,0 +1 @@
1
+<svg class="__sntry__ css-15xgryy e10nushx5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 44" width="212" height="47" style=""><defs><style type="text/css">@media (prefers-color-scheme: dark) {path.__sntry__ { fill: #362d59 !important; }}</style></defs><path d="M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z M124.32,28.28,109.56,9.22h-3.68V34.77h3.73V15.19l15.18,19.58h3.26V9.22h-3.73ZM87.15,23.54h13.23V20.22H87.14V12.53h14.93V9.21H83.34V34.77h18.92V31.45H87.14ZM71.59,20.3h0C66.44,19.06,65,18.08,65,15.7c0-2.14,1.89-3.59,4.71-3.59a12.06,12.06,0,0,1,7.07,2.55l2-2.83a14.1,14.1,0,0,0-9-3c-5.06,0-8.59,3-8.59,7.27,0,4.6,3,6.19,8.46,7.52C74.51,24.74,76,25.78,76,28.11s-2,3.77-5.09,3.77a12.34,12.34,0,0,1-8.3-3.26l-2.25,2.69a15.94,15.94,0,0,0,10.42,3.85c5.48,0,9-2.95,9-7.51C79.75,23.79,77.47,21.72,71.59,20.3ZM195.7,9.22l-7.69,12-7.64-12h-4.46L186,24.67V34.78h3.84V24.55L200,9.22Zm-64.63,3.46h8.37v22.1h3.84V12.68h8.37V9.22H131.08ZM169.41,24.8c3.86-1.07,6-3.77,6-7.63,0-4.91-3.59-8-9.38-8H154.67V34.76h3.8V25.58h6.45l6.48,9.2h4.44l-7-9.82Zm-10.95-2.5V12.6h7.17c3.74,0,5.88,1.77,5.88,4.84s-2.29,4.86-5.84,4.86Z" fill="#ffffff" class="__sntry__"></path></svg>

card-repo.png → assets/tldraw.png View File


+ 6
- 0
assets/vercel.svg
File diff suppressed because it is too large
View File


+ 0
- 1
examples/tldraw-example/.env View File

@@ -1 +0,0 @@
1
-LIVEBLOCKS_PUBLIC_API_KEY=pk_live_1LJGGaqBSNLjLT-4Jalkl-U9

+ 20
- 1
yarn.lock View File

@@ -9341,7 +9341,7 @@ jose@^1.27.2:
9341 9341
   dependencies:
9342 9342
     "@panva/asn1.js" "^1.0.0"
9343 9343
 
9344
-jpeg-js@^0.4.2:
9344
+jpeg-js@^0.4.1, jpeg-js@^0.4.2:
9345 9345
   version "0.4.3"
9346 9346
   resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b"
9347 9347
   integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==
@@ -11183,6 +11183,11 @@ only@~0.0.2:
11183 11183
   resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
11184 11184
   integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=
11185 11185
 
11186
+opentype.js@^0.4.3:
11187
+  version "0.4.11"
11188
+  resolved "https://registry.yarnpkg.com/opentype.js/-/opentype.js-0.4.11.tgz#281a2390639cc15931c955d8d63c14a7c7772b41"
11189
+  integrity sha1-KBojkGOcwVkxyVXY1jwUp8d3K0E=
11190
+
11186 11191
 optionator@^0.8.1:
11187 11192
   version "0.8.3"
11188 11193
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
@@ -11711,6 +11716,11 @@ plist@^3.0.1:
11711 11716
     base64-js "^1.5.1"
11712 11717
     xmlbuilder "^9.0.7"
11713 11718
 
11719
+pngjs@^3.3.1:
11720
+  version "3.4.0"
11721
+  resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
11722
+  integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
11723
+
11714 11724
 pngjs@^5.0.0:
11715 11725
   version "5.0.0"
11716 11726
   resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
@@ -11975,6 +11985,15 @@ pupa@^2.1.1:
11975 11985
   dependencies:
11976 11986
     escape-goat "^2.0.0"
11977 11987
 
11988
+pureimage@^0.3.6:
11989
+  version "0.3.6"
11990
+  resolved "https://registry.yarnpkg.com/pureimage/-/pureimage-0.3.6.tgz#3ab6070e2779193a8767fc9b657d41c6894b070f"
11991
+  integrity sha512-Wtk+QdlB1X7wnfaXads+5i6tI95dNMyR7Hq9Q0qmEOXiG38JvPRcAISSzuSVGXPlgi54VFzl26ic8UpT6GLs6g==
11992
+  dependencies:
11993
+    jpeg-js "^0.4.1"
11994
+    opentype.js "^0.4.3"
11995
+    pngjs "^3.3.1"
11996
+
11978 11997
 q@^1.5.1:
11979 11998
   version "1.5.1"
11980 11999
   resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"

Loading…
Cancel
Save