all repos — artbound-python @ 403441d201bf5ec950197d9eee84d46bea92dd0f

A client-server reimplementation of the administration panel for ArtBound.

artbound_python/static/script.js (view raw)

  1const BS_COL_WIDTH = 4,
  2	MAX_WIDTH = MAX_HEIGHT = 1000,
  3	WATERMARK_SRC = "/static/res/wm.png",
  4	WATERMARK_WIDTH = 325,
  5	WATERMARK_HEIGHT = 98,
  6	IG_TEMPLATE_SRC = "/static/res/ig.png",
  7	IG_MIN_OFFSET_X = 0,
  8	IG_MIN_OFFSET_Y = 342,
  9	IG_MAX_WIDTH = 1080,
 10	IG_MAX_HEIGHT = 988,
 11	
 12	WATERMARK = new Image(),
 13	IG_TEMPLATE = new Image(),
 14	date = new Date(),
 15	month_input = document.getElementById("month_input"),
 16	month_div = document.getElementById("month_div"),
 17	get_button = document.getElementById("get_button"),
 18	selectall_button = document.getElementById("selectall_button"),
 19	selectnone_button = document.getElementById("selectnone_button"),
 20	togglecolor_button = document.getElementById("togglecolor_button"),
 21	controls_div = document.getElementById("controls"),
 22	opacity_range = document.getElementById("opacity_range"),
 23	main_container_div = document.getElementById("main_container"),
 24	content_div = document.getElementById("content"),
 25	canvas_link = document.getElementById("canvas-download"),
 26	canvas_ig = document.getElementById("instagram-canvas");
 27
 28let	fanarts = new Array(),
 29	watermark_invert = '';
 30
 31WATERMARK.src = WATERMARK_SRC;
 32IG_TEMPLATE.src = IG_TEMPLATE_SRC;
 33month_input.value = `${date.getFullYear()}-${("0" + (date.getMonth() + 1)).slice(-2)}`;
 34
 35function addCanvasEvents(img, canvas, ctx){
 36	function abc(e) {
 37		if (e.button == 0) addWatermark(e, img, canvas, ctx);
 38	}
 39
 40	canvas.addEventListener('mousemove', abc);
 41	canvas.addEventListener('mousedown', function(e) {
 42		canvas.removeEventListener('mousemove', abc);
 43		canvas.addEventListener('mousedown', abc);
 44	});
 45}
 46
 47function getNewCardHtml(element) {
 48	element.div = document.createElement("div");
 49	element.canvas = document.createElement("canvas");
 50	const div1 = document.createElement("div"),
 51		div2 = document.createElement("div"),
 52		a = document.createElement("a"),
 53		div3 = document.createElement("div"),
 54		div4 = document.createElement("div"),
 55		button1 = document.createElement("button"),
 56		button2 = document.createElement("button"),
 57		button3 = document.createElement("button"),
 58		button4 = document.createElement("button"),
 59		button5 = document.createElement("button"),
 60		button6 = document.createElement("button"),
 61		filename = `${('0' + element.index).slice(-2)} - ${element.name}.png`;
 62	
 63	element.div.className = `col-md-${BS_COL_WIDTH} entry${element.enabled == 0 ? " entry-disabled" : ""}`;
 64	element.div.id = `div-${element.id}`;
 65	element.div.setAttribute("data-index", element.index);
 66	div1.className = `card mb-${BS_COL_WIDTH} box-shadow my-card`;
 67	element.canvas.className = "card-img-top entry-img";
 68	element.canvas.id = element.id;
 69	element.canvas.setAttribute("data-name", element.name);
 70	element.canvas.setAttribute("data-content", element.content);
 71	element.canvas.setAttribute("data-filename", filename)
 72	div2.className = "card-body";
 73	a.className = "card-text";
 74	a.innerText = filename;
 75	a.title = "Clicca per copiare."
 76	a.addEventListener("click", function() { navigator.clipboard.writeText(a.innerText); }, false)
 77	div3.className = "d-flex justify-content-between align-items-center card-controls";
 78	div4.className = "btn-group";
 79
 80	button1.className = button2.className = button3.className = button4.className = button5.className = button6.className = "btn btn-sm btn-outline-secondary";
 81	button1.innerText = "⬅️";
 82	button2.innerText = "*️⃣";
 83	button3.innerText = "🔄";
 84	button4.innerText = "💾";
 85	button5.innerText = "📷";
 86	button6.innerText = "➡️";
 87	button1.addEventListener("click", function() { moveUpDown(element.id, -1); }, false);
 88	button2.addEventListener("click", function() { toggleEntry(element.id); }, false);
 89	button3.addEventListener("click", function() { reloadEntry(element.id); }, false);
 90	button4.addEventListener("click", function() { saveEntry(element.id); }, false);
 91	button5.addEventListener("click", function() { saveEntryIG(element.id); }, false);
 92	button6.addEventListener("click", function() { moveUpDown(element.id, 1); }, false);
 93
 94	div4.appendChild(button1);
 95	div4.appendChild(button2);
 96	//div4.appendChild(button3);
 97	div4.appendChild(button4);
 98	div4.appendChild(button5);
 99	div4.appendChild(button6);
100	div3.appendChild(div4);
101	div2.appendChild(a);
102	div2.appendChild(div3);
103	div1.appendChild(element.canvas);
104	div1.appendChild(div2);
105	element.div.appendChild(div1);
106
107	const ctx = element.canvas.getContext("2d");
108
109	element.image = new Image();
110	element.image.addEventListener("load", () => {
111		setBaseImage(element.image, element.canvas, ctx);
112		addCanvasEvents(element.image, element.canvas, ctx);
113	});
114	element.image.src = element.content;
115
116	return element.div;
117}
118
119async function updateFanartList() {
120	main_container_div.hidden = false;
121	content_div.innerHTML = "";
122	get_button.disabled = false;
123	get_button.innerText = "Aggiungi";
124	
125	let i = 0;
126	for (fanart of fanarts) {
127		if(fanart.enabled){
128			i++;
129			fanart.index = i;
130			content_div.appendChild(getNewCardHtml(fanart));
131		}
132	}
133
134	for (fanart of fanarts) {
135		if(!fanart.enabled){
136			fanart.index = 0;
137			content_div.appendChild(getNewCardHtml(fanart));
138		}
139	}
140}
141
142function getFanart(id){
143	return fanarts.find(element => element.id == id)
144}
145
146function toggleEntry(id) {
147	entry = getFanart(id);
148	if (!entry) return;
149
150	entry.enabled = !entry.enabled;
151	updateFanartList()
152}
153
154function saveCanvas(my_canvas, filename) {
155	canvas_link.href = my_canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
156	canvas_link.setAttribute("download", filename);
157	canvas_link.click()
158}
159
160function reloadEntry(id){
161	const fanart = getFanart(id);
162	if (!fanart) return;
163
164	const old_div = fanart.div;
165	content_div.replaceChild(getNewCardHtml(fanart), old_div);
166	old_div.remove();
167}
168
169function selectAllNone(toggle) {
170	fanarts.map(x => x.enabled = toggle)
171	updateFanartList()
172}
173
174function debugFn(){
175	fanarts = JSON.parse('[{"id":"1dE8L7w2DuOfQSJwf5oRjAeJ-VZfy5o-6","date":["03","08","2022"],"name":"Saro","content":"/static/res/wm.png","enabled":1,"index":1,"div":{}},{"id":"1ZO2poqaylmh7_FkEjRthozVXFpcP1Edx","date":["18","08","2022"],"name":"suchetto","content":"https://drive.google.com/uc?id=1ZO2poqaylmh7_FkEjRthozVXFpcP1Edx","enabled":1,"index":2,"div":{}},{"id":"1jkpZzqnQUdXv7QiW1khuwnSsdnjudBt-","date":["18","08","2022"],"name":"suca","content":"https://drive.google.com/uc?id=1clZbi1QzJQo_c7PGWx-nmLgfPhXqHdZR","enabled":1,"index":3,"div":{}}]');
176	controls_div.hidden = false;
177	updateOpacity();
178	updateFanartList();
179}
180
181function toggleColor() {
182	watermark_invert = watermark_invert == '' ? 'invert(1)' : '';
183	updateColorDisplay();
184}
185
186function updateColorDisplay() {
187	togglecolor_button.innerText = watermark_invert ? "⚫" : "⚪";
188}
189
190function addWatermark(event, img, c, ctx) {
191	setBaseImage(img, c, ctx);
192
193	const rect = c.getBoundingClientRect();
194	const x = (event.clientX - rect.left) * c.width / c.clientWidth;
195	const y = (event.clientY - rect.top) * c.height / c.clientHeight;
196
197	ctx.globalAlpha = opacity_range.value;
198	ctx.filter = watermark_invert;
199	ctx.drawImage(WATERMARK, x - (WATERMARK_WIDTH / 2), y - (WATERMARK_HEIGHT / 2), WATERMARK_WIDTH, WATERMARK_HEIGHT);
200}
201
202function updateOpacity() {
203	opacity_label.innerHTML = Math.round(opacity_range.value * 100) + '%';
204}
205
206function getFactor(img_width, img_height, max_width, max_height){
207	return Math.min(max_width / img_width, max_height / img_height);
208}
209
210function setBaseImage(img, c, ctx) {
211	const f = getFactor(img.width, img.height, MAX_WIDTH, MAX_HEIGHT);
212
213	const new_width = c.width = Math.ceil(img.width * f);
214	const new_height = c.height = Math.ceil(img.height * f)
215
216	ctx.imageSmoothingEnabled = (f < 1);
217	ctx.drawImage(img, 0, 0, new_width, new_height);
218}
219
220function moveUpDown(id, amount) {
221	const pos = fanarts.indexOf(fanarts.find(element => element.id == id));
222	const new_pos = pos + amount;
223
224	if (new_pos <= -1 || new_pos >= fanarts.length) {
225		return;
226	}
227
228	[fanarts[pos], fanarts[new_pos]] = [fanarts[new_pos], fanarts[pos]];
229
230	updateFanartList();
231}
232
233async function postData(url = "", data = {}, contentType = "application/json") {
234    const response = await fetch(url, { method: "POST", headers: { "Content-Type": contentType }, body: JSON.stringify(data) });
235    return response.json();
236}
237
238function saveEntry(id) {
239	entry = getFanart(id);
240	if (!entry) return;
241	saveCanvas(entry.canvas, entry.canvas.getAttribute("data-filename"));
242}
243
244function saveCanvasIG(my_canvas) {
245	const f = getFactor(my_canvas.width, my_canvas.height, IG_MAX_WIDTH, IG_MAX_HEIGHT);
246
247	const width = Math.ceil(my_canvas.width * f);
248	const height = Math.ceil(my_canvas.height * f);
249
250	const offset_x = Math.round((IG_MAX_WIDTH - width) / 2);
251	const offset_y = Math.round((IG_MAX_HEIGHT - height) / 2);
252
253	destCtx = canvas_ig.getContext('2d');
254	destCtx.drawImage(IG_TEMPLATE, 0, 0);
255	destCtx.drawImage(my_canvas, IG_MIN_OFFSET_X + offset_x, IG_MIN_OFFSET_Y + offset_y, width, height);
256	saveCanvas(canvas_ig, "IG - " + my_canvas.getAttribute("data-filename"));
257}
258
259function saveEntryIG(id) {
260	entry = getFanart(id);
261	if (!entry) return;
262	saveCanvasIG(entry.canvas);
263}
264
265function getArtworks() {
266	get_button.disabled = true;
267	get_button.innerText = "…"
268    postData("/", { month: month_input.value }).then((data) => {
269        console.log(data);
270        fanarts = fanarts.concat(data);
271        controls_div.hidden = false;
272	    updateOpacity();
273	    updateFanartList();
274    });
275}
276
277function saveAll() {
278	const response = confirm("Vuoi davvero scaricare tutte le fanart?");
279	if(response == false) return;
280
281	fanarts.forEach((fanart) => {
282		if(fanart.enabled)
283			saveCanvas(fanart.canvas, fanart.canvas.getAttribute("data-filename"));
284	})
285}
286
287function saveAllIG() {
288	const response = confirm("Vuoi davvero scaricare tutte le storie per le fanart?");
289	if(response == false) return;
290
291	fanarts.forEach((fanart) => {
292		if(fanart.enabled)
293			saveCanvasIG(fanart.canvas);
294	});
295}