Skip to content

Commit f6be635

Browse files
authored
feat(app): add validation for nikke_launcher checks
feat(app): add validation for nikke_launcher checks
2 parents 60766b4 + db542d2 commit f6be635

File tree

5 files changed

+158
-8
lines changed

5 files changed

+158
-8
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ node_modules/
99
npm-debug.log
1010
neutralinojs.log
1111
package-lock.json
12+
changelog.sh
13+
CHANGELOG.md
1214

1315
# Neutralinojs binaries and builds
1416
/bin

neutralino.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/neutralinojs/neutralinojs/main/schemas/neutralino.config.schema.json",
33
"applicationId": "neu.js.nikkepwned",
4-
"version": "0.1.2-alpha",
4+
"version": "0.1.3-alpha",
55
"applicationName": "NIKKEPwned",
66
"author": "ScathachGrip",
77
"description": "NIKKEPwned",
@@ -50,7 +50,7 @@
5050
"fullScreen": false,
5151
"alwaysOnTop": false,
5252
"icon": "/resources/icons/appIcon.png",
53-
"enableInspector": true,
53+
"enableInspector": false,
5454
"borderless": false,
5555
"maximize": false,
5656
"hidden": false,

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "nikkepwned",
33
"description": "Password Manager for NIKKE",
44
"funding": "https://github.com/sponsors/sinkaroid",
5-
"version": "0.1.2-alpha",
5+
"version": "0.1.3-alpha",
66
"scripts": {
77
"prebuild": "ts-node src/frontend.ts",
88
"build": "tsc",
@@ -33,6 +33,7 @@
3333
"typescript-eslint": "^8.24.1"
3434
},
3535
"dependencies": {
36-
"discord-rpc": "^4.0.1"
36+
"discord-rpc": "^4.0.1",
37+
"toastify-js": "^1.12.0"
3738
}
3839
}

src/app.ts

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,45 @@ class PwnedManager {
128128
console.warn("⚠️ WebSocket not ready.");
129129
}
130130
}
131+
132+
/**
133+
* Displays vanilla toast with a success or fail message.
134+
* This function updates the snackbar text, applies the correct styling,
135+
* and animates a progress bar that disappears after 3 seconds.
136+
*
137+
* @param {string} message - The message to display inside the snackbar.
138+
* @param {"success" | "fail"} type - Determines the appearance of the snackbar: green for success, red for fail.
139+
*
140+
* @returns {void} This function does not return a value.
141+
*/
142+
public showAlert(message: string, type: "success" | "fail"): void {
143+
const snackbar = document.getElementById("snackbar");
144+
const textElement = document.getElementById("snackbar-text");
145+
const progressBar = document.querySelector(".progress-bar") as HTMLElement;
146+
147+
if (!snackbar || !textElement || !progressBar) {
148+
console.error("Snackbar elements not found.");
149+
return;
150+
}
151+
152+
snackbar.className = `show ${type}`;
153+
154+
if (type === "success") {
155+
textElement.textContent = `✅ ${message}`;
156+
} else {
157+
textElement.textContent = `❌ ${message}`;
158+
}
159+
160+
progressBar.style.width = "0%";
161+
progressBar.style.transition = "none";
162+
void progressBar.offsetWidth;
163+
progressBar.style.transition = "width 3s linear";
164+
progressBar.style.width = "100%";
165+
166+
setTimeout(() => {
167+
snackbar.classList.remove("show", "success", "fail");
168+
}, 3000);
169+
}
131170
}
132171

133172
const accountManager = new PwnedManager();
@@ -177,6 +216,15 @@ Neutralino.events.on("ready", async () => {
177216
// eslint-disable-next-line @typescript-eslint/no-explicit-any
178217
} as unknown as any);
179218

219+
if (!file || file.length === 0) {
220+
console.warn("⚠️ No file selected.");
221+
return;
222+
}
223+
if (!file[0].includes("nikke_launcher.exe")) {
224+
await Neutralino.os.showNotification("Oops :/", "Please select nikke_launcher.exe", "ERROR");
225+
accountManager.showAlert("Please select nikke_launcher.exe", "fail");
226+
return;
227+
}
180228
if (file && file.length > 0) {
181229
launcherPath = file[0]; // Store selected path in global variable
182230
await Neutralino.storage.setData("nikkeLauncherPath", launcherPath);
@@ -186,6 +234,7 @@ Neutralino.events.on("ready", async () => {
186234
} catch (error) {
187235
console.error("Error selecting file:", error);
188236
await Neutralino.os.showNotification("Oops :/", "Failed to select file.", "ERROR");
237+
accountManager.showAlert("Failed to select file.", "fail");
189238
}
190239
});
191240

@@ -225,11 +274,12 @@ Neutralino.events.on("ready", async () => {
225274

226275
const updatedAccounts = Array.from(accountMap.values());
227276
await Neutralino.storage.setData("accounts", JSON.stringify(updatedAccounts));
228-
alert("✅ Accounts Registered!");
277+
accountManager.showAlert("Accounts Registered!", "success");
229278
await accountManager.loadAccounts();
230279
} catch (e) {
231280
console.error("Invalid JSON format!", e);
232281
await Neutralino.os.showNotification("Oops :/", "Invalid JSON format! Please correct it.", "ERROR");
282+
accountManager.showAlert("Invalid JSON format! Please correct it.", "fail");
233283
}
234284
});
235285

@@ -253,13 +303,14 @@ Neutralino.events.on("ready", async () => {
253303

254304
if (selectedIndex === "") {
255305
await Neutralino.os.showNotification(">:(", "Please select an account!", "ERROR");
306+
accountManager.showAlert("Please select an account!", "fail");
256307
return;
257308
}
258309

259310
try {
260311
const data = await Neutralino.storage.getData("accounts");
261312
if (!data) {
262-
alert("No accounts found! Register first.");
313+
accountManager.showAlert("No accounts found! Register first.", "fail");
263314
return;
264315
}
265316
const accounts = JSON.parse(data);
@@ -275,6 +326,7 @@ Neutralino.events.on("ready", async () => {
275326
await Neutralino.os.execCommand(`powershell -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.Windows.Forms; Start-Sleep -Seconds 5; [System.Windows.Forms.SendKeys]::SendWait('{TAB}${emailFixed}{TAB}${passwordFixed}{ENTER}')"`);
276327
console.log("✅ Login complete!");
277328
await Neutralino.os.showNotification(`${account.nickname} `, "Successfully logged in!");
329+
accountManager.showAlert(`Logged in as ${account.nickname}!`, "success");
278330

279331
accountManager.updateDiscordRPC(`Playing NIKKE ${currentArray} / ${accounts.length} accounts`, `Logged in as ${account.nickname}`);
280332
} catch (error) {
@@ -299,7 +351,8 @@ Neutralino.events.on("ready", async () => {
299351
(document.getElementById("removeBtn") as HTMLButtonElement).addEventListener("click", async () => {
300352
const selectedEmail = (document.getElementById("accountSelect") as HTMLSelectElement).value;
301353
if (!selectedEmail) {
302-
alert("Please select an account to remove.");
354+
accountManager.showAlert("Please select an account!", "fail");
355+
303356
return;
304357
}
305358

@@ -308,7 +361,7 @@ Neutralino.events.on("ready", async () => {
308361
const updatedAccounts = accounts.filter((acc: Account) => acc.email !== selectedEmail);
309362

310363
await Neutralino.storage.setData("accounts", JSON.stringify(updatedAccounts));
311-
alert(`❌ Account ${selectedEmail} removed!`);
364+
accountManager.showAlert(`Account ${selectedEmail} removed!`, "success");
312365
await accountManager.loadAccounts();
313366
});
314367
});

src/frontend.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,94 @@ select {
132132
overflow: hidden;
133133
text-overflow: ellipsis;
134134
}
135+
136+
137+
/* Base Snackbar container */
138+
#snackbar {
139+
visibility: hidden;
140+
max-width: 320px;
141+
color: #fff;
142+
text-align: left;
143+
border-radius: 8px;
144+
padding: 14px 16px;
145+
position: fixed;
146+
z-index: 1000;
147+
top: 20px;
148+
right: 20px;
149+
font-size: 14px;
150+
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
151+
display: flex;
152+
flex-direction: column;
153+
gap: 8px;
154+
opacity: 0;
155+
transform: translateY(-10px);
156+
transition: opacity 0.3s, transform 0.3s;
157+
}
158+
159+
/* Success Snackbar */
160+
#snackbar.success {
161+
background-color: #222; /* Dark gray */
162+
}
163+
164+
/* Fail Snackbar */
165+
#snackbar.fail {
166+
background-color:rgb(133, 12, 12); /* Red */
167+
}
168+
169+
/* Show Snackbar */
170+
#snackbar.show {
171+
visibility: visible;
172+
opacity: 1;
173+
transform: translateY(0);
174+
}
175+
176+
/* Snackbar Text */
177+
#snackbar-text {
178+
flex: 1;
179+
word-wrap: break-word;
180+
}
181+
182+
/* Loading Bar */
183+
.progress {
184+
height: 4px;
185+
width: 100%;
186+
background-color: rgba(255, 255, 255, 0.2);
187+
border-radius: 2px;
188+
overflow: hidden;
189+
position: relative;
190+
}
191+
192+
.progress-bar {
193+
height: 100%;
194+
width: 0%;
195+
position: absolute;
196+
left: 0;
197+
top: 0;
198+
}
199+
200+
/* Success Bar */
201+
#snackbar.success .progress-bar {
202+
background-color:rgb(145, 255, 0); /* Orange */
203+
}
204+
205+
/* Fail Bar */
206+
#snackbar.fail .progress-bar {
207+
background-color:rgb(166, 255, 0); /* Bright Red */
208+
}
209+
210+
/* Responsive: Adjust for small screens */
211+
@media (max-width: 600px) {
212+
#snackbar {
213+
max-width: 90%;
214+
right: 5%;
215+
left: auto;
216+
font-size: 13px;
217+
padding: 12px;
218+
}
219+
}
220+
221+
</style>
222+
135223
</style>
136224
</head>
137225
<body>
@@ -151,6 +239,12 @@ select {
151239
<br>
152240
<button id="removeBtn">or Remove account</button>
153241
</div>
242+
<div id="snackbar">
243+
<span id="snackbar-text"></span>
244+
<div class="progress"><div class="progress-bar"></div></div>
245+
</div>
246+
247+
154248
<p>Password Manager for NIKKE v<span id="appVersion">Loading...</span></p>
155249
<script src="js/neutralino.js"></script>
156250
<script src="js/app.js"></script>

0 commit comments

Comments
 (0)