Power+ Userscript Loader

An alternate, customizable loader for Power+

当前为 2022-01-14 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Power+ Userscript Loader
  3. // @namespace https://powerplus.app/
  4. // @version 1.1
  5. // @description An alternate, customizable loader for Power+
  6. // @author jottocraft
  7. // @license MIT
  8. // @icon https://powerplus.app/favicon.png
  9. // @grant none
  10. // @run-at document-start
  11. // @match https://*.instructure.com/power+*
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. var s;
  18.  
  19. //Check for light or dark theme
  20. var light = false;
  21. if (window.localStorage.fluidTheme == "light") {
  22. light = true;
  23. } else if (((window.localStorage.fluidTheme == "system") || (window.localStorage.fluidTheme == "auto")) && !window.matchMedia("(prefers-color-scheme: dark)").matches) {
  24. light = true;
  25. }
  26.  
  27. //Replace canvas 404 page with Power+
  28. const observer = new MutationObserver(mutations => {
  29. mutations.forEach(({ addedNodes }) => {
  30. addedNodes.forEach(node => {
  31. //Power+ preloader
  32. if (node.nodeType === 1 && node.tagName === 'BODY') {
  33. node.innerHTML = /*html*/`
  34. <div dtps="true" id="dtpsNativeOverlay" style="background-color: inherit; position: fixed; top: 0px; left: 0px; width: 100%; height: 100vh; z-index: 99;text-align: center;z-index: 999;transition: opacity 0.2s;">
  35. <img dtps="true" style="height: 100px; margin-top: 132px;" src="${light ? "https://i.imgur.com/0WzWwb1.png" : "https://i.imgur.com/7dDUVh2.png"}" />
  36. <br dtps="true" />
  37. <div dtps="true" class="progress"><div id="dtpsLoadingScreenBar" dtps="true" class="indeterminate"></div></div>
  38. <style dtps="true">body {background-color: ${light ? "white" : "#151515"}; --crxElements: ${light ? "#ececec" : "#2b2b2b"}; --crxText: ${light ? "#333" : "#efefef"}; overflow: hidden;}*,:after,:before{box-sizing:border-box}.progress{background:var(--crxElements);position:relative;width:600px;height:5px;overflow:hidden;border-radius:12px;backdrop-filter:opacity(.4);display:inline-block;margin-top:75px}.progress .indeterminate{position:absolute;background:#e3ba4b;height:5px;animation:indeterminate 1.4s infinite;animation-timing-function:linear}@keyframes indeterminate{0%{width:5%;left:-15%}to{width:100%;left:110%}}p{font-family:BlinkMacSystemFont,-apple-system,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif;color: var(--crxText);margin-top: 24px;}</style>
  39. </div>
  40. `;
  41. } else if (node.nodeType === 1 && node.tagName === 'HEAD') {
  42. node.innerHTML = /*html*/`
  43. <link dtps="true" rel="shortcut icon" href="https://powerplus.app/favicon.png" type="image/png">
  44. <meta dtps="true" name="viewport" content="width=device-width, initial-scale=1">
  45. <meta dtps="true" charset="utf-8">
  46. <title dtps="true">Power+</title>
  47. <meta dtps="true" name="description" content="A better UI for Canvas LMS">
  48. <meta dtps="true" name="author" content="jottocraft">
  49. `;
  50. } else if (node.nodeType === 1 && node.tagName === 'SCRIPT' && (node.textContent && node.textContent.includes('"current_user"'))) {
  51. //Do nothing for node containing enviornment data for faster load times
  52. } else if (node.nodeType === 1 && node.getAttribute("dtps") != "true") {
  53. //Node is not added by dtps
  54. node.remove();
  55. }
  56. })
  57. })
  58. })
  59.  
  60. //Start MutationObserver
  61. observer.observe(document.documentElement, {
  62. childList: true,
  63. subtree: true
  64. });
  65.  
  66. //Get Power+ base URL
  67. var baseURL = "https://powerplus.app";
  68. if (window.localStorage.dtpsLoaderPref == "dev") {
  69. baseURL = "https://dev.dtps.jottocraft.com";
  70. } else if (window.localStorage.githubRepo && (window.localStorage.dtpsLoaderPref == "github")) {
  71. baseURL = "https://jottocraft.github.io/" + window.localStorage.githubRepo;
  72. } else if (window.localStorage.externalReleaseURL && (window.localStorage.dtpsLoaderPref == "external")) {
  73. baseURL = window.localStorage.externalReleaseURL;
  74. } else if (window.localStorage.dtpsLoaderPref == "local") {
  75. baseURL = "http://localhost:2750";
  76. }
  77.  
  78. //Set DTPS loader parameters
  79. s = document.createElement("script");
  80. s.textContent = "window.dtpsPreLoader = true;window.dtpsBaseURL = '" + baseURL + "'";
  81. s.async = false;
  82. s.setAttribute("dtps", "true");
  83. document.documentElement.appendChild(s);
  84.  
  85. //Load jQuery
  86. s = document.createElement("script");
  87. s.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js";
  88. s.async = false;
  89. s.setAttribute("dtps", "true");
  90. document.documentElement.appendChild(s);
  91.  
  92. //Wait for page to load
  93. window.onload = function () {
  94. //Stop observer
  95. observer.disconnect();
  96.  
  97. //Determine LMS script to load
  98. var lmsScript = null;
  99. if (window.location.hostname.startsWith("dtechhs")) {
  100. lmsScript = "dtech";
  101. } else {
  102. lmsScript = "canvas";
  103. }
  104.  
  105. //Check for debugging LMS overrides
  106. if (window.localStorage.dtpsLMSOverride) lmsScript = window.localStorage.dtpsLMSOverride;
  107.  
  108. //Add script to DOM
  109. s = document.createElement("script");
  110. s.src = baseURL + "/scripts/lms/" + lmsScript + ".js";
  111. s.async = false;
  112. s.setAttribute("dtps", "true");
  113. document.documentElement.appendChild(s);
  114. s.onerror = function () {
  115. //Couldn't load debugging script, fallback to production
  116. if (window.localStorage.dtpsLoaderPref && (window.localStorage.dtpsLoaderPref !== "prod")) {
  117. console.log("[DTPS CHROME] Failed to load debugging script. Falling back to production.");
  118. window.localStorage.dtpsLoaderPref = "prod";
  119. window.location.reload();
  120. } else {
  121. document.getElementById("dtpsLoadingScreenBar").style.animationPlayState = "paused";
  122. document.getElementById("dtpsLoadingScreenStatus").innerText = "Could not load Power+. Please try again later.";
  123. }
  124. };
  125. }
  126. })();