jbilcke commited on
Commit
6cc7c15
β€’
1 Parent(s): 3da1201

better instructions for sharing

Browse files
src/app/interface/ai-clip-factory/index.tsx CHANGED
@@ -9,7 +9,7 @@ export function AIClipFactory() {
9
  window.open("https://huggingface.co/spaces/jbilcke-hf/ai-clip-factory?postId=f63df23d-de2f-4dee-961c-a56f160dd159&prompt=pikachu%2C+working+on+a+computer%2C+office%2C+serious%2C+typing%2C+keyboard&model=TheLastBen%2FPikachu_SDXL", "_blank")
10
  }}>
11
  <span className="hidden md:inline">Try the clip factory!</span>
12
- <span className="inline md:hidden">AI Clips</span>
13
  </Button>
14
  )
15
  }
 
9
  window.open("https://huggingface.co/spaces/jbilcke-hf/ai-clip-factory?postId=f63df23d-de2f-4dee-961c-a56f160dd159&prompt=pikachu%2C+working+on+a+computer%2C+office%2C+serious%2C+typing%2C+keyboard&model=TheLastBen%2FPikachu_SDXL", "_blank")
10
  }}>
11
  <span className="hidden md:inline">Try the clip factory!</span>
12
+ <span className="inline md:hidden">Clips</span>
13
  </Button>
14
  )
15
  }
src/app/interface/bottom-bar/index.tsx CHANGED
@@ -1,14 +1,12 @@
1
  import { useStore } from "@/app/store"
2
- import { HuggingClap } from "@/components/icons/hugging-clap"
3
  import { Button } from "@/components/ui/button"
4
- import { base64ToFile } from "@/lib/base64ToFile"
5
- import { uploadToHuggingFace } from "@/lib/uploadToHuggingFace"
6
  import { cn } from "@/lib/utils"
7
  import { About } from "../about"
8
  import { startTransition, useState } from "react"
9
  import { upscaleImage } from "@/app/engine/render"
10
  import { sleep } from "@/lib/sleep"
11
  import { AIClipFactory } from "../ai-clip-factory"
 
12
 
13
  export function BottomBar() {
14
  const download = useStore(state => state.download)
@@ -58,45 +56,10 @@ export function BottomBar() {
58
  })
59
  }
60
 
61
- const handleShare = async () => {
62
- const dataUrl = await pageToImage()
63
- // console.log("dataUrl:", dataUrl)
64
- const fileToUpload = base64ToFile(dataUrl, "comic.png")
65
- let uploadUrl = ""
66
- try {
67
- uploadUrl = await uploadToHuggingFace(fileToUpload)
68
- // console.log("uploadUrl:", uploadUrl)
69
- } catch (err) {
70
- console.error("Failed to upload the image to Hugging Face")
71
- }
72
-
73
-
74
- const descriptionMd = `
75
- #### Prompt:
76
- \`\`\`${prompt}\`\`\`
77
-
78
- #### Preset:
79
- \`\`\`${preset.label}\`\`\`
80
-
81
- #### Comic:
82
- ${uploadUrl
83
- ? (`![${prompt}](${uploadUrl})`)
84
- : (`(please drag & drop a capture of your comic here - we recommend you to print the PDF and convert it to JPG for best quality!)`)}
85
- `;
86
-
87
- // console.log("descriptionMd:", descriptionMd)
88
-
89
- const params = new URLSearchParams({
90
- title: `[Comic] ${prompt}`,
91
- description: descriptionMd,
92
- });
93
- const paramsStr = params.toString();
94
- window.open(`https://huggingface.co/spaces/jbilcke-hf/comic-factory/discussions/new?${paramsStr}`, '_blank');
95
- }
96
-
97
  const handlePrint = () => {
98
  window.print()
99
  }
 
100
  return (
101
  <div className={cn(
102
  `print:hidden`,
@@ -163,7 +126,6 @@ ${uploadUrl
163
  </Button>
164
  </div>
165
  */}
166
- <div>
167
  <Button
168
  onClick={handlePrint}
169
  disabled={!prompt?.length}
@@ -172,28 +134,10 @@ ${uploadUrl
172
  remainingImages ? `${allStatus.length - remainingImages}/${allStatus.length} panels βŒ›` : `Save PDF`
173
  }</span>
174
  <span className="inline md:hidden">{
175
- remainingImages ? `${allStatus.length - remainingImages}/${allStatus.length} βŒ›` : `Save PDF`
176
  }</span>
177
- </Button>
178
- </div>
179
- <div>
180
- {
181
- // there is an issue, this env check doesn't work..
182
- // process.env.NEXT_PUBLIC_ENABLE_COMMUNITY_SHARING === "true" ?
183
- <Button
184
- onClick={handleShare}
185
- disabled={!prompt?.length}
186
- className="space-x-2"
187
- >
188
- <div className="scale-105"><HuggingClap /></div>
189
- <div>
190
- <span className="hidden md:inline">Share to community</span>
191
- <span className="inline md:hidden">Share</span>
192
- </div>
193
- </Button>
194
- //: null
195
- }
196
- </div>
197
  </div>
198
  </div>
199
  )
 
1
  import { useStore } from "@/app/store"
 
2
  import { Button } from "@/components/ui/button"
 
 
3
  import { cn } from "@/lib/utils"
4
  import { About } from "../about"
5
  import { startTransition, useState } from "react"
6
  import { upscaleImage } from "@/app/engine/render"
7
  import { sleep } from "@/lib/sleep"
8
  import { AIClipFactory } from "../ai-clip-factory"
9
+ import { Share } from "../share"
10
 
11
  export function BottomBar() {
12
  const download = useStore(state => state.download)
 
56
  })
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  const handlePrint = () => {
60
  window.print()
61
  }
62
+
63
  return (
64
  <div className={cn(
65
  `print:hidden`,
 
126
  </Button>
127
  </div>
128
  */}
 
129
  <Button
130
  onClick={handlePrint}
131
  disabled={!prompt?.length}
 
134
  remainingImages ? `${allStatus.length - remainingImages}/${allStatus.length} panels βŒ›` : `Save PDF`
135
  }</span>
136
  <span className="inline md:hidden">{
137
+ remainingImages ? `${allStatus.length - remainingImages}/${allStatus.length} βŒ›` : `Save`
138
  }</span>
139
+ </Button>
140
+ <Share />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  </div>
142
  </div>
143
  )
src/app/interface/share/index.tsx ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useStore } from "@/app/store"
2
+ import { HuggingClap } from "@/components/icons/hugging-clap"
3
+ import { Button } from "@/components/ui/button"
4
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
5
+ import { useState } from "react"
6
+
7
+ export function Share() {
8
+ const [isOpen, setOpen] = useState(false)
9
+ const preset = useStore(state => state.preset)
10
+ const prompt = useStore(state => state.prompt)
11
+ const panelGenerationStatus = useStore(state => state.panelGenerationStatus)
12
+ const allStatus = Object.values(panelGenerationStatus)
13
+ const remainingImages = allStatus.reduce((acc, s) => (acc + (s ? 1 : 0)), 0)
14
+
15
+
16
+ const handlePrint = () => {
17
+ window.print()
18
+ }
19
+
20
+ const handleShare = async () => {
21
+ /*
22
+
23
+ ------------------------------------------------------------------
24
+ Legacy mode: PNG export doesn't work well, so we are disabling it.
25
+ ------------------------------------------------------------------
26
+
27
+ const dataUrl = await pageToImage()
28
+ // console.log("dataUrl:", dataUrl)
29
+ const fileToUpload = base64ToFile(dataUrl, "comic.png")
30
+ let uploadUrl = ""
31
+ try {
32
+ uploadUrl = await uploadToHuggingFace(fileToUpload)
33
+ // console.log("uploadUrl:", uploadUrl)
34
+ } catch (err) {
35
+ console.error("Failed to upload the image to Hugging Face")
36
+ }
37
+
38
+ const comicFileMd = `
39
+ #### Comic:
40
+ ${uploadUrl
41
+ ? (`![${prompt}](${uploadUrl})`)
42
+ : (`(please drag & drop a capture of your comic here - we recommend you to print the PDF and convert it to JPG for best quality!)`)}
43
+ `;
44
+ */
45
+
46
+ const storyPrompt = (prompt.split("||")[1] || "")
47
+
48
+ const storyPromptMd = storyPrompt ? `
49
+ #### Story prompt:
50
+ \`\`\`${storyPrompt}\`\`\`
51
+ ` : ``
52
+
53
+ const stylePrompt = (prompt.split("||")[0] || "")
54
+
55
+ const stylePromptMd = stylePrompt ? `
56
+ #### Style prompt:
57
+ \`\`\`${stylePrompt}\`\`\`
58
+ ` : ``
59
+
60
+ const comicFileMd =
61
+ `### Comic:
62
+
63
+ Drag & drop your comic image (converted to JPG) here!
64
+ `
65
+
66
+ const descriptionMd = `
67
+ ${storyPromptMd}
68
+ ${stylePromptMd}
69
+ #### Preset:
70
+ \`\`\`${preset.label}\`\`\`
71
+
72
+ ${comicFileMd}`;
73
+
74
+ // console.log("descriptionMd:", descriptionMd)
75
+
76
+ const params = new URLSearchParams({
77
+ title: `[Comic] ${prompt}`,
78
+ description: descriptionMd,
79
+ });
80
+ const paramsStr = params.toString();
81
+ window.open(`https://huggingface.co/spaces/jbilcke-hf/comic-factory/discussions/new?${paramsStr}`, '_blank');
82
+ }
83
+
84
+ <div>
85
+ {
86
+ // there is an issue, this env check doesn't work..
87
+ // process.env.NEXT_PUBLIC_ENABLE_COMMUNITY_SHARING === "true" ?
88
+ <Button
89
+ onClick={handleShare}
90
+ disabled={!prompt?.length}
91
+ className="space-x-2"
92
+ >
93
+ <div className="scale-105"><HuggingClap /></div>
94
+ <div>
95
+ <span className="hidden md:inline">{remainingImages ? `βŒ›` : `Share to community`}</span>
96
+ <span className="inline md:hidden">{remainingImages ? `βŒ›` : `Share`}</span>
97
+ </div>
98
+ </Button>
99
+ //: null
100
+ }
101
+ </div>
102
+
103
+ return (
104
+ <Dialog open={isOpen} onOpenChange={setOpen}>
105
+ <DialogTrigger asChild>
106
+ <Button
107
+ disabled={!prompt?.length}
108
+ className="space-x-1 md:space-x-2"
109
+ >
110
+ <div className="scale-105"><HuggingClap /></div>
111
+ <div>
112
+ <span className="hidden md:inline">{remainingImages ? `βŒ›` : `Share to community`}</span>
113
+ <span className="inline md:hidden">{remainingImages ? `βŒ›` : `Share`}</span>
114
+ </div>
115
+ </Button>
116
+ </DialogTrigger>
117
+ <DialogContent className="sm:max-w-[425px]">
118
+ <DialogHeader>
119
+ <DialogDescription className="w-full text-center text-lg font-bold text-stone-800">
120
+ Sharing Your Comic
121
+ </DialogDescription>
122
+ </DialogHeader>
123
+ <div className="grid gap-4 py-4 text-stone-800">
124
+ <p className="">
125
+ To ensure optimal output quality comics are saved as PDF files:
126
+ </p>
127
+ <p>
128
+ πŸ‘‰ Step 1: Click on <Button
129
+ onClick={handlePrint}
130
+ disabled={!prompt?.length}
131
+ >
132
+ <span className="hidden md:inline">{
133
+ remainingImages ? `${allStatus.length - remainingImages}/${allStatus.length} panels βŒ›` : `Save PDF`
134
+ }</span>
135
+ <span className="inline md:hidden">{
136
+ remainingImages ? `${allStatus.length - remainingImages}/${allStatus.length} βŒ›` : `Save`
137
+ }</span>
138
+ </Button>
139
+ </p>
140
+ <p>
141
+ πŸ‘‰ Step 2: Select &quot;Print to PDF&quot; in the printing options
142
+ </p>
143
+ <p>
144
+ πŸ‘‰ Step 3: Open your PDF and convert it to a JPG image (using &quot;Export to&quot; or &quot;Convert to&quot;)
145
+ </p>
146
+ <p>
147
+ πŸ‘‰ Step 4: Click here to post: <Button
148
+ onClick={handleShare}
149
+ className="space-x-2"
150
+ >
151
+ <div className="scale-105"><HuggingClap /></div>
152
+ <div>
153
+ Share
154
+ </div>
155
+ </Button>
156
+ </p>
157
+ </div>
158
+ <DialogFooter>
159
+ <Button type="submit" onClick={() => setOpen(false)}>Close</Button>
160
+ </DialogFooter>
161
+ </DialogContent>
162
+ </Dialog>
163
+ )
164
+ }
src/app/interface/top-menu/index.tsx CHANGED
@@ -202,7 +202,7 @@ export function TopMenu() {
202
  <div className="flex flex-row flex-grow w-full">
203
  <div className="flex flex-row flex-grow w-full">
204
  <Input
205
- placeholder="1. Little story.."
206
  className="w-1/2 bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800 rounded-r-none border-r-stone-100"
207
  // disabled={atLeastOnePanelIsBusy}
208
  onChange={(e) => {
@@ -216,7 +216,7 @@ export function TopMenu() {
216
  value={draftPromptB}
217
  />
218
  <Input
219
- placeholder="2. Global style (optional)"
220
  className="w-1/2 bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800 border-l-stone-100 rounded-l-none rounded-r-none"
221
  // disabled={atLeastOnePanelIsBusy}
222
  onChange={(e) => {
 
202
  <div className="flex flex-row flex-grow w-full">
203
  <div className="flex flex-row flex-grow w-full">
204
  <Input
205
+ placeholder="1. Story prompt"
206
  className="w-1/2 bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800 rounded-r-none border-r-stone-100"
207
  // disabled={atLeastOnePanelIsBusy}
208
  onChange={(e) => {
 
216
  value={draftPromptB}
217
  />
218
  <Input
219
+ placeholder="2. Style prompt (optional)"
220
  className="w-1/2 bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800 border-l-stone-100 rounded-l-none rounded-r-none"
221
  // disabled={atLeastOnePanelIsBusy}
222
  onChange={(e) => {