{"version":3,"file":"music-3RpwnBIV.js","sources":["../../../ui/src/stores/project-store.ts","../../../ui/src/utilities/confetti.ts"],"sourcesContent":["import { defineStore } from 'pinia';\nimport { useUserStore } from '~/stores/user-store';\nimport pyscriptApi from '~/utilities/pyscript-api';\nimport type { Project, Version } from '~/utilities/pyscript-api-models';\n\nconst userStore = useUserStore();\n\ninterface State {\n  project: Project | null;\n  versions: Version[];\n}\n\n/**\n * Stores the current project being edited or viewed, as well as its versions.\n */\nexport const useProjectStore = defineStore('project', {\n  state: (): State => ({\n    project: null,\n    versions: [],\n  }),\n\n  getters: {\n    /**\n     * Determine if the current user is the owner of the project.\n     */\n    isProjectOwner(state) {\n      if (userStore.isLoggedIn === false || state.project === null) {\n        return false;\n      }\n\n      return (\n        state.project.user_id === userStore.user?.id ||\n        state.project.username === userStore.user?.username\n      );\n    },\n  },\n\n  actions: {\n    /**\n     * Fetch a project by its slug or id.\n     */\n    async fetchProjectAndVersions(usernameOrUserId: string, projectSlugOrId: string) {\n      const uuidPattern =\n        /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;\n\n      if (uuidPattern.test(projectSlugOrId)) {\n        this.project = await pyscriptApi.getProject(projectSlugOrId);\n      } else {\n        this.project = await pyscriptApi.getProjectBySlug(usernameOrUserId, projectSlugOrId);\n      }\n\n      await this.fetchVersions(this.project.id);\n    },\n\n    /**\n     * Fetch a project's versions.\n     */\n    async fetchVersions(projectId: string) {\n      const versions = await pyscriptApi.listVersions(projectId);\n      this.versions = versions.sort((a, b) => {\n        if (a.version !== 'latest' && b.version === 'latest') return 1;\n        if (a.version === 'latest' && b.version !== 'latest') return -1;\n        return Date.parse(b.created_at) - Date.parse(a.created_at);\n      });\n    },\n  },\n});\n","/**\n * After reviewing many confetti animations, the best one was a vanilla JS\n * script that was created in 2019. It's a bit outdated, and could definitely\n * use some work. I haven't touched much of it other than removing the IIFE,\n * turning it into a TS module, and all vars were converted to let and const.\n * @see https://www.cssscript.com/confetti-falling-animation/\n *\n * The goal was to make something similar to Github's confetti falling that\n * appears when signing up for GitHub Copilot.\n * @see https://github.com/github-copilot/signup/success\n */\nexport function confetti() {\n  const maxParticleCount = 150; // set max confetti count\n  const particleSpeed = 2; // set the particle animation speed\n  const startConfetti = startConfettiInner; // call to start confetti animation\n  const stopConfetti = stopConfettiInner; // call to stop adding confetti\n  const toggleConfetti = toggleConfettiInner; // call to start or stop the confetti animation depending on whether it's already running\n  const removeConfetti = removeConfettiInner; // call to stop the confetti animation and remove all confetti immediately\n  const colors = [\n    'DodgerBlue',\n    'OliveDrab',\n    'Gold',\n    'Pink',\n    'SlateBlue',\n    'LightBlue',\n    'Violet',\n    'PaleGreen',\n    'SteelBlue',\n    'SandyBrown',\n    'Chocolate',\n    'Crimson',\n  ];\n  let streamingConfetti = false;\n  let animationTimer = null;\n  let particles = [];\n  let waveAngle = 0;\n\n  function resetParticle(particle, width, height) {\n    particle.color = colors[(Math.random() * colors.length) | 0];\n    particle.x = Math.random() * width;\n    particle.y = Math.random() * height - height;\n    particle.diameter = Math.random() * 10 + 5;\n    particle.tilt = Math.random() * 10 - 10;\n    particle.tiltAngleIncrement = Math.random() * 0.07 + 0.05;\n    particle.tiltAngle = 0;\n    return particle;\n  }\n\n  function startConfettiInner() {\n    const width = window.innerWidth;\n    const height = window.innerHeight;\n    window.requestAnimFrame = (function () {\n      return (\n        window.requestAnimationFrame ||\n        window.webkitRequestAnimationFrame ||\n        window.mozRequestAnimationFrame ||\n        window.oRequestAnimationFrame ||\n        window.msRequestAnimationFrame ||\n        function (callback) {\n          return window.setTimeout(callback, 16.6666667);\n        }\n      );\n    })();\n    let canvas = document.getElementById('confetti-canvas');\n    if (canvas === null) {\n      canvas = document.createElement('canvas');\n      canvas.setAttribute('id', 'confetti-canvas');\n      canvas.setAttribute(\n        'style',\n        'display:block;z-index:999999;pointer-events:none;position:fixed;top:0;right:0;bottom:0;left:0;',\n      );\n      document.body.appendChild(canvas);\n      canvas.width = width;\n      canvas.height = height;\n      window.addEventListener(\n        'resize',\n        function () {\n          canvas.width = window.innerWidth;\n          canvas.height = window.innerHeight;\n        },\n        true,\n      );\n    }\n    const context = canvas.getContext('2d');\n    while (particles.length < maxParticleCount) particles.push(resetParticle({}, width, height));\n    streamingConfetti = true;\n    if (animationTimer === null) {\n      (function runAnimation() {\n        context.clearRect(0, 0, window.innerWidth, window.innerHeight);\n        if (particles.length === 0) animationTimer = null;\n        else {\n          updateParticles();\n          drawParticles(context);\n          animationTimer = requestAnimFrame(runAnimation);\n        }\n      })();\n    }\n  }\n\n  function stopConfettiInner() {\n    streamingConfetti = false;\n  }\n\n  function removeConfettiInner() {\n    stopConfetti();\n    particles = [];\n  }\n\n  function toggleConfettiInner() {\n    if (streamingConfetti) stopConfettiInner();\n    else startConfettiInner();\n  }\n\n  function drawParticles(context) {\n    let particle;\n    let x;\n    for (let i = 0; i < particles.length; i++) {\n      particle = particles[i];\n      context.beginPath();\n      context.lineWidth = particle.diameter;\n      context.strokeStyle = particle.color;\n      x = particle.x + particle.tilt;\n      context.moveTo(x + particle.diameter / 2, particle.y);\n      context.lineTo(x, particle.y + particle.tilt + particle.diameter / 2);\n      context.stroke();\n    }\n  }\n\n  function updateParticles() {\n    const width = window.innerWidth;\n    const height = window.innerHeight;\n    let particle;\n    waveAngle += 0.01;\n    for (let i = 0; i < particles.length; i++) {\n      particle = particles[i];\n      if (!streamingConfetti && particle.y < -15) particle.y = height + 100;\n      else {\n        particle.tiltAngle += particle.tiltAngleIncrement;\n        particle.x += Math.sin(waveAngle);\n        particle.y += (Math.cos(waveAngle) + particle.diameter + particleSpeed) * 0.5;\n        particle.tilt = Math.sin(particle.tiltAngle) * 15;\n      }\n      if (particle.x > width + 20 || particle.x < -20 || particle.y > height) {\n        if (streamingConfetti && particles.length <= maxParticleCount)\n          resetParticle(particle, width, height);\n        else {\n          particles.splice(i, 1);\n          i--;\n        }\n      }\n    }\n  }\n\n  return {\n    startConfetti,\n    stopConfetti,\n    toggleConfetti,\n    removeConfetti,\n  };\n}\n"],"names":["userStore","useUserStore","useProjectStore","defineStore","state","_a","_b","usernameOrUserId","projectSlugOrId","pyscriptApi","projectId","versions","b","confetti","startConfetti","startConfettiInner","stopConfetti","stopConfettiInner","toggleConfetti","toggleConfettiInner","removeConfetti","removeConfettiInner","colors","streamingConfetti","animationTimer","particles","waveAngle","resetParticle","particle","width","height","callback","canvas","context","runAnimation","updateParticles","drawParticles","x"],"mappings":"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"}