xmoj-script 2.1.1 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/Update.json +22 -0
  2. package/XMOJ.user.js +89 -15
  3. package/package.json +1 -1
package/Update.json CHANGED
@@ -2980,6 +2980,28 @@
2980
2980
  }
2981
2981
  ],
2982
2982
  "Notes": "No release notes were provided for this release."
2983
+ },
2984
+ "2.1.2": {
2985
+ "UpdateDate": 1755589063111,
2986
+ "Prerelease": true,
2987
+ "UpdateContents": [
2988
+ {
2989
+ "PR": 834,
2990
+ "Description": "feat: use credential management api"
2991
+ }
2992
+ ],
2993
+ "Notes": "No release notes were provided for this release."
2994
+ },
2995
+ "2.1.3": {
2996
+ "UpdateDate": 1755596470421,
2997
+ "Prerelease": true,
2998
+ "UpdateContents": [
2999
+ {
3000
+ "PR": 835,
3001
+ "Description": "feat: add user-selectable theme"
3002
+ }
3003
+ ],
3004
+ "Notes": "No release notes were provided for this release."
2983
3005
  }
2984
3006
  }
2985
3007
  }
package/XMOJ.user.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // ==UserScript==
2
2
  // @name XMOJ
3
- // @version 2.1.1
3
+ // @version 2.1.3
4
4
  // @description XMOJ增强脚本
5
5
  // @author @XMOJ-Script-dev, @langningchen and the community
6
6
  // @namespace https://github/langningchen
@@ -441,6 +441,35 @@ let UtilityEnabled = (Name) => {
441
441
  }
442
442
  }
443
443
  };
444
+ let storeCredential = async (username, password) => {
445
+ if ('credentials' in navigator && window.PasswordCredential) {
446
+ try {
447
+ const credential = new PasswordCredential({ id: username, password: password });
448
+ await navigator.credentials.store(credential);
449
+ } catch (e) {
450
+ console.error(e);
451
+ }
452
+ }
453
+ };
454
+ let getCredential = async () => {
455
+ if ('credentials' in navigator && window.PasswordCredential) {
456
+ try {
457
+ return await navigator.credentials.get({ password: true, mediation: 'optional' });
458
+ } catch (e) {
459
+ console.error(e);
460
+ }
461
+ }
462
+ return null;
463
+ };
464
+ let clearCredential = async () => {
465
+ if ('credentials' in navigator && window.PasswordCredential) {
466
+ try {
467
+ await navigator.credentials.preventSilentAccess();
468
+ } catch (e) {
469
+ console.error(e);
470
+ }
471
+ }
472
+ };
444
473
  let RequestAPI = (Action, Data, CallBack) => {
445
474
  try {
446
475
  let Session = "";
@@ -523,6 +552,24 @@ let CurrentUsername = document.querySelector("#profile").innerText;
523
552
  CurrentUsername = CurrentUsername.replaceAll(/[^a-zA-Z0-9]/g, "");
524
553
  let IsAdmin = AdminUserList.indexOf(CurrentUsername) !== -1;
525
554
 
555
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
556
+ const applyTheme = (theme) => {
557
+ document.querySelector("html").setAttribute("data-bs-theme", theme);
558
+ localStorage.setItem("UserScript-Setting-DarkMode", theme === "dark" ? "true" : "false");
559
+ };
560
+ const applySystemTheme = (e) => applyTheme(e.matches ? "dark" : "light");
561
+ let initTheme = () => {
562
+ const saved = localStorage.getItem("UserScript-Setting-Theme") || "auto";
563
+ if (saved === "auto") {
564
+ applyTheme(prefersDark.matches ? "dark" : "light");
565
+ prefersDark.addEventListener("change", applySystemTheme);
566
+ } else {
567
+ applyTheme(saved);
568
+ prefersDark.removeEventListener("change", applySystemTheme);
569
+ }
570
+ };
571
+ initTheme();
572
+
526
573
 
527
574
  class NavbarStyler {
528
575
  constructor() {
@@ -962,8 +1009,7 @@ async function main() {
962
1009
  location.href = "https://www.xmoj.tech/modifypage.php?ByUserScript=1";
963
1010
  });
964
1011
  PopupUL.children[5].addEventListener("click", () => {
965
- localStorage.removeItem("UserScript-Username");
966
- localStorage.removeItem("UserScript-Password");
1012
+ clearCredential();
967
1013
  document.cookie = "PHPSESSID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"; //This is how you remove a cookie?
968
1014
  location.href = "https://www.xmoj.tech/logout.php";
969
1015
  });
@@ -1331,7 +1377,32 @@ async function main() {
1331
1377
  } else if (Data[i].Type == "D") {
1332
1378
  Row.classList.add("list-group-item-danger");
1333
1379
  }
1334
- if (Data[i].Children == undefined) {
1380
+ if (Data[i].ID == "Theme") {
1381
+ let Label = document.createElement("label");
1382
+ Label.classList.add("me-2");
1383
+ Label.htmlFor = "UserScript-Setting-Theme";
1384
+ Label.innerText = Data[i].Name;
1385
+ Row.appendChild(Label);
1386
+ let Select = document.createElement("select");
1387
+ Select.classList.add("form-select", "form-select-sm", "w-auto", "d-inline");
1388
+ Select.id = "UserScript-Setting-Theme";
1389
+ [
1390
+ ["light", "亮色"],
1391
+ ["dark", "暗色"],
1392
+ ["auto", "跟随系统"]
1393
+ ].forEach(opt => {
1394
+ let option = document.createElement("option");
1395
+ option.value = opt[0];
1396
+ option.innerText = opt[1];
1397
+ Select.appendChild(option);
1398
+ });
1399
+ Select.value = localStorage.getItem("UserScript-Setting-Theme") || "auto";
1400
+ Select.addEventListener("change", () => {
1401
+ localStorage.setItem("UserScript-Setting-Theme", Select.value);
1402
+ initTheme();
1403
+ });
1404
+ Row.appendChild(Select);
1405
+ } else if (Data[i].Children == undefined) {
1335
1406
  let CheckBox = document.createElement("input");
1336
1407
  CheckBox.classList.add("form-check-input");
1337
1408
  CheckBox.classList.add("me-1");
@@ -1389,7 +1460,7 @@ async function main() {
1389
1460
  }, {"ID": "ResetType", "Type": "F", "Name": "重新排版*"}, {
1390
1461
  "ID": "AddColorText", "Type": "A", "Name": "增加彩色文字"
1391
1462
  }, {"ID": "AddUnits", "Type": "A", "Name": "状态界面内存与耗时添加单位"}, {
1392
- "ID": "DarkMode", "Type": "A", "Name": "使用暗色模式"
1463
+ "ID": "Theme", "Type": "A", "Name": "界面主题"
1393
1464
  }, {"ID": "AddAnimation", "Type": "A", "Name": "增加动画"}, {
1394
1465
  "ID": "ReplaceYN", "Type": "F", "Name": "题目前状态提示替换为好看的图标"
1395
1466
  }, {"ID": "RemoveAlerts", "Type": "D", "Name": "去除多余反复的提示"}, {
@@ -3213,12 +3284,11 @@ async function main() {
3213
3284
  .then((Response) => {
3214
3285
  return Response.text();
3215
3286
  })
3216
- .then((Response) => {
3287
+ .then(async (Response) => {
3217
3288
  if (UtilityEnabled("LoginFailed")) {
3218
3289
  if (Response.indexOf("history.go(-2);") != -1) {
3219
3290
  if (UtilityEnabled("SavePassword")) {
3220
- localStorage.setItem("UserScript-Username", Username);
3221
- localStorage.setItem("UserScript-Password", Password);
3291
+ await storeCredential(Username, Password);
3222
3292
  }
3223
3293
  let NewPage = localStorage.getItem("UserScript-LastPage");
3224
3294
  if (NewPage == null) {
@@ -3227,8 +3297,7 @@ async function main() {
3227
3297
  location.href = NewPage;
3228
3298
  } else {
3229
3299
  if (UtilityEnabled("SavePassword")) {
3230
- localStorage.removeItem("UserScript-Username");
3231
- localStorage.removeItem("UserScript-Password");
3300
+ clearCredential();
3232
3301
  }
3233
3302
  Response = Response.substring(Response.indexOf("alert('") + 7);
3234
3303
  Response = Response.substring(0, Response.indexOf("');"));
@@ -3244,10 +3313,15 @@ async function main() {
3244
3313
  });
3245
3314
  }
3246
3315
  });
3247
- if (UtilityEnabled("SavePassword") && localStorage.getItem("UserScript-Username") != null && localStorage.getItem("UserScript-Password") != null) {
3248
- document.querySelector("#login > div:nth-child(1) > div > input").value = localStorage.getItem("UserScript-Username");
3249
- document.querySelector("#login > div:nth-child(2) > div > input").value = localStorage.getItem("UserScript-Password");
3250
- LoginButton.click();
3316
+ if (UtilityEnabled("SavePassword")) {
3317
+ (async () => {
3318
+ let Credential = await getCredential();
3319
+ if (Credential) {
3320
+ document.querySelector("#login > div:nth-child(1) > div > input").value = Credential.id;
3321
+ document.querySelector("#login > div:nth-child(2) > div > input").value = Credential.password;
3322
+ LoginButton.click();
3323
+ }
3324
+ })();
3251
3325
  }
3252
3326
  } else if (location.pathname == "/contest_video.php" || location.pathname == "/problem_video.php") {
3253
3327
  let ScriptData = document.querySelector("body > div > div.mt-3 > center > script").innerHTML;
@@ -3814,7 +3888,7 @@ int main()
3814
3888
  AddUser.disabled = true;
3815
3889
  RequestAPI("SendMail", {
3816
3890
  "ToUser": String(UsernameData),
3817
- "Content": String("您好,我是" + localStorage.getItem("UserScript-Username"))
3891
+ "Content": String("您好,我是" + CurrentUsername)
3818
3892
  }, (ResponseData) => {
3819
3893
  AddUser.children[0].style.display = "none";
3820
3894
  AddUser.disabled = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xmoj-script",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "an improvement script for xmoj.tech",
5
5
  "main": "AddonScript.js",
6
6
  "scripts": {