Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸŽ‰ Waifu minter #4427

Merged
merged 64 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4f963b9
:tada: generative
vikiival Nov 13, 2022
c751448
:wrench: added replicate url
vikiival Nov 13, 2022
4b6c484
:zap: Replicate Service Worker
vikiival Nov 13, 2022
cce5166
:zap: predict function
vikiival Nov 15, 2022
ec2f8c7
:zap: using anime-waifu instead of 16-bit
vikiival Nov 15, 2022
8133f87
:zap: image grid
vikiival Nov 15, 2022
1e9a73b
:sparkles: SelectableImage
vikiival Nov 15, 2022
2536b39
:sparkles: ImageGrid
vikiival Nov 15, 2022
4552d22
:zap: fixed props
vikiival Nov 15, 2022
5c7878c
:zap: propagate disabled to selectable image
vikiival Nov 16, 2022
6cc2148
:art: quick fix so text is not light gray
vikiival Nov 16, 2022
5b38352
:sparkles: CongratsView.vue
vikiival Nov 16, 2022
8380ccb
:sparkles: ContactForm.vue
vikiival Nov 16, 2022
a6a757c
:sparkles: GenerativeMintForm.vue
vikiival Nov 16, 2022
7c4c74b
:sparkles: ImageSelectGrid.vue
vikiival Nov 16, 2022
b3cb58a
:art: congrats view has image 1by1
vikiival Nov 16, 2022
185724c
:zap: Submit button in composition API
vikiival Nov 16, 2022
9656d33
:zap: Generative mint has steps
vikiival Nov 16, 2022
2ec00b5
Merge remote-tracking branch 'origin/main' into waifu-mint
vikiival Nov 16, 2022
06a635f
:bug: step has not started from step 1
vikiival Nov 16, 2022
fa89455
:bug: handle click emitted wrong data
vikiival Nov 16, 2022
cee87f1
:bug: listening to bad event
vikiival Nov 16, 2022
ada8d6d
:bug: forgot to set correct prompt
vikiival Nov 17, 2022
df663ed
:bug: correct step numbers
vikiival Nov 17, 2022
ee3e4de
aaaaa still can fix image selector properly
vikiival Nov 17, 2022
fbd4e2a
:art: tweaking button color
vikiival Nov 17, 2022
0314c31
:wheelchair: remove navigation
vikiival Nov 18, 2022
fd58a87
:sparkles: radioselect
vikiival Nov 18, 2022
da032d2
:tada: set of options
vikiival Nov 20, 2022
dce51af
:bug: ability to select none
vikiival Nov 20, 2022
3ab86db
:zap: finally cute form
vikiival Nov 20, 2022
fee2ca1
:zap: naive impl of prompt builder
vikiival Nov 20, 2022
69f34ac
:bug: show-empty is not required
vikiival Nov 20, 2022
dbc0aa7
:zap: ability to apply style
vikiival Nov 20, 2022
a1f4810
:bug: prompt builder without spaces
vikiival Nov 20, 2022
c62792b
:zap: bring back minting process
vikiival Nov 20, 2022
91d3015
:bug: start over went to bad step
vikiival Nov 20, 2022
b881f6e
:zap: prod addr
vikiival Nov 23, 2022
a36fa84
:tada: supabase functions
vikiival Nov 24, 2022
ce0dc42
:zap: submit button can be expanded
vikiival Nov 24, 2022
2849cea
:zap: all submit buttons are expanded
vikiival Nov 24, 2022
2ee553f
:zap: send correct value to supabase service
vikiival Nov 25, 2022
d22c2e9
:sparkles: BasicInput can be disabled
vikiival Nov 25, 2022
ea2716c
:sparkles: tell how many were generated by @just_luuuu
vikiival Nov 26, 2022
d380b49
:zap: full supabase API Ready
vikiival Nov 27, 2022
38b670c
:globe_with_meridians: translatioons
vikiival Nov 27, 2022
f666a3a
:zap: log prediction to supabase
vikiival Nov 27, 2022
2f56b27
:tada: netlify waifu service
vikiival Nov 27, 2022
f3058ef
:sparkles: such creative
vikiival Nov 27, 2022
3843611
:sparkles: я поняття Π½Π΅ маю
vikiival Nov 27, 2022
27fd917
:globe_with_meridians: translatioons
vikiival Nov 27, 2022
6a7aa5c
:zap: Π΄ΠΎΠ±Ρ€ΠΈΠΉ Π²Π΅Ρ‡Ρ–Ρ€
vikiival Nov 27, 2022
b7652b2
:wrench: anon key in supabase
vikiival Nov 27, 2022
6a97f96
:zap: send image to waifu minter
vikiival Nov 27, 2022
66cd8b4
:tada: Claim page!
vikiival Nov 27, 2022
a7f51b5
:zap: waifu is powered by supabase proxy
vikiival Nov 27, 2022
a081ffe
:bug: forgot the version of replicate
vikiival Nov 27, 2022
f44629e
:zap: adding seed and version to minter
vikiival Nov 28, 2022
fb6bb65
:bug: bad apii
vikiival Nov 28, 2022
864106d
:bug: fetch not defined
vikiival Nov 28, 2022
a61bbbc
Merge remote-tracking branch 'origin/main' into waifu-mint
vikiival Nov 28, 2022
17d80e4
:zap: claim form
vikiival Nov 29, 2022
bf2d5a6
:bug: claim
vikiival Nov 29, 2022
e1c595c
:snake: waifu
vikiival Nov 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions components/base/SubmitButton.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
<template>
<b-field>
<b-button
type="is-primary"
icon-left="paper-plane"
@click="$emit('click')"
:type="type"
:icon-left="icon"
:disabled="disabled"
:loading="loading"
outlined>
:expanded="expanded"
outlined
@click="$emit('click')">
<slot>
{{ $t(label) }}
</slot>
</b-button>
</b-field>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'nuxt-property-decorator'

@Component({})
export default class SubmitButton extends Vue {
@Prop(Boolean) public disabled!: boolean
@Prop(Boolean) public loading!: boolean
@Prop(String) public label!: string
<script setup lang="ts">
export interface Props {
disabled?: boolean
expanded?: boolean
icon?: string
label: string
loading?: boolean
type?: string
}

const props = withDefaults(defineProps<Props>(), {
loading: false,
disabled: false,
type: 'is-primary',
icon: 'paper-plane',
})
</script>
125 changes: 125 additions & 0 deletions components/bsx/Create/GenerativeMint.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<template>
<div>
<Loader v-model="isLoading" :status="status" />
<b-steps
v-model="currentStep"
:rounded="false"
mobile-mode="minimalist"
:has-navigation="false">
<b-step-item step="1" label="Mint" :clickable="isStepsClickable">
<GenerativeMint @select="handlePrediction" @submit="handleBuilder" />
</b-step-item>

<b-step-item step="2" label="Select" :clickable="isStepsClickable">
<ImageSelectGrid
:predicion="predicion"
:selected="image"
@select="handleImageSelect" />
</b-step-item>

<b-step-item step="3" label="Contact" :clickable="isStepsClickable">
<ContactForm @select="handleMailSubmit" />
</b-step-item>

<b-step-item
step="4"
label="Finish"
:clickable="isStepsClickable"
:type="{ 'is-success': true }">
<CongratsView @select="clearAll" />
</b-step-item>
</b-steps>
</div>
</template>

<script setup lang="ts">
import { PredictionStatus } from '@/services/replicate'
import { sendWaifu } from '@/services/waifu'
import { emptyObject } from '@/utils/empty'
import { notificationTypes, showNotification } from '@/utils/notification'
import { Options, buildMetadata } from '@/components/generative/promptBuilder'

const Loader = defineAsyncComponent(
() => import('@/components/shared/Loader.vue')
)

const GenerativeMint = defineAsyncComponent(
() => import('@/components/generative/GenerativeMintForm.vue')
)

const ImageSelectGrid = defineAsyncComponent(
() => import('@/components/generative/ImageSelectGrid.vue')
)

const ContactForm = defineAsyncComponent(
() => import('@/components/generative/ContactForm.vue')
)

const CongratsView = defineAsyncComponent(
() => import('@/components/generative/CongratsView.vue')
)

const isStepsClickable = ref(true)
const currentStep = ref<number>(0)
const predicion = ref<PredictionStatus>(emptyObject<PredictionStatus>())
const builder = ref<Options>(emptyObject<Options>())
const image = ref<string>('')
const email = ref('')
const isLoading = ref(false)
const status = ref('')

const handlePrediction = (generation: PredictionStatus) => {
predicion.value = generation
goToStep(1)
}

const handleImageSelect = (imageURI: string) => {
image.value = imageURI
goToStep(2)
}

const handleMailSubmit = (mail: string) => {
email.value = mail
submitAll()
goToStep(3)
}

const handleBuilder = (options: Options) => {
builder.value = options
}

const submitAll = async () => {
try {
isLoading.value = true
status.value = 'loader.ipfs'
const metadata = await buildMetadata(
image.value,
builder.value,
predicion.value
)
status.value = 'loader.generative.send'
await sendWaifu(email.value, metadata, image.value)
goToStep(4)
} catch (error) {
showNotification(
'Error: ' + (error as Error).message,
notificationTypes.danger
)
} finally {
isLoading.value = false
status.value = ''
}
console.log('submitAll', predicion.value, image.value, email.value)
}

const clearAll = () => {
predicion.value = emptyObject<PredictionStatus>()
image.value = ''
email.value = ''
goToStep(0)
}

const goToStep = (step: number) => {
currentStep.value = step
}
</script>
30 changes: 30 additions & 0 deletions components/generative/CongratsView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<section>
<br />
<p class="title is-size-3">Waii you made it! ✨</p>
<p class="title is-size-4">Our interns will process it soon!</p>
<b-image
ratio="1by1"
src="https://pbs.twimg.com/media/FhZZxxwXwAAkvKI?format=jpg" />
<br />

<SubmitButton
icon="sync"
type="is-success"
label="Start over"
expanded
@click="submit" />
</section>
</template>

<script setup lang="ts">
const SubmitButton = defineAsyncComponent(
() => import('@/components/base/SubmitButton.vue')
)

const emit = defineEmits(['select'])

const submit = () => {
emit('select')
}
</script>
40 changes: 40 additions & 0 deletions components/generative/ContactForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<section>
<br />
<p class="title is-size-3">Enter your email</p>

<BasicInput
v-model="email"
required
:label="$t('mint.nft.email.label')"
:message="$t('mint.nft.email.message')"
:placeholder="$t('mint.nft.email.placeholder')"
expanded
type="email"
spellcheck="true"
data-cy="input-name" />

<SubmitButton
label="submit"
type="is-info"
icon="envelope"
expanded
@click="submit" />
</section>
</template>

<script setup lang="ts">
const BasicInput = defineAsyncComponent(
() => import('@/components/shared/form/BasicInput.vue')
)
const SubmitButton = defineAsyncComponent(
() => import('@/components/base/SubmitButton.vue')
)

const email = ref('')
const emit = defineEmits(['select'])

const submit = async () => {
emit('select', email.value)
}
</script>
144 changes: 144 additions & 0 deletions components/generative/GenerativeMintForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<template>
<section>
<br />
<Loader v-model="isLoading" :status="status" />
<p class="title is-size-3">Mint your sub0 POAP</p>

<p class="title is-size-4">I want to be</p>
<RadioSelect v-model="form.gender" :options="gender" />

<p class="title is-size-5">on</p>
<RadioSelect v-model="form.art" :options="art" />

<p class="title is-size-5">using</p>
<RadioSelect
v-model="form.style"
:options="isPhoto ? filmTypes : styles"
separated
show-empty />

<p class="title is-size-5">displaying</p>
<RadioSelect
v-model="form.framing"
:options="framing"
separated
show-empty />

<p class="title is-size-5">having</p>
<RadioSelect
v-model="form.having"
:options="accessories"
separated
show-empty />

<p class="title is-size-5">wearing</p>
<RadioSelect
v-model="form.wearing"
:options="clothes"
separated
show-empty />

<p class="title is-size-5">in light</p>
<RadioSelect
v-model="form.lighting"
:options="lights"
separated
show-empty />

<p class="title is-size-5">art inspired by</p>
<RadioSelect
v-model="form.inspiredBy"
:options="inspirations"
separated
show-empty />

<SubmitButton
icon="plus"
label="generate"
:loading="isLoading"
expanded
@click="submit" />
</section>
</template>

<script setup lang="ts">
import { PredictionStatus, getPrediction, predict } from '@/services/replicate'
import { logPrediction } from '@/services/supabase'
import { emptyObject } from '@/utils/empty'
import {
accessories,
art,
clothes,
filmTypes,
framing,
gender,
inspirations,
lights,
styles,
} from './options'
import { Options, buildPrompt } from './promptBuilder'

const Loader = defineAsyncComponent(
() => import('@/components/shared/Loader.vue')
)
// const BasicInput = defineAsyncComponent(
// () => import('@/components/shared/form/BasicInput.vue')
// )
const SubmitButton = defineAsyncComponent(
() => import('@/components/base/SubmitButton.vue')
)

const RadioSelect = defineAsyncComponent(
() => import('@/components/shared/input/selectable/RadioSelect.vue')
)

const form = reactive<Options>({
gender: 'waifu',
art: 'painting',
vibe: '',
framing: 'close-up',
filmType: '',
style: '',
inspiredBy: '',
having: '',
wearing: '',
lighting: '',
})

const isLoading = ref(false)
const status = ref('')
const predictionId = ref('')
const predicion = ref<PredictionStatus>(emptyObject<PredictionStatus>())
const emit = defineEmits(['select', 'submit'])
const isPhoto = computed(() => form.art === 'photo')

// change form.style when form.art changes
watch(isPhoto, () => (form.style = ''))

const submit = async () => {
isLoading.value = true
status.value = 'predicting'
const prompt = buildPrompt(form)
console.log('prompt', prompt)
const predictRequest = await predict(prompt)
emit('submit', form)

const timeout = setInterval(async () => {
const generation = await getPrediction(predictRequest.id)
console.log('status', status)
predicion.value = generation
status.value = 'loader.generative.' + generation.status
if (generation.status === 'failed' || generation.status === 'succeeded') {
isLoading.value = false
status.value = ''
clearInterval(timeout)
if (generation.status === 'succeeded') {
emit('select', generation)
logPrediction(predictRequest.id, prompt).catch(console.error)
}
}
}, 2500)

predictionId.value = predictRequest.id
}
</script>
Loading