diff --git a/README.md b/README.md
index fdfa9a7..f7fe71d 100644
--- a/README.md
+++ b/README.md
@@ -15,4 +15,4 @@ Join our Discord:
-
+
\ No newline at end of file
diff --git a/locales/en_US.json b/locales/en_US.json
index 936f6e7..0946d15 100644
--- a/locales/en_US.json
+++ b/locales/en_US.json
@@ -11,6 +11,15 @@
"accountWidget": {
"settings": "Settings",
"logout": "Logout"
+ },
+ "dropdown": {
+ "captions": {
+ "credits": "Meet the team",
+ "about": "About the project",
+ "faq": "Frequently asked questions",
+ "blog": "Our latest updates, condensed",
+ "progress": "Check the project progress and goals"
+ }
}
},
"hero": {
diff --git a/package-lock.json b/package-lock.json
index e6ab64d..abe7838 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3078,9 +3078,9 @@
}
},
"node_modules/mongoose": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.4.0.tgz",
- "integrity": "sha512-eBDrueap1Zx3qFrcYylTiqTFlL5iTEaYAxoDF1MSRdipwAzChQRMJve+vxHtxPhI2q5tmf9RYHfZwXfTUHPd3g==",
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.4.6.tgz",
+ "integrity": "sha512-ZAfNCWgXhwev6k/+rMzjHIJ/+wLkundQU/i+aUTqmCgGoYqc+B5e4EC4Y3E1XaLzNXiWID1/vocSM6zs5IAGvA==",
"dependencies": {
"bson": "^4.6.2",
"kareem": "2.4.1",
@@ -4354,9 +4354,9 @@
}
},
"node_modules/undici": {
- "version": "5.8.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.8.0.tgz",
- "integrity": "sha512-1F7Vtcez5w/LwH2G2tGnFIihuWUlc58YidwLiCv+jR2Z50x0tNXpRRw7eOIJ+GvqCqIkg9SB7NWAJ/T9TLfv8Q==",
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.10.0.tgz",
+ "integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==",
"engines": {
"node": ">=12.18"
}
@@ -6938,9 +6938,9 @@
}
},
"mongoose": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.4.0.tgz",
- "integrity": "sha512-eBDrueap1Zx3qFrcYylTiqTFlL5iTEaYAxoDF1MSRdipwAzChQRMJve+vxHtxPhI2q5tmf9RYHfZwXfTUHPd3g==",
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.4.6.tgz",
+ "integrity": "sha512-ZAfNCWgXhwev6k/+rMzjHIJ/+wLkundQU/i+aUTqmCgGoYqc+B5e4EC4Y3E1XaLzNXiWID1/vocSM6zs5IAGvA==",
"requires": {
"bson": "^4.6.2",
"kareem": "2.4.1",
@@ -7928,9 +7928,9 @@
}
},
"undici": {
- "version": "5.8.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.8.0.tgz",
- "integrity": "sha512-1F7Vtcez5w/LwH2G2tGnFIihuWUlc58YidwLiCv+jR2Z50x0tNXpRRw7eOIJ+GvqCqIkg9SB7NWAJ/T9TLfv8Q=="
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.10.0.tgz",
+ "integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g=="
},
"universalify": {
"version": "2.0.0",
diff --git a/public/assets/css/account.css b/public/assets/css/account.css
index 47da37e..bbed44e 100644
--- a/public/assets/css/account.css
+++ b/public/assets/css/account.css
@@ -12,9 +12,11 @@
/* Account settings sidebar */
.account-sidebar .user {
- text-align: center;
margin: 55px auto;
width: fit-content;
+ display: flex;
+ flex-flow: column;
+ align-items: center;
}
.account-sidebar .user .miiname {
font-size: 1.2rem;
@@ -341,4 +343,4 @@ footer {
.setting-card .setting-list {
grid-template-columns: auto;
}
-}
\ No newline at end of file
+}
diff --git a/public/assets/css/documentation.css b/public/assets/css/documentation.css
index 1f001a4..0b3e11a 100644
--- a/public/assets/css/documentation.css
+++ b/public/assets/css/documentation.css
@@ -23,10 +23,16 @@ button#openSidebar {
}
.docs-wrapper header {
+ position: relative;
box-sizing: border-box;
margin: 20px;
margin-left: 0;
}
+.docs-wrapper header::before {
+ content: none;
+ background: none;
+ pointer-events: none;
+}
.docs-wrapper header a.logo-link {
display: none;
}
@@ -278,6 +284,7 @@ button#openSidebar {
.docs-wrapper header {
margin-left: 20px;
width: 100%;
+ left: 0;
}
.docs-wrapper {
@@ -321,12 +328,34 @@ button#openSidebar {
}
}
+@media screen and (max-width: 900px) {
+ .docs-wrapper header button.dropdown-button#mobile-button {
+ display: none;
+ }
+ .docs-wrapper header .logo-link svg text {
+ display: block;
+ }
+ .docs-wrapper header .logo-link svg {
+ width: 120px;
+ }
+}
+
@media screen and (max-width: 820px) {
.docs-wrapper .content .quick-links-grid,
.platform-grid {
grid-template-columns: 1fr;
grid-auto-rows: 1fr;
}
+
+ .docs-wrapper header a.logo-link {
+ margin-right: 6px;
+ }
+}
+
+@media screen and (max-width: 576px) {
+ .docs-wrapper header div.dropdown {
+ left: calc(-39.876px - 6px - 30px - 40px);
+ }
}
@media screen and (max-width: 492px) {
diff --git a/public/assets/css/main.css b/public/assets/css/main.css
index 2f52611..c60b039 100644
--- a/public/assets/css/main.css
+++ b/public/assets/css/main.css
@@ -4,7 +4,9 @@
--bg-shade-0: #131733;
--bg-shade-1: #1B1F3B;
--bg-shade-2: #23274A;
+ --bg-shade-2-5: #2D3258;
--bg-shade-3: #373C65;
+ --bg-shade-3-5: #404673;
--bg-shade-4: #494F81;
--accent-shade-0: #673DB6;
@@ -65,7 +67,7 @@ body, .main-body {
.wrapper {
width: 95%;
max-width: 1590px;
- margin: 0 auto;
+ margin: 48px auto 0;
}
h1.dot:not([data-title-suffix]):after, h2.dot:not([data-title-suffix]):after {
@@ -636,8 +638,8 @@ section.update-signup div.circle {
/* the next 4 lines make it so the circle is always the same aspect ratio and covers enough of the screen */
width: 2591px;
height: 1454px;
- min-width: 135vw;
- min-height: 76vw; /* yes, this is supposed to be in vw */
+ min-width: 145vw;
+ min-height: 13vw; /* yes, this is supposed to be in vw */
border-radius: 100%;
position: absolute;
top: 0;
@@ -864,8 +866,8 @@ section.update-signup div.circle {
padding: 8px 27px;
}
.button.secondary.icon-btn {
- width: 41px;
- height: 41px;
+ width: 41px !important;
+ height: 41px !important;
}
.button.icon-btn svg {
min-width: 30px;
@@ -1009,4 +1011,4 @@ section.update-signup div.circle {
.purple-circle {
display: none;
}
-}
\ No newline at end of file
+}
diff --git a/public/assets/css/partials/footer.css b/public/assets/css/partials/footer.css
index 8e64a29..da71bc4 100644
--- a/public/assets/css/partials/footer.css
+++ b/public/assets/css/partials/footer.css
@@ -127,8 +127,8 @@ footer .bandwidth-raccoon-wrapper .text-bubble:after {
z-index: 1;
border-style: solid;
border-color: var(--bg-shade-3) transparent;
- border-width: 10px 10px 0;
- bottom: -10px;
+ border-width: 12px 12px 0;
+ bottom: -9px;
right: 60px;
margin-left: -10px;
}
diff --git a/public/assets/css/partials/header.css b/public/assets/css/partials/header.css
index 3d95b73..fbdc397 100644
--- a/public/assets/css/partials/header.css
+++ b/public/assets/css/partials/header.css
@@ -1,7 +1,53 @@
header {
+ position: fixed;
+ top: 0;
+ left: 2.5%;
display: flex;
align-items: center;
+ width: 95%;
margin-top: 35px;
+ z-index: 60;
+ transition: box-shadow 180ms, background 180ms;
+}
+header * {
+ z-index: 1;
+}
+header::before {
+ content: "";
+ position: absolute;
+ top: -35px;
+ left: -10vw;
+ width: 120vw;
+ height: calc(100% + 35px + 35px);
+ background: rgba(27, 31, 59, 0.98);
+ transition: background 180ms;
+}
+header.transparent,
+header.transparent::before {
+ background: rgba(27, 31, 59, 0);
+}
+header.dropdown-active {
+ background: rgba(27, 31, 59, 0.98);
+ box-shadow: 0 0 0 600vw rgba(27, 31, 59, 0.8);
+}
+header .dropdown-arrow {
+ opacity: 0;
+ position: absolute;
+ width: 0;
+ border-style: solid;
+ border-color: var(--bg-shade-3) transparent;
+ border-width: 0 14px 14px;
+ bottom: -26px;
+ margin-left: -10px;
+ margin-bottom: -10px;
+ transition: left 180ms, margin-bottom 180ms, opacity 180ms;
+ pointer-events: none;
+}
+
+header.dropdown-active .dropdown-arrow {
+ opacity: 1;
+ display: block;
+ margin-bottom: 0;
}
header a {
text-decoration: none;
@@ -10,23 +56,225 @@ header .logo-link,
header .logo-link svg {
display: block;
}
-header nav a:first-child {
+
+header div.left-section {
+ display: flex;
+ flex-flow: row nowrap;
+}
+
+header nav {
+ position: relative;
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
margin-left: 40px;
}
-header nav a {
+header button.dropdown-button#mobile-button {
+ display: none;
+ background: none;
+ padding: 0;
+ margin-right: 12px;
+ transition: transform 200ms;
+}
+header button.dropdown-button#mobile-button.active {
+ transform: rotate(90deg);
+}
+
+header div.dropdown-button-wrapper {
+ position: relative;
+ display: flex;
+ flex-flow: row nowrap;
+}
+/* these are safezones where the dropdown will not close */
+header div.dropdown-button-wrapper::before {
+ content: "";
+ position: absolute;
+ top: -16px;
+ bottom: 100%;
+ left: 0;
+ right: -12px;
+}
+header div.dropdown-button-wrapper::after {
+ content: "";
+ position: absolute;
+ top: 100%;
+ bottom: -32px;
+ left: 0;
+ right: -12px;
+}
+
+header nav button {
+ background: none;
color: var(--text-shade-1);
margin: 0 17px;
- text-decoration: none;
+ padding: 0;
}
-header nav a:hover {
+header nav button:hover,
+header nav button.active {
+ background: none;
color: var(--text-shade-3);
- transition: color 50ms ease-in-out;
+}
+header nav a.donate button {
+ display: grid;
+ grid-auto-flow: column;
+ align-items: center;
+ gap: 4px;
+ font-weight: bold;
+ background: #332b61;
+ color: var(--accent-shade-3);
+ padding: 2px 12px;
+ border-radius: 24px;
+}
+header nav a.donate button svg {
+ height: 1rem;
+ width: 1rem;
+}
+header nav a.donate button:hover {
+ background: var(--accent-shade-0);
+ color: #fff;
+}
+header nav a.donate button.dropdown-button::after {
+ content: "";
+ display: inline-block;
+ align-items: center;
+ width: 16px;
+ height: 8px;
+ bottom: 0;
+ margin-left: 0.3rem;
+ background: no-repeat center url("/assets/images/down-arrow.svg");
+ filter: brightness(0) invert(78%) sepia(2%) saturate(5488%) hue-rotate(197deg)
+ brightness(88%) contrast(93%);
+
+ transition: transform 100ms;
+}
+header nav button.dropdown-button.active::after {
+ transform: scaleY(-1);
+ filter: none;
+}
+
+header div.dropdown {
+ position: absolute;
+ top: 100%;
+ margin-top: 24px;
+ left: 0;
+ display: block;
+ background: var(--bg-shade-3);
+ border-radius: 8px;
+ width: 420px;
+ height: 0;
+ overflow-y: hidden;
+ transition: height 180ms;
+}
+header div.dropdown * {
+ box-sizing: border-box;
+}
+
+header div.dropdown-content {
+ position: absolute;
+ top: 0;
+ width: 100%;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 180ms;
+}
+header div.dropdown-content.show {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+header div.dropdown .top {
+ padding: 32px 18px;
+}
+header div.dropdown .top a {
+ position: relative;
+ display: grid;
+ grid-auto-flow: column;
+ gap: 16px;
+ justify-content: start;
+ align-items: center;
+ color: var(--text-shade-1);
+ padding: 16px;
+ border-radius: 8px;
+}
+header div.dropdown .top a .icon {
+ background: var(--bg-shade-2);
+ color: var(--accent-shade-3);
+ height: 56px;
+ width: 56px;
+ border-radius: 8px;
+}
+header div.dropdown .top a:hover .icon {
+ background: #151b44;
+ color: var(--accent-shade-1);
+}
+header div.dropdown .top a .icon svg {
+ width: 32px;
+ height: 32px;
+ margin: 12px;
+}
+header div.dropdown .top a .title {
+ margin: 0;
+ font-weight: bold;
+ color: var(--text-shade-3);
+}
+header div.dropdown .top a .caption {
+ margin: 0;
+}
+header div.dropdown .top a:hover {
+ background: var(--bg-shade-2-5);
+}
+header div.dropdown .top a:hover::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 24px;
+ width: 24px;
+ height: 100%;
+ background: no-repeat center url("/assets/images/arrow-right.svg");
+ /* garbage to make it look the same color */
+ filter: brightness(0) invert(60%) sepia(70%) saturate(453%) hue-rotate(208deg)
+ brightness(113%) contrast(97%);
+}
+header div.dropdown .top a:hover .title {
+ color: var(--accent-shade-3);
+}
+
+header div.dropdown .bottom {
+ display: grid;
+ grid-auto-flow: column;
+ justify-content: center;
+ gap: 24px;
+ background: var(--bg-shade-3-5);
+ padding: 22px;
+ width: 100%;
+ box-sizing: border-box;
+}
+header div.dropdown .bottom a {
+ width: 48px;
+ height: 48px;
+ background: var(--bg-shade-3);
+ color: var(--text-shade-3);
+ border-radius: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+header div.dropdown .bottom a:hover {
+ background: var(--bg-shade-2);
+}
+header div.dropdown .bottom a svg {
+ width: 24px;
+ height: auto;
+}
+
+header div.dropdown .top a.show-on-mobile {
+ display: none;
}
header .right-section {
display: grid;
grid-auto-flow: column;
- grid-gap: 24px;
+ gap: 24px;
margin-left: auto;
z-index: 2;
color: var(--text-shade-1);
@@ -46,12 +294,14 @@ header .locale-dropdown-toggle.active {
}
header .user-widget-wrapper {
- height: 24px;
+ height: auto;
}
header .user-widget-wrapper a.login-link {
color: var(--text-shade-1);
text-decoration: none;
+ display: block;
+ height: 32px;
transition: color 150ms;
}
header .user-widget-wrapper a.login-link:hover {
@@ -128,16 +378,83 @@ header .user-widget .button.logout {
}
@media screen and (max-width: 900px) {
- header nav a:not(.keep-on-mobile) {
- display: none;
+ header {
+ position: relative;
+ justify-content: flex-end;
+ width: 90%;
+ left: 5%;
}
- header .logo-link {
- margin-right: 20px;
+ header .hide-on-mobile {
+ display: none !important;
+ }
+ header button.dropdown-button#mobile-button {
+ display: block;
+ }
+ header .left-section {
+ margin-right: auto;
+ }
+ header .right-section {
+ margin-left: 24px;
+ }
+ header nav a.donate button {
+ margin: 0;
+ }
+
+ header div.dropdown {
+ left: unset;
+ right: -104px;
+ width: 90vw;
+ }
+ header div.dropdown .top {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
}
}
-@media screen and (max-width: 480px) {
+@media screen and (max-width: 600px) {
+ header div.dropdown .top {
+ grid-template-columns: 1fr;
+ }
+ header div.dropdown .top {
+ padding: 16px 9px;
+ }
+}
+
+@media screen and (max-width: 500px) {
+ header nav a.donate button span {
+ display: none;
+ }
+ header nav a.donate button {
+ padding: 6px;
+ }
+}
+
+@media screen and (max-width: 420px) {
+ header nav a.donate button {
+ display: none;
+ }
+ header .right-section {
+ margin-left: 0;
+ }
+ header div.dropdown {
+ right: -80px;
+ }
+ header div.dropdown .top a {
+ padding: 8px;
+ }
+ header div.dropdown .top a .icon {
+ height: 40px;
+ width: 40px;
+ }
+ header div.dropdown .top a .icon svg {
+ width: 24px;
+ height: 24px;
+ margin: 8px;
+ }
+}
+
+@media screen and (max-width: 330px) {
header .logo-link svg text {
display: none;
}
@@ -147,9 +464,6 @@ header .user-widget .button.logout {
}
header .logo-link {
- margin-right: 10px;
- }
- header nav a {
- margin: 0 10px;
+ margin-right: 6px;
}
}
diff --git a/public/assets/images/arrow-right.svg b/public/assets/images/arrow-right.svg
new file mode 100644
index 0000000..88abada
--- /dev/null
+++ b/public/assets/images/arrow-right.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/js/header-handler.js b/public/assets/js/header-handler.js
index 4acbbfc..5bccda6 100644
--- a/public/assets/js/header-handler.js
+++ b/public/assets/js/header-handler.js
@@ -1,5 +1,118 @@
/* eslint-disable no-undef, no-unused-vars */
+const header = document.querySelector('header');
+const dropdownButtonWrapper = document.querySelector('.dropdown-button-wrapper');
+const dropdown = document.querySelector('header div.dropdown');
+const allDropdownButtons = document.querySelectorAll('button.dropdown-button');
+const desktopDropdownBtns = document.querySelectorAll('header .dropdown-button-wrapper button.dropdown-button');
+const mobileDropdownBtn = document.querySelector('.dropdown-button#mobile-button');
+let dropdownContent;
+
+function isDropdownOpen() {
+ return header.classList.contains('dropdown-active');
+}
+
+function closeDropdown() {
+ dropdown.style.height = '0';
+ header.classList.remove('dropdown-active');
+ // deselect all buttons
+ allDropdownButtons.forEach((button) => {
+ button.classList.remove('active');
+ });
+}
+window.addEventListener('resize', () => {
+ if (isDropdownOpen() && dropdownContent) {
+ // set the dropdown height to the height of the content
+ dropdown.style.height = `${dropdownContent.offsetHeight}px`;
+ }
+});
+
+function navbarDropdownHandler(buttonID) {
+ const allDropdownContents = dropdown.querySelectorAll('div.dropdown-content');
+ dropdownContent = document.querySelector(`.dropdown-content#${buttonID}-dropdown-content`);
+ const dropdownButton = document.querySelector(`button.dropdown-button#${buttonID}-button`);
+ const dropdownArrow = document.querySelector('.dropdown-arrow#navbar-dropdown-arrow');
+
+ // if on mobile, reclicking the button should close the dropdown
+ if (buttonID === 'mobile' && dropdownButton.classList.contains('active')) {
+ closeDropdown();
+ return;
+ }
+
+ // hide all contents
+ allDropdownContents.forEach((content) => {
+ content.classList.remove('show');
+ });
+ // deselect all buttons
+ allDropdownButtons.forEach((button) => {
+ button.classList.remove('active');
+ });
+ // show the content of the clicked button
+ dropdownContent.classList.add('show');
+ // select the clicked button
+ dropdownButton.classList.add('active');
+ // set the dropdown height to the height of the content
+ dropdown.style.height = `${dropdownContent.offsetHeight}px`;
+
+ // move the arrow to the selected button
+ dropdownArrow.style.left = `${dropdownButton.offsetLeft + dropdownButton.offsetWidth / 2 - 5}px`;
+
+ // dim the rest of the page
+ header.classList.add('dropdown-active');
+}
+
+const dropdownAnchors = document.querySelectorAll('.dropdown-content a');
+dropdownAnchors.forEach((a) => {
+ a.addEventListener('click', () => {
+ closeDropdown();
+ });
+});
+
+
+// make the header background transparent if near the top of the page
+function makeHeaderBackgroundTransparent() {
+ if(window.pageYOffset < 100) {
+ header.classList.add('transparent');
+ } else {
+ header.classList.remove('transparent');
+ }
+}
+makeHeaderBackgroundTransparent();
+window.addEventListener('scroll', () => {
+ makeHeaderBackgroundTransparent();
+});
+
+desktopDropdownBtns.forEach((btn) => {
+ [ 'click', 'mouseover' ].forEach((event) => {
+ btn.addEventListener(event, () => {
+ const id = btn.id.replace('-button', '');
+ navbarDropdownHandler(id);
+ });
+ });
+});
+mobileDropdownBtn.addEventListener('click', () => {
+ const id = 'mobile';
+ navbarDropdownHandler(id, true);
+});
+
+/* if on desktop: we check if the element the mouse moves to is part of the ignored element (keep the dropdown open) or not (close the dropdown)
+ * if on mobile: do nothing
+*/
+function dropdownOnMouseLeave(e, ignoredElement) {
+ if (window.innerWidth > 900) {
+ const targetElement = e.relatedTarget || e.toElement;
+ if (targetElement !== ignoredElement && !ignoredElement.contains(targetElement)) {
+ closeDropdown();
+ }
+ }
+}
+dropdownButtonWrapper.addEventListener('mouseleave', (e) => {
+ dropdownOnMouseLeave(e, dropdown);
+});
+dropdown.addEventListener('mouseleave', (e) => {
+ dropdownOnMouseLeave(e, dropdownButtonWrapper);
+});
+
// Account widget handler
const userWidgetToggle = document.querySelector('.user-widget-toggle') ;
const userWidget = document.querySelector('.user-widget');
diff --git a/public/assets/js/miieditor.js b/public/assets/js/miieditor.js
index 58e7f8e..cd90a4c 100644
--- a/public/assets/js/miieditor.js
+++ b/public/assets/js/miieditor.js
@@ -1,4 +1,12 @@
-// This file gets automatically bundled with browserify when running the start script. This also means that after any update you're gonna need to restart the server to see any changes.
+/**
+ * Compilation note:
+ * This file gets automatically bundled with browserify when running the start script.
+ * This also means that after any update you're gonna need to restart the server to see any changes.
+ *
+ * browserify is needed for the use of require() in the browser
+ */
+const Mii = require('mii-js');
+const newMiiData = 'AwAAQOlVognnx0GC2qjhdwOzuI0n2QAAAGBzAHQAZQB2AGUAAAAAAAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAANeC';
// Prevent the user from reloading or leaving the page
window.onbeforeunload = function (e) {
@@ -32,33 +40,56 @@ window.addEventListener('resize', () => {
setCanvasScale();
});
-// MII RENDERER
+let mii; // global mii object
-const Mii = require('mii-js');
+// this initalizes a mii for editing
+// returns if mii data was parsed successfully
+function initializeMiiData(encodedUserMiiData) {
+ console.group('Initalizing Mii data');
+ console.log('encoded mii data:', encodedUserMiiData);
+
+ // We initialize the Mii object
+ try {
+ console.log('Attempting to parse mii data');
+ mii = new Mii(Buffer.from(encodedUserMiiData, 'base64'));
+ } catch (err) {
+ console.error('failed to decode mii data', err);
+ console.groupEnd();
+ return false;
+ }
+
+ // We set the img sources for the unedited miis in the save animation
+ console.log('grabbing rendered miis for later use');
+ const miiStudioNeutralUrl = mii.studioUrl({
+ width: 512,
+ bgColor: '13173300',
+ });
+ const miiStudioSorrowUrl = mii.studioUrl({
+ width: 512,
+ bgColor: '13173300',
+ expression: 'sorrow',
+ });
+ document.querySelector('.mii-comparison img.old-mii').src = miiStudioNeutralUrl;
+ document.querySelector('.mii-comparison.confirmed img.old-mii').src = miiStudioSorrowUrl;
+ console.log('initialization complete');
+ console.groupEnd();
+ return true;
+}
// The Mii data is stored in a script tag in the HTML, so we can just grab it and then remove the element
const encodedUserMiiData = document.querySelector(
'script#encodedUserMiiData'
).textContent;
document.querySelector('script#encodedUserMiiData').remove();
-console.log('encodedMiiData', encodedUserMiiData);
-// We initialize the Mii object
-const mii = new Mii(Buffer.from(encodedUserMiiData, 'base64'));
-
-// We set the img sources for the unedited miis in the save animation
-const miiStudioNeutralUrl = mii.studioUrl({
- width: 512,
- bgColor: '13173300',
-});
-const miiStudioSorrowUrl = mii.studioUrl({
- width: 512,
- bgColor: '13173300',
- expression: 'sorrow',
-});
-document.querySelector('.mii-comparison img.old-mii').src = miiStudioNeutralUrl;
-document.querySelector('.mii-comparison.confirmed img.old-mii').src =
- miiStudioSorrowUrl;
+// is valid mii data
+const validMiiData = initializeMiiData(encodedUserMiiData);
+if (!validMiiData) {
+ const shouldContinue = window.confirm('Found corrupted mii data, want to continue with a new Mii?');
+ if (!shouldContinue)
+ window.location.assign('/account');
+ initializeMiiData(newMiiData);
+}
// we keeep the images here so we can cache them when we need to change the build/height
const miiFaceImg = new Image();
@@ -444,8 +475,8 @@ document
const miiData = mii.encode().toString('base64');
const tokenType = document.cookie.split('; ').find(row => row.startsWith('token_type=')).split('=')[1];
const accessToken = document.cookie.split('; ').find(row => row.startsWith('access_token=')).split('=')[1];
-
- fetch('http://api.pretendo.cc/v1/user', {
+
+ fetch('https://api.pretendo.cc/v1/user', {
method: 'POST',
headers: {
'Accept': 'application/json',
diff --git a/views/account/account.handlebars b/views/account/account.handlebars
index 230d70c..0e629c6 100644
--- a/views/account/account.handlebars
+++ b/views/account/account.handlebars
@@ -1,8 +1,8 @@
-