Skip to content

Commit 5a6ba0c

Browse files
committed
feat: create a first version
1 parent 436fd4f commit 5a6ba0c

File tree

10 files changed

+293
-0
lines changed

10 files changed

+293
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Pixely-Sort-&-Save.xpi
2+
Pixely-Sort-&-Save.zip

README.md

Whitespace-only changes.

background.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
function generateRandomName(length = 10) {
2+
const chars =
3+
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
4+
return Array.from(
5+
{ length },
6+
() => chars[Math.floor(Math.random() * chars.length)]
7+
).join("");
8+
}
9+
10+
function getFileExtension(url) {
11+
const match = url.match(/\.(\w+)(?=($|\?|#))/);
12+
return match ? match[1] : "jpg";
13+
}
14+
15+
function createContextMenus(suffixes) {
16+
browser.contextMenus.removeAll().then(() => {
17+
browser.contextMenus.create({
18+
id: "quick-save-parent",
19+
title: "Salvar imagem (aleatório)",
20+
contexts: ["image"],
21+
});
22+
23+
suffixes.forEach((suffix) => {
24+
browser.contextMenus.create({
25+
id: `quick-save-${suffix}`,
26+
parentId: "quick-save-parent",
27+
title: suffix,
28+
contexts: ["image"],
29+
});
30+
});
31+
});
32+
}
33+
34+
browser.runtime.onInstalled.addListener(() => {
35+
browser.storage.local
36+
.get({ suffixes: ["picture", "wallpapers", "uncategorized", "direct"] })
37+
.then((data) => createContextMenus(data.suffixes));
38+
});
39+
40+
browser.runtime.onStartup.addListener(() => {
41+
browser.storage.local
42+
.get({ suffixes: ["picture", "wallpapers", "uncategorized", "direct"] })
43+
.then((data) => createContextMenus(data.suffixes));
44+
});
45+
46+
browser.storage.onChanged.addListener((changes) => {
47+
if (changes.suffixes) {
48+
createContextMenus(changes.suffixes.newValue);
49+
}
50+
});
51+
52+
browser.contextMenus.onClicked.addListener((info) => {
53+
const clickedId = info.menuItemId;
54+
if (clickedId.startsWith("quick-save-")) {
55+
const suffix = clickedId.replace("quick-save-", "");
56+
57+
const url = info.srcUrl;
58+
const ext = getFileExtension(url);
59+
60+
if (!url) {
61+
console.error("URL not found");
62+
return;
63+
}
64+
65+
let filename;
66+
67+
if (suffix == "direct") {
68+
filename = `images/${generateRandomName(10)}.${ext}`;
69+
} else {
70+
filename = `images/${suffix}/${generateRandomName(10)}.${ext}`;
71+
}
72+
73+
browser.downloads.download({
74+
url: url,
75+
filename: filename,
76+
conflictAction: "uniquify",
77+
saveAs: false,
78+
});
79+
}
80+
});

compactar_extensao.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/bin/bash
2+
3+
EXTENSION_NAME="Pixely-Sort-&-Save"
4+
FILES_TO_INCLUDE="."
5+
EXCLUDE_LIST=(
6+
"--exclude=compactar_extensao.sh"
7+
"--exclude=${EXTENSION_NAME}.xpi"
8+
"--exclude=README.md"
9+
"--exclude=LICENSE"
10+
"--exclude=screenshot/*"
11+
"--exclude=.git/*"
12+
"--exclude=.gitignore"
13+
"--exclude=*.zip"
14+
)
15+
16+
EXCLUDE_CMD="${EXCLUDE_LIST[*]}"
17+
18+
echo "--- Removendo versões anteriores ---"
19+
20+
if [ -f "${EXTENSION_NAME}.xpi" ]; then
21+
echo "Removendo .xpi anterior: ${EXTENSION_NAME}.xpi"
22+
rm "${EXTENSION_NAME}.xpi"
23+
fi
24+
25+
if [ -f "${EXTENSION_NAME}.zip" ]; then
26+
echo "Removendo .zip anterior: ${EXTENSION_NAME}.zip"
27+
rm "${EXTENSION_NAME}.zip"
28+
fi
29+
30+
echo ""
31+
32+
echo "--- Criando arquivo .xpi ---"
33+
echo "Criando arquivo compactado: ${EXTENSION_NAME}.xpi"
34+
zip -q -r "${EXTENSION_NAME}.xpi" ${FILES_TO_INCLUDE} ${EXCLUDE_CMD}
35+
echo ".xpi criado com sucesso!"
36+
echo ""
37+
38+
echo "--- Criando arquivo .zip ---"
39+
echo "Criando arquivo compactado: ${EXTENSION_NAME}.zip"
40+
zip -q -r "${EXTENSION_NAME}.zip" ${FILES_TO_INCLUDE} ${EXCLUDE_CMD}
41+
echo ".zip criado com sucesso!"
42+
echo ""
43+
44+
echo "--- Todas as tarefas de compactação concluídas! ---"

icons/icon.png

57.8 KB
Loading

manifest.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"manifest_version": 2,
3+
"name": "Pixely Sort & Save",
4+
"version": "1.2",
5+
"description": "Salva imagens rapidamente em subpastas com nome aleatório.",
6+
"permissions": [
7+
"downloads",
8+
"contextMenus",
9+
"storage",
10+
"<all_urls>"
11+
],
12+
"background": {
13+
"scripts": [
14+
"background.js"
15+
],
16+
"persistent": false
17+
},
18+
"options_ui": {
19+
"page": "options.html",
20+
"open_in_tab": false
21+
},
22+
"icons": {
23+
"48": "icons/icon.png"
24+
}
25+
}

options.html

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Configurações - Quick Image Saver</title>
6+
<style>
7+
:root {
8+
--purple-primary: #8a2be2;
9+
--purple-light: #9945e8;
10+
--dark: #1a1a1a;
11+
--gray-light: #f5f5f5;
12+
}
13+
14+
body {
15+
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
16+
background-color: var(--dark);
17+
color: var(--gray-light);
18+
margin: 0;
19+
padding: 2rem;
20+
min-height: 100vh;
21+
}
22+
23+
h1 {
24+
color: var(--purple-primary);
25+
font-size: 2rem;
26+
margin-bottom: 2rem;
27+
border-bottom: 2px solid var(--purple-primary);
28+
padding-bottom: 0.5rem;
29+
}
30+
31+
input {
32+
background-color: #2a2a2a;
33+
border: 2px solid var(--purple-primary);
34+
color: white;
35+
padding: 8px 12px;
36+
border-radius: 4px;
37+
font-size: 1rem;
38+
transition: all 0.3s ease;
39+
}
40+
41+
input:focus {
42+
outline: none;
43+
border-color: var(--purple-light);
44+
box-shadow: 0 0 5px var(--purple-light);
45+
}
46+
47+
button {
48+
background-color: var(--purple-primary);
49+
color: white;
50+
border: none;
51+
padding: 8px 16px;
52+
border-radius: 4px;
53+
cursor: pointer;
54+
font-size: 1rem;
55+
transition: all 0.3s ease;
56+
}
57+
58+
button:hover {
59+
background-color: var(--purple-light);
60+
transform: translateY(-1px);
61+
}
62+
63+
ul {
64+
list-style: none;
65+
padding: 0;
66+
margin-top: 2rem;
67+
}
68+
69+
li {
70+
display: flex;
71+
justify-content: space-between;
72+
align-items: center;
73+
background-color: #2a2a2a;
74+
margin-bottom: 0.8rem;
75+
padding: 12px 16px;
76+
border-radius: 4px;
77+
border-left: 4px solid var(--purple-primary);
78+
transition: all 0.3s ease;
79+
}
80+
81+
li:hover {
82+
background-color: #333;
83+
transform: translateX(5px);
84+
}
85+
86+
li button {
87+
background-color: #ff4444;
88+
}
89+
90+
li button:hover {
91+
background-color: #ff6666;
92+
}
93+
</style>
94+
</head>
95+
<body>
96+
<h1>Configurar Subpastas</h1>
97+
<input id="new-suffix" type="text" placeholder="Nome da subpasta" />
98+
<button id="add-suffix">Adicionar</button>
99+
<ul id="suffix-list"></ul>
100+
<script src="options.js"></script>
101+
</body>
102+
</html>

options.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const suffixList = document.getElementById("suffix-list");
2+
const addButton = document.getElementById("add-suffix");
3+
const newSuffixInput = document.getElementById("new-suffix");
4+
5+
function renderList(suffixes) {
6+
suffixList.innerHTML = "";
7+
suffixes.forEach((suffix, index) => {
8+
const li = document.createElement("li");
9+
li.textContent = suffix;
10+
11+
if (suffix !== "direct") {
12+
const removeButton = document.createElement("button");
13+
removeButton.textContent = "Remover";
14+
removeButton.addEventListener("click", () => {
15+
suffixes.splice(index, 1);
16+
browser.storage.local.set({ suffixes });
17+
renderList(suffixes);
18+
});
19+
20+
li.appendChild(removeButton);
21+
}
22+
suffixList.appendChild(li);
23+
});
24+
}
25+
26+
browser.storage.local
27+
.get({ suffixes: ["picture", "wallpapers", "uncategorized", "direct"] })
28+
.then((data) => {
29+
renderList(data.suffixes);
30+
31+
addButton.addEventListener("click", () => {
32+
const newSuffix = newSuffixInput.value.trim();
33+
if (newSuffix && !data.suffixes.includes(newSuffix)) {
34+
data.suffixes.push(newSuffix);
35+
browser.storage.local.set({ suffixes: data.suffixes });
36+
newSuffixInput.value = "";
37+
renderList(data.suffixes);
38+
}
39+
});
40+
});

screenshot/example.jpg

98.9 KB
Loading

screenshot/options.jpg

35 KB
Loading

0 commit comments

Comments
 (0)