2345 |
2346 |
2347 |
2443 |
2444 |
2864 |
2865 |
2866 |
2867 |
--------------------------------------------------------------------------------
/src/Button.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
24 |
25 |
dispatch('grabPacks', e) }">
29 |

30 |
31 |
--------------------------------------------------------------------------------
/src/bd-main.js:
--------------------------------------------------------------------------------
1 | /* global BdApi */
2 | const App = require('./App.svelte');
3 |
4 | module.exports = class MaganeBD {
5 | log(message, type = 'log') {
6 | return console[type]('%c[MaganeBD]%c', 'color: #3a71c1; font-weight: 700', '', message);
7 | }
8 |
9 | load() {}
10 |
11 | start() {
12 | for (const id of Object.keys(global.MAGANE_STYLES)) {
13 | BdApi.injectCSS(`${this.constructor.name}-${id}`, global.MAGANE_STYLES[id]);
14 | }
15 | this.log('Mounting container into DOM\u2026');
16 | this.container = document.createElement('div');
17 | this.container.id = 'maganeContainer';
18 | document.body.appendChild(this.container);
19 | this.app = new App({
20 | target: this.container
21 | });
22 | }
23 |
24 | stop() {
25 | if (this.app) {
26 | this.log('Destroying Svelte component\u2026');
27 | this.app.$destroy();
28 | }
29 | if (this.container) {
30 | this.log('Removing container from DOM\u2026');
31 | this.container.remove();
32 | }
33 | for (const id of Object.keys(global.MAGANE_STYLES)) {
34 | BdApi.clearCSS(`${this.constructor.name}-${id}`);
35 | }
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/src/meta.txt:
--------------------------------------------------------------------------------
1 | @name <%= data.name %>
2 | @displayName <%= data.displayName %>
3 | @description <%= data.description %>
4 | @author Kana, Bobby
5 | @authorId 176200089226706944
6 | @authorLink https://github.com/Pitu
7 | @license MIT - https://opensource.org/licenses/MIT
8 | @version <%= pkg.version %>
9 | @invite 5g6vgwn
10 | @source https://github.com/Pitu/Magane
11 | @updateUrl <%= data.updateUrl %>
12 | @website https://magane.moe
13 | @donate https://github.com/sponsors/Pitu
14 | @patreon https://patreon.com/pitu
15 |
--------------------------------------------------------------------------------
/src/styles/main.scss:
--------------------------------------------------------------------------------
1 | /** Magane: main.scss **/
2 |
3 | div#magane {
4 | $backgroundPrimary: var(--background-secondary);
5 | $backgroundSecondary: var(--background-tertiary);
6 | $textColor: var(--header-secondary);
7 | $hoverColor: var(--interactive-active);
8 | $scrollbarColor: rgb(105, 96, 128);
9 | display: flex;
10 | flex-direction: row;
11 | height: 44px;
12 | position: absolute;
13 | z-index: 1001;
14 |
15 | button, input, select, label, span, p, a, li, ul, div, textarea {
16 | font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
17 | color: $textColor;
18 | font-weight: 400;
19 | line-height: 1.5;
20 | font-size: 16px;
21 | text-rendering: optimizeLegibility;
22 | text-size-adjust: 100%;
23 | }
24 |
25 | div.stickerWindow {
26 | width: 600px;
27 | min-height: 200px;
28 | position: fixed;
29 | background: $backgroundPrimary;
30 | max-height: 600px;
31 | transition: all 0.2s ease;
32 | border-radius: 4px;
33 | box-shadow: var(--elevation-stroke),var(--elevation-high);
34 |
35 | div.stickers {
36 | height: 550px !important;
37 | margin-bottom: 100px;
38 | position: relative;
39 |
40 | &.has-left-toolbar {
41 | height: 600px !important;
42 | margin-left: 50px;
43 | }
44 |
45 | h3.getStarted {
46 | text-align: center;
47 | padding-top: 40%;
48 | pointer-events: none;
49 | }
50 |
51 | div.pack {
52 | float: left;
53 | display: flex;
54 | flex-flow: wrap;
55 | justify-content: center;
56 | padding: 20px;
57 | width: 100%;
58 | box-sizing: border-box;
59 |
60 | span {
61 | color: $textColor;
62 | width: 100%;
63 | cursor: auto;
64 | padding-left: 10px;
65 | margin: 10px 0px;
66 |
67 | .counts {
68 | padding-left: 0;
69 | }
70 |
71 | .counts span {
72 | padding: 0 0.5em;
73 | }
74 | }
75 |
76 | div.sticker {
77 | display: flex;
78 | align-items: center;
79 | justify-content: center;
80 | width: 100px;
81 | height: 100px;
82 | float: left;
83 | position: relative;
84 |
85 | .image {
86 | cursor: pointer;
87 | max-height: 100%;
88 | max-width: 100%;
89 | }
90 |
91 | div.addFavorite, div.deleteFavorite {
92 | width: 20px;
93 | height: 20px;
94 | position: absolute;
95 | right: 0;
96 | transition: all 0.2s ease;
97 | display: none;
98 | &:hover {
99 | transform: scale(1.25);
100 | svg path {
101 | transition: all 0.2s ease;
102 | }
103 | }
104 | }
105 |
106 | div.addFavorite {
107 | bottom: 0;
108 | &:hover {
109 | svg path {
110 | fill: #2ECC71;
111 | }
112 | }
113 | }
114 |
115 | div.deleteFavorite {
116 | top: 0px;
117 | transform: rotateZ(45deg);
118 | &:hover {
119 | transform: scale(1.25) rotateZ(45deg);
120 | svg path {
121 | fill: #F04747;
122 | }
123 | }
124 | }
125 |
126 | &:hover div.addFavorite,
127 | &:hover div.deleteFavorite {
128 | display: block;
129 | cursor: pointer;
130 | }
131 | }
132 | }
133 | }
134 |
135 | div.packs-toolbar {
136 | position: absolute;
137 | bottom: 0;
138 | background: $backgroundSecondary;
139 | display: flex;
140 |
141 | &.has-scroll-x {
142 | width: 100%;
143 | height: 50px;
144 |
145 | div.packs {
146 | flex: 1 0 auto;
147 |
148 | &.packs-controls {
149 | flex: 0 0 auto;
150 | }
151 |
152 | div.packs-wrapper {
153 | white-space: nowrap;
154 | float: left;
155 | width: 100%;
156 | font-size: 0; /* quick hax to clear whitespace */
157 | }
158 | }
159 | }
160 |
161 | &.has-scroll-y {
162 | width: 50px;
163 | height: 100%;
164 | flex-direction: column;
165 |
166 | div.packs {
167 | flex: 1 1 auto;
168 | height: 100%;
169 |
170 | &.packs-controls {
171 | flex: 0 0 auto;
172 | height: auto;
173 | }
174 |
175 | div.packs-wrapper {
176 | font-size: 0; /* quick hax to clear whitespace */
177 | }
178 | }
179 | }
180 |
181 | div.packs div.pack {
182 | display: inline-block;
183 | height: 40px;
184 | width: 40px;
185 | margin: 5px;
186 | cursor: pointer;
187 | background-position: center;
188 | background-size: contain;
189 | background-repeat: no-repeat;
190 | transition: all 0.2s ease;
191 | filter: grayscale(100%);
192 |
193 | &:hover,
194 | div.pack.active {
195 | transform: scale(1.25);
196 | filter: grayscale(0%);
197 | }
198 |
199 | > div {
200 | background-image: url('/assets/62ed7720accb1adfe95565b114e843c6.png');
201 | width: 32px;
202 | height: 32px;
203 | background-size: 1344px 1216px;
204 | background-repeat: no-repeat;
205 | margin-top: 4px;
206 | margin-left: 4px;
207 | }
208 |
209 | div.icon-favorite {
210 | background-position: -1056px -288px;
211 | }
212 |
213 | div.icon-plus {
214 | background-position: -384px -896px;
215 | /* make it greenish */
216 | /* thanks to the magic of https://codepen.io/sosuke/pen/Pjoqqp */
217 | filter: invert(63%) sepia(25%) saturate(813%) hue-rotate(55deg) brightness(98%) contrast(82%);
218 | }
219 |
220 | div.icon-frequently-used {
221 | background-position: -160px -960px;
222 | }
223 | }
224 | }
225 | }
226 |
227 | .stickersModal {
228 | bottom: 0;
229 | left: 0;
230 | position: absolute;
231 | right: 0;
232 | top: 0;
233 | align-items: center;
234 | justify-content: center;
235 |
236 | &.is-active {
237 | display: flex;
238 | }
239 |
240 | .inputQuery {
241 | width: calc(100% - 30px);
242 | height: 36px;
243 | box-sizing: border-box;
244 | margin: 0 15px 10px;
245 | padding: 5px 12px;
246 | border-radius: 3px;
247 | border: 1px solid $backgroundPrimary;
248 | background: $backgroundPrimary;
249 | color: $textColor;
250 | }
251 |
252 | textarea.inputQuery {
253 | height: auto;
254 | min-height: 54px;
255 | }
256 |
257 | .inputPackIndex {
258 | width: 55px;
259 | height: 36px;
260 | box-sizing: border-box;
261 | padding: 5px 12px;
262 | border-radius: 3px;
263 | border: 1px solid $backgroundPrimary;
264 | background: $backgroundPrimary;
265 | color: $textColor;
266 | text-align: center;
267 | }
268 |
269 | .modal-background {
270 | bottom: 0;
271 | left: 0;
272 | position: absolute;
273 | right: 0;
274 | top: 0;
275 | width: 100%;
276 | height: 100%;
277 | background-color: rgba(10, 10, 10, 0.86);
278 | }
279 |
280 | .modal-content,
281 | .modal-card {
282 | position: absolute;
283 | width: 100%;
284 | height: 100%;
285 | left: 0;
286 | top: 0;
287 | background: $backgroundSecondary;
288 | }
289 |
290 | .modal-content {
291 | .stickersConfig {
292 | height: 100%;
293 | width: 100%;
294 | display: flex;
295 | flex-direction: column;
296 |
297 | .tabs {
298 | width: 100%;
299 | text-align: center;
300 |
301 | .tab {
302 | color: $textColor;
303 | display: inline-block;
304 | border: none;
305 | border-top: 0px transparent;
306 | border-left: 0px transparent;
307 | border-right: 0px transparent;
308 | border-width: 1px;
309 | border-style: solid;
310 | border-bottom-color: $textColor;
311 | padding: 20px;
312 | cursor: pointer;
313 |
314 | &:hover,
315 | &.is-active {
316 | border-bottom-color: $hoverColor;
317 | color: $hoverColor;
318 | }
319 | }
320 | }
321 |
322 | div.tab-content {
323 | height: calc(100% - 66px); /* .tabs height */
324 | width: 100%;
325 | padding: 10px 0;
326 | box-sizing: border-box;
327 |
328 | &.avail-packs {
329 | display: flex;
330 | flex-direction: column;
331 | padding-bottom: 0;
332 |
333 | .packs {
334 | height: 100%;
335 | width: 100%;
336 | padding-bottom: 10px;
337 | }
338 | }
339 |
340 | &.import,
341 | &.misc {
342 | user-select: text;
343 |
344 | .section {
345 | padding: 0 24px 14px;
346 |
347 | .section-title {
348 | font-weight: 800;
349 | }
350 |
351 | > p:last-of-type {
352 | margin-bottom: 0;
353 | }
354 |
355 | a {
356 | /* inherit Discord's link color */
357 | color: var(--text-link);
358 |
359 | &:hover {
360 | text-decoration: underline;
361 | }
362 | }
363 | }
364 |
365 | .input-grouped {
366 | display: flex;
367 |
368 | input {
369 | margin: 0;
370 | width: auto;
371 | flex-grow: 1;
372 | }
373 |
374 | textarea {
375 | margin: 0;
376 | width: auto;
377 | flex-grow: 1;
378 | }
379 |
380 | button {
381 | margin-left: 4px;
382 | }
383 | }
384 | }
385 | }
386 |
387 | div.pack {
388 | height: 75px;
389 | width: 100%;
390 | float: left;
391 | display: flex;
392 | padding: 0 20px;
393 | box-sizing: border-box;
394 | margin-bottom: 5px;
395 |
396 | &:last-of-type {
397 | margin-bottom: 0;
398 | }
399 |
400 | div.index,
401 | div.handle,
402 | div.preview {
403 | flex: 0 0 auto;
404 | min-width: 75px;
405 | }
406 |
407 | div.action {
408 | flex: 1 0 auto;
409 |
410 | &.is-tight button {
411 | width: auto;
412 | padding-right: 0.5em;
413 | padding-left: 0.5em;
414 | }
415 |
416 | button.delete-pack {
417 | width: 36px;
418 | height: 36px;
419 |
420 | &:before,
421 | &:after {
422 | background-color: $textColor;
423 | content: "";
424 | display: block;
425 | left: 50%;
426 | position: absolute;
427 | top: 50%;
428 | transform: translateX(-50%) translateY(-50%) rotate(45deg);
429 | transform-origin: center center;
430 | }
431 |
432 | &:before {
433 | height: 2px;
434 | width: 50%;
435 | }
436 |
437 | &:after {
438 | height: 50%;
439 | width: 2px;
440 | }
441 | }
442 | }
443 |
444 | div.index {
445 | padding-top: 20px;
446 | text-align: left;
447 | }
448 |
449 | div.preview {
450 | height: 75px;
451 | background-position: center;
452 | background-size: contain;
453 | background-repeat: no-repeat;
454 | }
455 |
456 | div.handle {
457 | padding: 20px;
458 | cursor: move;
459 | padding-top: 30px;
460 |
461 | span {
462 | background: #555;
463 | height: 2px;
464 | width: 100%;
465 | display: block;
466 | margin-bottom: 6px;
467 | }
468 | }
469 |
470 | div.action {
471 | padding-top: 20px;
472 | text-align: right;
473 | }
474 |
475 | div.info {
476 | flex: 1 1 auto;
477 | padding: 14px;
478 |
479 | > span {
480 | display: block;
481 | width: 100%;
482 | color: $textColor;
483 |
484 | &:nth-of-type(1) {
485 | font-weight: bold;
486 | color: $textColor;
487 | }
488 |
489 | .appendix span {
490 | &:nth-of-type(1) {
491 | padding: 0 0.5em;
492 | }
493 |
494 | &:nth-of-type(2) {
495 | user-select: text;
496 | }
497 | }
498 | }
499 | }
500 |
501 | div.preview img {
502 | height: 100%;
503 | width: 100%;
504 | }
505 | }
506 | }
507 | }
508 |
509 | .modal-close {
510 | user-select: none;
511 | background-color: rgba(10, 10, 10, 0.2);
512 | border: none;
513 | border-radius: 290486px;
514 | cursor: pointer;
515 | display: inline-block;
516 | flex-grow: 0;
517 | flex-shrink: 0;
518 | font-size: 0;
519 | outline: none;
520 | vertical-align: top;
521 | background: none;
522 | position: absolute;
523 | right: 20px;
524 | top: 20px;
525 | height: 32px;
526 | max-height: 32px;
527 | max-width: 32px;
528 | min-height: 32px;
529 | min-width: 32px;
530 | width: 32px;
531 |
532 | &:before,
533 | &:after {
534 | background-color: $textColor;
535 | content: "";
536 | display: block;
537 | left: 50%;
538 | position: absolute;
539 | top: 50%;
540 | transform: translateX(-50%) translateY(-50%) rotate(45deg);
541 | transform-origin: center center;
542 | }
543 |
544 | &:before {
545 | height: 2px;
546 | width: 50%;
547 | }
548 |
549 | &:after {
550 | height: 50%;
551 | width: 2px;
552 | }
553 |
554 | &:hover,
555 | &:focus {
556 | background-color: rgba(10, 10, 10, 0.3);
557 | }
558 | }
559 | }
560 |
561 | .button {
562 | align-items: center;
563 | border: 1px solid transparent;
564 | border-radius: 3px;
565 | box-shadow: none;
566 | display: inline-flex;
567 | font-size: 1rem;
568 | padding: calc(0.375em - 1px) 0.75em;
569 | position: relative;
570 | vertical-align: top;
571 | user-select: none;
572 | cursor: pointer;
573 | justify-content: center;
574 | text-align: center;
575 | white-space: nowrap;
576 | border-color: transparent;
577 | color: $textColor;
578 | background-color: $backgroundPrimary;
579 | width: 62px; /* consistent width */
580 |
581 | &.is-danger {
582 | color: #ffffff;
583 | border-color: rgba(240,71,71,.3);
584 | background: #f04747;
585 | }
586 |
587 | &:hover, &.is-primary:hover {
588 | transform: scale3d(1.1, 1.1, 1.1);
589 | }
590 |
591 | &.has-width-full {
592 | width: 100%;
593 |
594 | &:hover {
595 | /* TODO: Figure out how to do a more consistent scaling,
596 | regardless of the button's dynamic size. */
597 | transform: scale3d(1.04, 1.04, 1.04);
598 | }
599 | }
600 | }
601 |
602 | .has-scroll-x {
603 | overflow-x: auto;
604 | scrollbar-gutter: stable;
605 | }
606 |
607 | .has-scroll-y {
608 | overflow-y: auto;
609 | scrollbar-gutter: stable;
610 | }
611 |
612 | ::-webkit-scrollbar {
613 | /* Let's make the scrollbars pretty */
614 | width: 6px;
615 | height: 6px;
616 |
617 | &-track {
618 | margin: 0;
619 | background: transparent;
620 | border-radius: 5px;
621 |
622 | &-piece {
623 | border: 0 solid transparent;
624 | background: transparent;
625 | margin: 0;
626 | }
627 | }
628 |
629 | &-thumb {
630 | background: rgba($scrollbarColor, 0.5);
631 | border: 0 solid transparent;
632 | border-radius: 5px;
633 |
634 | &:hover {
635 | background: rgba($scrollbarColor, 0.75);
636 | }
637 |
638 | &:active {
639 | background: rgba($scrollbarColor, 1);
640 | }
641 | }
642 | }
643 |
644 | code {
645 | box-sizing: border-box;
646 | padding: 2px 6px;
647 | border-radius: 3px;
648 | border: 1px solid $backgroundPrimary;
649 | background: $backgroundPrimary;
650 | color: $textColor;
651 | }
652 | }
653 |
654 | div#maganeButton {
655 | &.channel-textarea-stickers {
656 | display: flex;
657 | align-items: center;
658 | cursor: pointer;
659 |
660 | &:hover, &.active {
661 | filter: brightness(1.35);
662 | }
663 | }
664 |
665 | img.channel-textarea-stickers-content {
666 | width: 24px;
667 | height: 24px;
668 | padding: 4px;
669 | margin-left: 2px;
670 | margin-right: 2px;
671 | }
672 | }
673 |
674 | /* Visually hide Magane button in certain scenarios */
675 |
676 | div[class^="submitContainer_"] div#maganeButton { /* create thread */
677 | display: none;
678 | }
679 |
680 | div[data-list-item-id^="forum-channel-list-"] div#maganeButton { /* create forum post */
681 | display: none;
682 | }
683 |
--------------------------------------------------------------------------------
/src/vencord-main.js:
--------------------------------------------------------------------------------
1 | /* global definePlugin */
2 | const App = require('./App.svelte');
3 |
4 | const pluginName = 'MaganeVencord';
5 |
6 | export default definePlugin({
7 | name: pluginName,
8 | authors: [
9 | {
10 | id: 176200089226706944n,
11 | name: 'Pitu'
12 | },
13 | {
14 | id: 530445553562025984n,
15 | name: 'Bobby'
16 | }
17 | ],
18 | description: 'Bringing LINE stickers to Discord in a chaotic way. Vencord edition.',
19 |
20 | log(message, type = 'log') {
21 | return console[type]('%c[MaganeVencord]%c', 'color: #3a71c1; font-weight: 700', '', message);
22 | },
23 |
24 | start() {
25 | for (const id of Object.keys(window.MAGANE_STYLES)) {
26 | const style = document.createElement('style');
27 | style.id = `${pluginName}-${id}`;
28 | style.innerText = window.MAGANE_STYLES[id];
29 | document.head.appendChild(style);
30 | }
31 | this.log('Mounting container into DOM\u2026');
32 | this.container = document.createElement('div');
33 | this.container.id = 'maganeContainer';
34 | document.body.appendChild(this.container);
35 | this.app = new App({
36 | target: this.container
37 | });
38 | },
39 |
40 | stop() {
41 | if (this.app) {
42 | this.log('Destroying Svelte component\u2026');
43 | this.app.$destroy();
44 | }
45 | if (this.container) {
46 | this.log('Removing container from DOM\u2026');
47 | this.container.remove();
48 | }
49 | for (const id of Object.keys(window.MAGANE_STYLES)) {
50 | const _style = document.head.getElementById(`${pluginName}-${id}`);
51 | if (_style) {
52 | _style.remove();
53 | }
54 | }
55 | }
56 | });
57 |
--------------------------------------------------------------------------------