initial commit

This commit is contained in:
silva guimaraes 2025-04-21 17:59:57 -03:00
commit c21f569144
37 changed files with 3956 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,78 @@
@import "tailwindcss";
/* não deve ser o jeito certo de fazer isso. */
.primary_button {
@apply rounded p-2 bg-indigo-500;
}
.my-input {
@apply w-full bg-transparent placeholder:text-slate-400 text-slate-700 text-sm border border-slate-200 rounded-md px-3 py-2 transition duration-300 focus:outline-none focus:border-slate-400 hover:border-slate-300 shadow-sm focus:shadow;
}
.my-label {
@apply block mb-1 text-sm text-slate-600;
}
.however {
@apply flex items-center mt-2 text-xs text-slate-400;
}
.my-my-input {
@apply w-full min-w-[200px] mb-5;
}
.btn {
@apply w-full rounded-md bg-slate-800 py-2 px-4 my-4 border border-transparent text-center text-sm text-white transition-all shadow-md hover:shadow-lg focus:bg-slate-700 focus:shadow-none active:bg-slate-700 hover:bg-slate-700 active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none;
}
h1 {
@apply text-5xl font-bold mb-5
}
h2 {
@apply text-4xl font-bold mb-5
}
@keyframes bounce {
0% {
transform: translateX(-7px);
timing-function: ease-in;
}
37% {
transform: translateX(7px);
timing-function: ease-out;
}
55% {
transform: translateX(-7px);
timing-function: ease-in;
}
73% {
transform: translateX(5px);
timing-function: ease-out;
}
82% {
transform: translateX(-5px);
timing-function: ease-in;
}
91% {
transform: translateX(2px);
timing-function: ease-out;
}
96% {
transform: translateX(-2px);
timing-function: ease-in;
}
100% {
transform: translateX(0px);
timing-function: ease-in;
}
}
.bounce {
animation-name: bounce;
animation-duration: .5s;
}

View file

@ -0,0 +1,74 @@
# **This box URL belongs to no one.**
**Drop a file** with the `Edit code` field of your choice **to claim this URL as yours**.
So as long as you **keep your edit code**, you will be able to make permissive moditifications to this box,
including visualizing files, moderation and exclusion of files.
**To make modifications to this readme section, drop a file called `README.md`** that will override the
currently set header. This is how you're supposed to make edits to this section.
New boxes have been set to have a **maximum lifetime of two years,** after the lifetime period is over,
the box files are going to be deleted and the URL is going to be reclaimed. You'll no longer own this URL.
Once you've claimed this box, you'll be able to **drop a `config.json5`** with valid [`json5`](https://json5.org/) options
**to replace the default box configuration.** [The default configuration file can be found
here](/box-configurations#) along with all customizeble options.
## FAQ
### Can I set a maximum upload size?
Works is in progress. You won't be able to set it above the maximum size set be this instance administrator
### Is there a views counter?
Works is in progress. There will be one.
### Can I block others from viewing the box contents?
Works is in progress. You will be able to.
### What filetypes are allowed? Can I black/white list filetypes?
Per the default configuration, all filetypes are allowed. but works are in progress. You will be able to
white or blacklist filetypes.
### How can I see the IP addresses of the file uploaders
You cannot and there is no configuration you or the instance administrator can set that will allow you
to see address of the uploaders because the servers don't collect them in the first place.
Let it be known that the instance administrator can still set the server to run behind a reverse proxy
which would allow him or her to collect data from the client accesses, but even still,
this is not something the instance has access to and therefore you won't either.
### Is the instance adminstrator able to view the contents of this box
Yes they are. Whether you trust the instance adminsitrator with these files is up to you.
### What can't be uploaded to these boxes?
This is up to the instance administrator to define. See [Uploading guidelines](/uploading-guidelines#).
### What happens if the instance administrator changes the max lifetime of a box or the maximum upload size?
If the max lifetime is changed your newly created box won't be affected and your lifetime will still be the same from when the
box was created. If the instance administrator changes te maximum upload size, your configurations will be capped to
conform to those changes. Make sure your configurations are up to date by downloading the `config.json5` from this box at
every periodic change.
### Making changes to these files is hard on a mobile UwU, why can't I edit the configurations with a form?
Not our problem. Get a computer.
### Why json5?
YAML sucks. TOML sucks. JSON sucks. JSON5 sucks less. [Here's what it looks like](https://github.com/chromium/chromium/blob/feb3c9f670515edf9a88f185301cbd7794ee3e52/third_party/blink/renderer/platform/runtime_enabled_features.json5).
Lua is an option and it actually rocks but that's a bit overkill for this project.
### What happens if I lose my edit code?
It's totally up to you to not do that.
<script>alert("if this is executed it means we screwed up")</script>

256
views/template.templ Normal file
View file

@ -0,0 +1,256 @@
package views
import (
"foobar/database"
"foobar/model"
"fmt"
"time"
)
templ indexLayout() {
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<title>Mude meu título!</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="htmx-config" content='{ "responseHandling":[{"code":"422", "swap": true}, {"code":"200", "swap": true}] }' />
<!-- tailwind -->
<link href="/static/css/output.css" rel="stylesheet"/>
<!-- markdown styling -->
<link href="/static/css/github-markdown.css" rel="stylesheet"/>
<!-- daisyUI -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
<!-- daisyUI Themes -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
// <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- HTMX -->
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<!-- Hyperscript -->
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script>
<style>
html, body {
min-height: 100vh;
}
</style>
</head>
<body class="flex-wrap flex content-center justify-between flex-col bg-base-100 text-sm"
hx-boost="true" hx-push-url="true" hx-target="this">
{ children... }
<footer></footer>
</body>
</html>
}
templ mainCenterBody() {
@indexLayout() {
<main class="w-full" >
{ children... }
</main>
}
}
const toggleButtonInMeUntilLoad =
`on every htmx:beforeSend
tell <button/> in me
toggle [@disabled='true'] until htmx:afterOnLoad
end
end`
func safeURL(s string) string {
return fmt.Sprint(templ.SafeURL(s))
}
templ Index() {
@mainCenterBody() {
<div class="hero-content">
<div class="max-w-md text-center">
<h1>hakobox</h1>
<p>nothing here...</p>
</div>
</div>
}
}
templ boxUploadSidebar(boxURL model.BoxURL) {
@mainCenterBody() {
<div class="">
<section class="static md:fixed top-0 left-0 z-10 w-full md:w-3/9 p-10 bg-base-200 h-full ">
<header>
<h1>hakobox</h1>
<p>It's temporary file sharing but everyone gets to contribute! </p>
<p class="leading-tight font-medium text-black">Drop in a file to be added to this box </p>
</header>
<form id="add-file"
hx-trigger="submit"
hx-post={safeURL(fmt.Sprintf("/box/%s", boxURL))}
hx-encoding="multipart/form-data">
<fieldset class="fieldset">
<legend class="fieldset-legend">Pick a file</legend>
<input name="file" type="file" class="file-input" style="width: 100%;" multiple required/>
<label class="fieldset-label">Max size 2MB</label>
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Edit code</legend>
<input type="text" class="input" name="edit_code" placeholder="Type here" style="width: 100%;"/>
<p class="label">Optional</p>
</fieldset>
@errorTarget()
<button type="submit" class="btn btn-primary mb-5">Add to the box!</button>
<div class="text-center">
<a class="link link-primary block mb-0"
href={templ.SafeURL(fmt.Sprintf("/box/%s/inside", boxURL))}>
See what's inside
</a>
<a class="link link-primary block mb-0"
href={templ.SafeURL(fmt.Sprintf("/box/%s", boxURL))}>
Front page
</a>
</div>
</form>
</section>
<section class="md:px-20 p-4 md:my-40 m-0 md:ml-auto md:max-w-6/9">
{ children... }
</section>
</div>
}
}
templ BoxUpload(box model.Box) {
@boxUploadSidebar(box.Url()) {
<div class="markdown-body">
@templ.Raw(box.Header())
</div>
}
}
templ NewBox(boxURL model.BoxURL, templateReadme model.Markdown) {
@boxUploadSidebar(boxURL) {
<div class="markdown-body">
@templ.Raw(templateReadme)
</div>
}
}
templ Box(boxURL model.BoxURL, files []model.File) {
@boxUploadSidebar(boxURL) {
<main class="inline-flex flex-wrap gap-0 md:gap-5 mt-20 w-full h-full justify-start md:justify-center">
if len(files) == 0 {
<h2 class="m-auto">Empty box.</h2>
} else {
for i := range files {
@fileCard(files[i])
}
}
</main>
}
}
func fileDisplay(file model.File) templ.Component {
switch {
case file.Mime().IsImage():
return fileImageFigure(file)
case file.Mime().IsVideo():
return fileVideoFigure(file)
default:
return unknownFileFigure()
// panic(fmt.Errorf("unrecognized mime: %s", file.Mime))
}
}
templ fileCard(file model.File) {
<a class="card w-1/2 md:w-2xs aspect-square mb-10" href={templ.SafeURL(fmt.Sprintf("/static/box/%s", file.ID()))} target="_blank">
<figure class="flex flex-col p-1 m-auto mb-auto md:mb-0 text-center">
@fileDisplay(file)
</figure>
<div class="hidden md:inline font-light text-sm" style="text-wrap: nowrap;">
<p title={file.Name()}>{shorten(file.Name())}</p>
<p title={file.Name()}>{file.CreatedAt().Format(time.DateOnly)}</p>
<p>{formatSize(file.Size())} {file.Mime().PrettyType()}</p>
</div>
</a>
}
templ fileImageFigure(file model.File) {
<img
title={file.Name()}
loading="lazy"
src={fmt.Sprintf("/static/box/%s", file.ID())}
alt={file.Name()} />
}
templ fileVideoFigure(file model.File) {
<video title={file.Name()} loading="lazy" alt={file.Name()} >
<source src={fmt.Sprintf("/static/box/%s", file.ID())}/>
</video>
}
templ unknownFileFigure() {
<div>unknown format!</div>
}
func shorten(text string) string {
if len(text) > 41 {
return fmt.Sprintf("%s...", text[:41-3])
} else {
return text
}
}
func formatSize(size int64) string {
units := []string{"b", "Kb", "Mb", "Gb"}
i := 0
fSize := float64(size)
for fSize >= 1000 && i < len(units)-1 {
fSize /= 1000
i++
}
return fmt.Sprintf("%.2f %s", fSize, units[i])
}
templ FourOfour() {
@indexLayout() {
<div>404</div>
}
}
templ Logged(usuario *database.Usuario) {
@indexLayout() {
<p>Logado como: { usuario.Nome }</p>
<div style="text-align: center;">
<p>
<a href="/">index</a>
</p>
<p>
<a href="/logout">logout</a>
</p>
</div>
}
}
templ errorTarget() {
<div id="error-target">
</div>
}
templ ErrorBox(msg string) {
<div role="alert" class="bounce mt-3 relative flex flex-col w-full p-3 text-sm text-white bg-red-600 rounded-md">
<p class="flex text-base">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="h-5 w-5 mr-2 mt-0.5"><path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"></path></svg>
Error
</p>
<p class="ml-4 p-3">
{ msg }
</p>
<button class="flex items-center justify-center transition-all w-8 h-8 rounded-md text-white hover:bg-white/10 active:bg-white/10 absolute top-1.5 right-1.5" type="button"
_='on click tell closest <div[role="alert"]/> transition opacity to 0 then remove yourself end'
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-5 w-5" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg>
</button>
</div>
}